From 000b34aa61e240ed8b6b17d516080b551f81c999 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Tue, 2 Jul 2024 17:35:51 +0100 Subject: [PATCH 01/18] Create RISC-V group checking infrastructure --- test/regression/RegressionTest.cc | 70 ++++++++++++++++++- test/regression/RegressionTest.hh | 18 +++-- .../aarch64/AArch64RegressionTest.hh | 8 +++ test/regression/riscv/RISCVRegressionTest.cc | 18 +++++ test/regression/riscv/RISCVRegressionTest.hh | 11 +++ test/regression/riscv/SmokeTest.cc | 2 + 6 files changed, 120 insertions(+), 7 deletions(-) diff --git a/test/regression/RegressionTest.cc b/test/regression/RegressionTest.cc index d4bf8e3a42..97975a239f 100644 --- a/test/regression/RegressionTest.cc +++ b/test/regression/RegressionTest.cc @@ -21,6 +21,75 @@ void RegressionTest::TearDown() { } } +void RegressionTest::createArchitecture(const char* source, const char* triple, + const char* extensions) { + // Zero-out process memory from any prior runs + if (processMemory_ != nullptr) + std::memset(processMemory_, '\0', processMemorySize_); + + // Assemble the source to a flat binary + assemble(source, triple, extensions); + if (HasFatalFailure()) return; + + // Generate the predefined model config + generateConfig(); + + // Due to SimInfo being static, we need to ensure the config values/options + // stored are up-to-date with the latest generated config file + simeng::config::SimInfo::reBuild(); + + // Create a linux process from the assembled code block. + // Memory allocation for process images also takes place + // during linux process creation. The Elf binary is parsed + // and relevant sections are copied to the process image. + // The process image is finalised by the createStack method + // which creates and populates the initial process stack. + // The created process image can be accessed via a shared_ptr + // returned by the getProcessImage method. + process_ = std::make_unique( + simeng::span(reinterpret_cast(code_), codeSize_)); + + ASSERT_TRUE(process_->isValid()); + uint64_t entryPoint = process_->getEntryPoint(); + processMemorySize_ = process_->getProcessImageSize(); + // This instance of procImgPtr pointer needs to be shared because + // getMemoryValue in RegressionTest.hh uses reference to the class + // member processMemory_. + std::shared_ptr procImgPtr = process_->getProcessImage(); + processMemory_ = procImgPtr.get(); + + // Create memory interfaces for instruction and data access. + // For each memory interface, a dereferenced shared_ptr to the + // processImage is passed as argument. + simeng::memory::FlatMemoryInterface instructionMemory(processMemory_, + processMemorySize_); + + std::unique_ptr flatDataMemory = + std::make_unique(processMemory_, + processMemorySize_); + + std::unique_ptr + fixedLatencyDataMemory = + std::make_unique( + processMemory_, processMemorySize_, 4); + std::unique_ptr dataMemory; + + // Create the OS kernel and the process + simeng::kernel::Linux kernel( + simeng::config::SimInfo::getConfig()["CPU-Info"]["Special-File-Dir-Path"] + .as()); + kernel.createProcess(*process_); + + // Populate the heap with initial data (specified by the test being run). + ASSERT_LT(process_->getHeapStart() + initialHeapData_.size(), + process_->getInitialStackPointer()); + std::copy(initialHeapData_.begin(), initialHeapData_.end(), + processMemory_ + process_->getHeapStart()); + + // Create the architecture + architecture_ = createArchitecture(kernel); +} + void RegressionTest::run(const char* source, const char* triple, const char* extensions) { testing::internal::CaptureStdout(); @@ -90,7 +159,6 @@ void RegressionTest::run(const char* source, const char* triple, // Create the architecture architecture_ = createArchitecture(kernel); - // Create a port allocator for an out-of-order core std::unique_ptr portAllocator = createPortAllocator(); diff --git a/test/regression/RegressionTest.hh b/test/regression/RegressionTest.hh index 86c3252c29..f2e4d7cd86 100644 --- a/test/regression/RegressionTest.hh +++ b/test/regression/RegressionTest.hh @@ -71,6 +71,9 @@ class RegressionTest /** Generate a default YAML-formatted configuration. */ virtual void generateConfig() const = 0; + void createArchitecture(const char* source, const char* triple, + const char* extensions); + /** Run the assembly in `source`, building it for the target `triple` and ISA * extensions. */ void run(const char* source, const char* triple, const char* extensions); @@ -84,6 +87,9 @@ class RegressionTest ryml::ConstNodeRef config = simeng::config::SimInfo::getConfig()) const = 0; + virtual void checkGroup(const char* source, const int expectedGroup, + const char* extensions) = 0; + /** Get the value of an architectural register. */ template T getRegister(simeng::Register reg) const { @@ -135,14 +141,14 @@ class RegressionTest /** True if the test program finished running. */ bool programFinished_ = false; - private: - /** Assemble test source to a flat binary for the given triple and ISA - * extensions. */ - void assemble(const char* source, const char* triple, const char* extensions); + /** The size of the assembled flat binary in bytes. */ + size_t codeSize_ = 0; /** The flat binary produced by assembling the test source. */ uint8_t* code_ = nullptr; - /** The size of the assembled flat binary in bytes. */ - size_t codeSize_ = 0; + private: + /** Assemble test source to a flat binary for the given triple and ISA + * extensions. */ + void assemble(const char* source, const char* triple, const char* extensions); }; diff --git a/test/regression/aarch64/AArch64RegressionTest.hh b/test/regression/aarch64/AArch64RegressionTest.hh index 70507408b8..c54124f7ed 100644 --- a/test/regression/aarch64/AArch64RegressionTest.hh +++ b/test/regression/aarch64/AArch64RegressionTest.hh @@ -189,6 +189,14 @@ inline std::vector> genCoreTypeSVLPairs( checkMatrixRegisterCol(tag, index, __VA_ARGS__); \ } +#define EXPECT_GROUP(source, expectedGroup) \ + { \ + std::string sourceWithTerminator = source; \ + sourceWithTerminator += "\n.word 0"; \ + checkGroup(sourceWithTerminator.c_str(), expectedGroup, "+m,+a,+f,+d,+c"); \ + } \ + if (HasFatalFailure()) return + /** The test fixture for all AArch64 regression tests. */ class AArch64RegressionTest : public RegressionTest { protected: diff --git a/test/regression/riscv/RISCVRegressionTest.cc b/test/regression/riscv/RISCVRegressionTest.cc index a75f182fff..fec770ab7a 100644 --- a/test/regression/riscv/RISCVRegressionTest.cc +++ b/test/regression/riscv/RISCVRegressionTest.cc @@ -3,6 +3,7 @@ #include "simeng/arch/riscv/Architecture.hh" #include "simeng/pipeline/BalancedPortAllocator.hh" +using MacroOp = std::vector>; using namespace simeng::arch::riscv; void RISCVRegressionTest::run(const char* source, const char* extensions) { @@ -60,3 +61,20 @@ RISCVRegressionTest::createPortAllocator(ryml::ConstNodeRef config) const { return std::make_unique( portArrangement); } + +void RISCVRegressionTest::checkGroup(const char* source, + const int expectedGroup, + const char* extensions) { + // Initialise LLVM + LLVMInitializeRISCVTargetInfo(); + LLVMInitializeRISCVTargetMC(); + LLVMInitializeRISCVAsmParser(); + + RegressionTest::createArchitecture(source, "riscv64", extensions); + + MacroOp out; + architecture_->predecode(code_, 4, 0, out); + + auto group = out[0]->getGroup(); + EXPECT_EQ(group, expectedGroup); +} diff --git a/test/regression/riscv/RISCVRegressionTest.hh b/test/regression/riscv/RISCVRegressionTest.hh index 56f8f1bcdd..4a478842e0 100644 --- a/test/regression/riscv/RISCVRegressionTest.hh +++ b/test/regression/riscv/RISCVRegressionTest.hh @@ -81,6 +81,14 @@ inline std::string paramToString( } \ if (HasFatalFailure()) return +#define EXPECT_GROUP(source, expectedGroup) \ + { \ + std::string sourceWithTerminator = source; \ + sourceWithTerminator += "\n.word 0"; \ + checkGroup(sourceWithTerminator.c_str(), expectedGroup, "+m,+a,+f,+d"); \ + } \ + if (HasFatalFailure()) return + /** The test fixture for all RISCV regression tests. */ class RISCVRegressionTest : public RegressionTest { protected: @@ -89,6 +97,9 @@ class RISCVRegressionTest : public RegressionTest { /** Run the assembly code in `source`. */ void run(const char* source, const char* extensions); + void checkGroup(const char* source, const int expectedGroup, + const char* extensions) override; + /** Generate a default YAML-formatted configuration. */ void generateConfig() const override; diff --git a/test/regression/riscv/SmokeTest.cc b/test/regression/riscv/SmokeTest.cc index ee5676d0c0..ac7b20916b 100644 --- a/test/regression/riscv/SmokeTest.cc +++ b/test/regression/riscv/SmokeTest.cc @@ -3,6 +3,7 @@ namespace { using SmokeTest = RISCVRegressionTest; +using namespace simeng::arch::riscv; // Test that a trivial instruction will execute TEST_P(SmokeTest, instruction) { @@ -10,6 +11,7 @@ TEST_P(SmokeTest, instruction) { addi a5,a5,32 )"); EXPECT_EQ(getGeneralRegister(15), 32u); + EXPECT_GROUP(R"(addi a5,a5,32)", InstructionGroups::INT_SIMPLE_ARTH); } INSTANTIATE_TEST_SUITE_P( From 43ef17fd8df5956a1236bd661d8891bb942b0155 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Wed, 3 Jul 2024 14:55:01 +0100 Subject: [PATCH 02/18] Add infrastructure for AArch64 --- .../aarch64/AArch64RegressionTest.cc | 24 +++++++++++++++++++ .../aarch64/AArch64RegressionTest.hh | 5 +++- test/regression/aarch64/SmokeTest.cc | 3 +++ test/regression/riscv/RISCVRegressionTest.hh | 12 +++++----- 4 files changed, 37 insertions(+), 7 deletions(-) diff --git a/test/regression/aarch64/AArch64RegressionTest.cc b/test/regression/aarch64/AArch64RegressionTest.cc index ffe9f60fd3..66cc24244c 100644 --- a/test/regression/aarch64/AArch64RegressionTest.cc +++ b/test/regression/aarch64/AArch64RegressionTest.cc @@ -3,6 +3,7 @@ #include "simeng/arch/aarch64/Architecture.hh" #include "simeng/pipeline/BalancedPortAllocator.hh" +using MacroOp = std::vector>; using namespace simeng::arch::aarch64; void AArch64RegressionTest::run(const char* source) { @@ -84,3 +85,26 @@ bool AArch64RegressionTest::getCarryFlag() const { bool AArch64RegressionTest::getOverflowFlag() const { return (getNZCV() >> 0) & 1; } + +void AArch64RegressionTest::checkGroup( + const char* source, const int expectedGroup, + const char* extensions) { // Initialise LLVM + LLVMInitializeAArch64TargetInfo(); + LLVMInitializeAArch64TargetMC(); + LLVMInitializeAArch64AsmParser(); + + const char* subtargetFeatures; +#if SIMENG_LLVM_VERSION < 14 + subtargetFeatures = "+sve,+lse"; +#else + subtargetFeatures = "+sve,+lse,+sve2,+sme,+sme-f64"; +#endif + + RegressionTest::createArchitecture(source, "aarch64", subtargetFeatures); + + MacroOp out; + architecture_->predecode(code_, 4, 0, out); + + auto group = out[0]->getGroup(); + EXPECT_EQ(group, expectedGroup); +} diff --git a/test/regression/aarch64/AArch64RegressionTest.hh b/test/regression/aarch64/AArch64RegressionTest.hh index c54124f7ed..3d67ea6bf1 100644 --- a/test/regression/aarch64/AArch64RegressionTest.hh +++ b/test/regression/aarch64/AArch64RegressionTest.hh @@ -193,7 +193,7 @@ inline std::vector> genCoreTypeSVLPairs( { \ std::string sourceWithTerminator = source; \ sourceWithTerminator += "\n.word 0"; \ - checkGroup(sourceWithTerminator.c_str(), expectedGroup, "+m,+a,+f,+d,+c"); \ + checkGroup(sourceWithTerminator.c_str(), expectedGroup, ""); \ } \ if (HasFatalFailure()) return @@ -205,6 +205,9 @@ class AArch64RegressionTest : public RegressionTest { /** Run the assembly code in `source`. */ void run(const char* source); + void checkGroup(const char* source, const int expectedGroup, + const char* extensions) override; + /** Generate a default YAML-formatted configuration. */ void generateConfig() const override; diff --git a/test/regression/aarch64/SmokeTest.cc b/test/regression/aarch64/SmokeTest.cc index a3a04d6164..da214bfae8 100644 --- a/test/regression/aarch64/SmokeTest.cc +++ b/test/regression/aarch64/SmokeTest.cc @@ -3,6 +3,7 @@ namespace { using SmokeTest = AArch64RegressionTest; +using namespace simeng::arch::aarch64; // Test that a trivial instruction will execute TEST_P(SmokeTest, instruction) { @@ -10,6 +11,8 @@ TEST_P(SmokeTest, instruction) { orr x0, xzr, #7 )"); EXPECT_EQ(getGeneralRegister(0), 7u); + EXPECT_GROUP(R"(orr x0, xzr, #7)", + InstructionGroups::INT_SIMPLE_LOGICAL_NOSHIFT); } // Test a loop executing 1024 times, adding 3 to w1 each time diff --git a/test/regression/riscv/RISCVRegressionTest.hh b/test/regression/riscv/RISCVRegressionTest.hh index 4a478842e0..957803032c 100644 --- a/test/regression/riscv/RISCVRegressionTest.hh +++ b/test/regression/riscv/RISCVRegressionTest.hh @@ -81,12 +81,12 @@ inline std::string paramToString( } \ if (HasFatalFailure()) return -#define EXPECT_GROUP(source, expectedGroup) \ - { \ - std::string sourceWithTerminator = source; \ - sourceWithTerminator += "\n.word 0"; \ - checkGroup(sourceWithTerminator.c_str(), expectedGroup, "+m,+a,+f,+d"); \ - } \ +#define EXPECT_GROUP(source, expectedGroup) \ + { \ + std::string sourceWithTerminator = source; \ + sourceWithTerminator += "\n.word 0"; \ + checkGroup(sourceWithTerminator.c_str(), expectedGroup, "+m,+a,+f,+d,+c"); \ + } \ if (HasFatalFailure()) return /** The test fixture for all RISCV regression tests. */ From a6b9506370677a0581b161ef84461b9487b3cf6d Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Wed, 3 Jul 2024 15:01:29 +0100 Subject: [PATCH 03/18] Cleanup --- test/regression/RegressionTest.cc | 1 + test/regression/RegressionTest.hh | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/test/regression/RegressionTest.cc b/test/regression/RegressionTest.cc index 97975a239f..1e8e6fec05 100644 --- a/test/regression/RegressionTest.cc +++ b/test/regression/RegressionTest.cc @@ -159,6 +159,7 @@ void RegressionTest::run(const char* source, const char* triple, // Create the architecture architecture_ = createArchitecture(kernel); + // Create a port allocator for an out-of-order core std::unique_ptr portAllocator = createPortAllocator(); diff --git a/test/regression/RegressionTest.hh b/test/regression/RegressionTest.hh index f2e4d7cd86..3b4894be49 100644 --- a/test/regression/RegressionTest.hh +++ b/test/regression/RegressionTest.hh @@ -141,9 +141,6 @@ class RegressionTest /** True if the test program finished running. */ bool programFinished_ = false; - /** The size of the assembled flat binary in bytes. */ - size_t codeSize_ = 0; - /** The flat binary produced by assembling the test source. */ uint8_t* code_ = nullptr; @@ -151,4 +148,7 @@ class RegressionTest /** Assemble test source to a flat binary for the given triple and ISA * extensions. */ void assemble(const char* source, const char* triple, const char* extensions); + + /** The size of the assembled flat binary in bytes. */ + size_t codeSize_ = 0; }; From 035aa07d4b4ccea468b044223b975e523b583147 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Wed, 3 Jul 2024 18:12:49 +0100 Subject: [PATCH 04/18] Add support for micro-ops --- test/regression/RegressionTest.hh | 3 ++- .../aarch64/AArch64RegressionTest.cc | 23 ++++++++++++++++--- .../aarch64/AArch64RegressionTest.hh | 15 ++++++------ test/regression/aarch64/MicroOperation.cc | 5 ++++ test/regression/riscv/RISCVRegressionTest.cc | 12 +++++++--- test/regression/riscv/RISCVRegressionTest.hh | 6 ++--- 6 files changed, 47 insertions(+), 17 deletions(-) diff --git a/test/regression/RegressionTest.hh b/test/regression/RegressionTest.hh index 3b4894be49..75cfff1e46 100644 --- a/test/regression/RegressionTest.hh +++ b/test/regression/RegressionTest.hh @@ -87,7 +87,8 @@ class RegressionTest ryml::ConstNodeRef config = simeng::config::SimInfo::getConfig()) const = 0; - virtual void checkGroup(const char* source, const int expectedGroup, + virtual void checkGroup(const char* source, + const std::vector expectedGroups, const char* extensions) = 0; /** Get the value of an architectural register. */ diff --git a/test/regression/aarch64/AArch64RegressionTest.cc b/test/regression/aarch64/AArch64RegressionTest.cc index 66cc24244c..df12b2a853 100644 --- a/test/regression/aarch64/AArch64RegressionTest.cc +++ b/test/regression/aarch64/AArch64RegressionTest.cc @@ -87,7 +87,7 @@ bool AArch64RegressionTest::getOverflowFlag() const { } void AArch64RegressionTest::checkGroup( - const char* source, const int expectedGroup, + const char* source, const std::vector expectedGroups, const char* extensions) { // Initialise LLVM LLVMInitializeAArch64TargetInfo(); LLVMInitializeAArch64TargetMC(); @@ -102,9 +102,26 @@ void AArch64RegressionTest::checkGroup( RegressionTest::createArchitecture(source, "aarch64", subtargetFeatures); + // TODO give out better name as this shows in the print out. Apply to RISC-V + // also MacroOp out; architecture_->predecode(code_, 4, 0, out); - auto group = out[0]->getGroup(); - EXPECT_EQ(group, expectedGroup); + // TODO doesn't stop execution so for loop below could access out of bounds + // memory Check that there is one expectation group per micro-op + EXPECT_EQ(out.size(), expectedGroups.size()); + + // std::cout << expectedGroups.size() << std::endl; + // for (auto ent : expectedGroups) { + // std::cout << ent << ","; + // } + // std::cout << "" << std::endl; + + // Check each + for (size_t i = 0; i < out.size(); i++) { + auto group = out[i]->getGroup(); + // std::cout << "actual group " << group << std::endl; + + EXPECT_EQ(group, expectedGroups[i]); + } } diff --git a/test/regression/aarch64/AArch64RegressionTest.hh b/test/regression/aarch64/AArch64RegressionTest.hh index 3d67ea6bf1..922a4da1bf 100644 --- a/test/regression/aarch64/AArch64RegressionTest.hh +++ b/test/regression/aarch64/AArch64RegressionTest.hh @@ -189,12 +189,13 @@ inline std::vector> genCoreTypeSVLPairs( checkMatrixRegisterCol(tag, index, __VA_ARGS__); \ } -#define EXPECT_GROUP(source, expectedGroup) \ - { \ - std::string sourceWithTerminator = source; \ - sourceWithTerminator += "\n.word 0"; \ - checkGroup(sourceWithTerminator.c_str(), expectedGroup, ""); \ - } \ +#define EXPECT_GROUP(source, ...) \ + { \ + std::string sourceWithTerminator = source; \ + sourceWithTerminator += "\n.word 0"; \ + checkGroup(sourceWithTerminator.c_str(), {__VA_ARGS__}, \ + ""); \ + } \ if (HasFatalFailure()) return /** The test fixture for all AArch64 regression tests. */ @@ -205,7 +206,7 @@ class AArch64RegressionTest : public RegressionTest { /** Run the assembly code in `source`. */ void run(const char* source); - void checkGroup(const char* source, const int expectedGroup, + void checkGroup(const char* source, const std::vector expectedGroups, const char* extensions) override; /** Generate a default YAML-formatted configuration. */ diff --git a/test/regression/aarch64/MicroOperation.cc b/test/regression/aarch64/MicroOperation.cc index 2cd14b1d10..ceca4744e0 100644 --- a/test/regression/aarch64/MicroOperation.cc +++ b/test/regression/aarch64/MicroOperation.cc @@ -10,6 +10,7 @@ namespace { using MicroOp = AArch64RegressionTest; +using namespace simeng::arch::aarch64; TEST_P(MicroOp, ld1Two) { initialHeapData_.resize(32); @@ -292,6 +293,10 @@ TEST_P(MicroOp, loadPairD) { CHECK_NEON(6, double, {-3.0}); CHECK_NEON(7, double, {1.0}); CHECK_NEON(8, double, {-1.0}); + + EXPECT_GROUP(R"(ldp d1, d2, [x0], #16)", InstructionGroups::LOAD_SCALAR, + InstructionGroups::LOAD_SCALAR, + InstructionGroups::INT_SIMPLE_ARTH_NOSHIFT); } TEST_P(MicroOp, loadPairQ) { diff --git a/test/regression/riscv/RISCVRegressionTest.cc b/test/regression/riscv/RISCVRegressionTest.cc index fec770ab7a..4a047fc9c4 100644 --- a/test/regression/riscv/RISCVRegressionTest.cc +++ b/test/regression/riscv/RISCVRegressionTest.cc @@ -63,7 +63,7 @@ RISCVRegressionTest::createPortAllocator(ryml::ConstNodeRef config) const { } void RISCVRegressionTest::checkGroup(const char* source, - const int expectedGroup, + const std::vector expectedGroups, const char* extensions) { // Initialise LLVM LLVMInitializeRISCVTargetInfo(); @@ -75,6 +75,12 @@ void RISCVRegressionTest::checkGroup(const char* source, MacroOp out; architecture_->predecode(code_, 4, 0, out); - auto group = out[0]->getGroup(); - EXPECT_EQ(group, expectedGroup); + // Check that there is one expectation group per micro-op + EXPECT_EQ(out.size(), expectedGroups.size()); + + // Check each + for (size_t i = 0; i < out.size(); i++) { + auto group = out[i]->getGroup(); + EXPECT_EQ(group, expectedGroups[i]); + } } diff --git a/test/regression/riscv/RISCVRegressionTest.hh b/test/regression/riscv/RISCVRegressionTest.hh index 957803032c..68ee64ef5e 100644 --- a/test/regression/riscv/RISCVRegressionTest.hh +++ b/test/regression/riscv/RISCVRegressionTest.hh @@ -81,11 +81,11 @@ inline std::string paramToString( } \ if (HasFatalFailure()) return -#define EXPECT_GROUP(source, expectedGroup) \ +#define EXPECT_GROUP(source, ...) \ { \ std::string sourceWithTerminator = source; \ sourceWithTerminator += "\n.word 0"; \ - checkGroup(sourceWithTerminator.c_str(), expectedGroup, "+m,+a,+f,+d,+c"); \ + checkGroup(sourceWithTerminator.c_str(), {__VA_ARGS__}, "+m,+a,+f,+d,+c"); \ } \ if (HasFatalFailure()) return @@ -97,7 +97,7 @@ class RISCVRegressionTest : public RegressionTest { /** Run the assembly code in `source`. */ void run(const char* source, const char* extensions); - void checkGroup(const char* source, const int expectedGroup, + void checkGroup(const char* source, const std::vector expectedGroups, const char* extensions) override; /** Generate a default YAML-formatted configuration. */ From 68f7b325bbaacac20fbc8e31bcf9745c82e090f3 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Mon, 8 Jul 2024 13:50:58 +0100 Subject: [PATCH 05/18] Remove repeated code --- test/regression/RegressionTest.cc | 156 +++++++----------- test/regression/RegressionTest.hh | 68 +++++--- .../aarch64/AArch64RegressionTest.cc | 33 ++-- .../aarch64/AArch64RegressionTest.hh | 15 +- test/regression/riscv/RISCVRegressionTest.cc | 13 +- test/regression/riscv/RISCVRegressionTest.hh | 2 +- 6 files changed, 132 insertions(+), 155 deletions(-) diff --git a/test/regression/RegressionTest.cc b/test/regression/RegressionTest.cc index 1e8e6fec05..4d4ee87529 100644 --- a/test/regression/RegressionTest.cc +++ b/test/regression/RegressionTest.cc @@ -21,79 +21,23 @@ void RegressionTest::TearDown() { } } -void RegressionTest::createArchitecture(const char* source, const char* triple, - const char* extensions) { - // Zero-out process memory from any prior runs - if (processMemory_ != nullptr) - std::memset(processMemory_, '\0', processMemorySize_); - - // Assemble the source to a flat binary - assemble(source, triple, extensions); - if (HasFatalFailure()) return; - - // Generate the predefined model config - generateConfig(); - - // Due to SimInfo being static, we need to ensure the config values/options - // stored are up-to-date with the latest generated config file - simeng::config::SimInfo::reBuild(); - - // Create a linux process from the assembled code block. - // Memory allocation for process images also takes place - // during linux process creation. The Elf binary is parsed - // and relevant sections are copied to the process image. - // The process image is finalised by the createStack method - // which creates and populates the initial process stack. - // The created process image can be accessed via a shared_ptr - // returned by the getProcessImage method. - process_ = std::make_unique( - simeng::span(reinterpret_cast(code_), codeSize_)); - - ASSERT_TRUE(process_->isValid()); - uint64_t entryPoint = process_->getEntryPoint(); - processMemorySize_ = process_->getProcessImageSize(); - // This instance of procImgPtr pointer needs to be shared because - // getMemoryValue in RegressionTest.hh uses reference to the class - // member processMemory_. - std::shared_ptr procImgPtr = process_->getProcessImage(); - processMemory_ = procImgPtr.get(); - +void RegressionTest::instantiateMemoryInterfaces() { // Create memory interfaces for instruction and data access. // For each memory interface, a dereferenced shared_ptr to the // processImage is passed as argument. - simeng::memory::FlatMemoryInterface instructionMemory(processMemory_, - processMemorySize_); + instructionMemory_ = std::make_unique( + processMemory_, processMemorySize_); - std::unique_ptr flatDataMemory = - std::make_unique(processMemory_, - processMemorySize_); + flatDataMemory_ = std::make_unique( + processMemory_, processMemorySize_); - std::unique_ptr - fixedLatencyDataMemory = - std::make_unique( - processMemory_, processMemorySize_, 4); - std::unique_ptr dataMemory; - - // Create the OS kernel and the process - simeng::kernel::Linux kernel( - simeng::config::SimInfo::getConfig()["CPU-Info"]["Special-File-Dir-Path"] - .as()); - kernel.createProcess(*process_); - - // Populate the heap with initial data (specified by the test being run). - ASSERT_LT(process_->getHeapStart() + initialHeapData_.size(), - process_->getInitialStackPointer()); - std::copy(initialHeapData_.begin(), initialHeapData_.end(), - processMemory_ + process_->getHeapStart()); - - // Create the architecture - architecture_ = createArchitecture(kernel); + fixedLatencyDataMemory_ = + std::make_unique( + processMemory_, processMemorySize_, 4); } -void RegressionTest::run(const char* source, const char* triple, - const char* extensions) { - testing::internal::CaptureStdout(); - +void RegressionTest::createProcess(const char* source, const char* triple, + const char* extensions) { // Zero-out process memory from any prior runs if (processMemory_ != nullptr) std::memset(processMemory_, '\0', processMemorySize_); @@ -121,51 +65,53 @@ void RegressionTest::run(const char* source, const char* triple, simeng::span(reinterpret_cast(code_), codeSize_)); ASSERT_TRUE(process_->isValid()); - uint64_t entryPoint = process_->getEntryPoint(); + entryPoint_ = process_->getEntryPoint(); processMemorySize_ = process_->getProcessImageSize(); // This instance of procImgPtr pointer needs to be shared because // getMemoryValue in RegressionTest.hh uses reference to the class // member processMemory_. std::shared_ptr procImgPtr = process_->getProcessImage(); processMemory_ = procImgPtr.get(); +} - // Create memory interfaces for instruction and data access. - // For each memory interface, a dereferenced shared_ptr to the - // processImage is passed as argument. - simeng::memory::FlatMemoryInterface instructionMemory(processMemory_, - processMemorySize_); - - std::unique_ptr flatDataMemory = - std::make_unique(processMemory_, - processMemorySize_); - - std::unique_ptr - fixedLatencyDataMemory = - std::make_unique( - processMemory_, processMemorySize_, 4); - std::unique_ptr dataMemory; +void RegressionTest::createKernel(const char* source, const char* triple, + const char* extensions) { + createProcess(source, triple, extensions); // Create the OS kernel and the process - simeng::kernel::Linux kernel( + kernel_ = std::make_unique( simeng::config::SimInfo::getConfig()["CPU-Info"]["Special-File-Dir-Path"] .as()); - kernel.createProcess(*process_); + kernel_->createProcess(*process_); + // TODO ensure performing this before kernel_.createProcess is ok // Populate the heap with initial data (specified by the test being run). ASSERT_LT(process_->getHeapStart() + initialHeapData_.size(), process_->getInitialStackPointer()); std::copy(initialHeapData_.begin(), initialHeapData_.end(), processMemory_ + process_->getHeapStart()); +} + +// TODO potential rename +void RegressionTest::createArchitecture(const char* source, const char* triple, + const char* extensions) { + // Create kernel and process + createKernel(source, triple, extensions); // Create the architecture - architecture_ = createArchitecture(kernel); + architecture_ = instantiateArchitecture(*kernel_); +} + +// TODO rename ~createSystem +void RegressionTest::createCore(const char* source, const char* triple, + const char* extensions) { + // Create the architecture, kernel and process + createArchitecture(source, triple, extensions); // Create a port allocator for an out-of-order core - std::unique_ptr portAllocator = - createPortAllocator(); + portAllocator_ = createPortAllocator(); // Create a branch predictor for a pipelined core - std::unique_ptr predictor_ = nullptr; std::string predictorType = simeng::config::SimInfo::getConfig()["Branch-Predictor"]["Type"] .as(); @@ -175,34 +121,44 @@ void RegressionTest::run(const char* source, const char* triple, predictor_ = std::make_unique(); } + instantiateMemoryInterfaces(); + // Create the core model switch (std::get<0>(GetParam())) { case EMULATION: core_ = std::make_unique( - instructionMemory, *flatDataMemory, entryPoint, processMemorySize_, - *architecture_); - dataMemory = std::move(flatDataMemory); + *instructionMemory_, *flatDataMemory_, entryPoint_, + processMemorySize_, *architecture_); + dataMemory_ = std::move(flatDataMemory_); break; case INORDER: core_ = std::make_unique( - instructionMemory, *flatDataMemory, processMemorySize_, entryPoint, - *architecture_, *predictor_); - dataMemory = std::move(flatDataMemory); + *instructionMemory_, *flatDataMemory_, processMemorySize_, + entryPoint_, *architecture_, *predictor_); + dataMemory_ = std::move(flatDataMemory_); break; case OUTOFORDER: core_ = std::make_unique( - instructionMemory, *fixedLatencyDataMemory, processMemorySize_, - entryPoint, *architecture_, *predictor_, *portAllocator); - dataMemory = std::move(fixedLatencyDataMemory); + *instructionMemory_, *fixedLatencyDataMemory_, processMemorySize_, + entryPoint_, *architecture_, *predictor_, *portAllocator_); + dataMemory_ = std::move(fixedLatencyDataMemory_); break; } +} + +void RegressionTest::run(const char* source, const char* triple, + const char* extensions) { + testing::internal::CaptureStdout(); + + // Create the core, memory interfaces, kernel and process + createCore(source, triple, extensions); // Run the core model until the program is complete - while (!core_->hasHalted() || dataMemory->hasPendingRequests()) { + while (!core_->hasHalted() || dataMemory_->hasPendingRequests()) { ASSERT_LT(numTicks_, maxTicks_) << "Maximum tick count exceeded."; core_->tick(); - instructionMemory.tick(); - dataMemory->tick(); + instructionMemory_->tick(); + dataMemory_->tick(); numTicks_++; } diff --git a/test/regression/RegressionTest.hh b/test/regression/RegressionTest.hh index 75cfff1e46..d637602f19 100644 --- a/test/regression/RegressionTest.hh +++ b/test/regression/RegressionTest.hh @@ -79,7 +79,7 @@ class RegressionTest void run(const char* source, const char* triple, const char* extensions); /** Create an ISA instance from a kernel. */ - virtual std::unique_ptr createArchitecture( + virtual std::unique_ptr instantiateArchitecture( simeng::kernel::Linux& kernel) const = 0; /** Create a port allocator for an out-of-order core model. */ @@ -87,6 +87,9 @@ class RegressionTest ryml::ConstNodeRef config = simeng::config::SimInfo::getConfig()) const = 0; + // TODO could make this none virtual (prevent AArch64 from needing to pass + // empty extensions param), but this forces all ISA's to implement it which is + // probably preferable virtual void checkGroup(const char* source, const std::vector expectedGroups, const char* extensions) = 0; @@ -115,41 +118,66 @@ class RegressionTest /** The initial data to populate the heap with. */ std::vector initialHeapData_; - /** The maximum number of ticks to run before aborting the test. */ - uint64_t maxTicks_ = UINT64_MAX; - - /** The number of ticks that were run before the test program completed. */ - uint64_t numTicks_ = 0; - - /** The architecture instance. */ - std::unique_ptr architecture_; - - /** The process memory. */ - char* processMemory_ = nullptr; - - /** The size of the process memory in bytes. */ - size_t processMemorySize_ = 0; - /** The process that was executed. */ std::unique_ptr process_; - /** The core that was used. */ - std::unique_ptr core_ = nullptr; + /** The process memory. */ + char* processMemory_ = nullptr; /** The output written to stdout during the test. */ std::string stdout_; - /** True if the test program finished running. */ - bool programFinished_ = false; + /** The architecture instance. */ + std::unique_ptr architecture_; + + /** The number of ticks that were run before the test program completed. */ + uint64_t numTicks_ = 0; /** The flat binary produced by assembling the test source. */ uint8_t* code_ = nullptr; + /** The maximum number of ticks to run before aborting the test. */ + uint64_t maxTicks_ = UINT64_MAX; + private: /** Assemble test source to a flat binary for the given triple and ISA * extensions. */ void assemble(const char* source, const char* triple, const char* extensions); + void createProcess(const char* source, const char* triple, + const char* extensions); + + void createKernel(const char* source, const char* triple, + const char* extensions); + + void instantiateMemoryInterfaces(); + + std::unique_ptr instructionMemory_ = nullptr; + std::unique_ptr flatDataMemory_ = nullptr; + std::unique_ptr fixedLatencyDataMemory_ = + nullptr; + std::unique_ptr dataMemory_ = nullptr; + + void createCore(const char* source, const char* triple, + const char* extensions); + + std::unique_ptr kernel_ = nullptr; + + std::unique_ptr portAllocator_ = nullptr; + + std::unique_ptr predictor_ = nullptr; + + /** The core that was used. */ + std::unique_ptr core_ = nullptr; + + /** The size of the process memory in bytes. */ + size_t processMemorySize_ = 0; + + /** True if the test program finished running. */ + bool programFinished_ = false; + /** The size of the assembled flat binary in bytes. */ size_t codeSize_ = 0; + + uint64_t entryPoint_ = 0; }; diff --git a/test/regression/aarch64/AArch64RegressionTest.cc b/test/regression/aarch64/AArch64RegressionTest.cc index df12b2a853..2c9f96304d 100644 --- a/test/regression/aarch64/AArch64RegressionTest.cc +++ b/test/regression/aarch64/AArch64RegressionTest.cc @@ -48,7 +48,8 @@ void AArch64RegressionTest::generateConfig() const { } std::unique_ptr -AArch64RegressionTest::createArchitecture(simeng::kernel::Linux& kernel) const { +AArch64RegressionTest::instantiateArchitecture( + simeng::kernel::Linux& kernel) const { return std::make_unique(kernel); } @@ -86,9 +87,10 @@ bool AArch64RegressionTest::getOverflowFlag() const { return (getNZCV() >> 0) & 1; } -void AArch64RegressionTest::checkGroup( - const char* source, const std::vector expectedGroups, - const char* extensions) { // Initialise LLVM +void AArch64RegressionTest::checkGroup(const char* source, + const std::vector expectedGroups, + const char* extensions) { + // Initialise LLVM LLVMInitializeAArch64TargetInfo(); LLVMInitializeAArch64TargetMC(); LLVMInitializeAArch64AsmParser(); @@ -102,26 +104,17 @@ void AArch64RegressionTest::checkGroup( RegressionTest::createArchitecture(source, "aarch64", subtargetFeatures); - // TODO give out better name as this shows in the print out. Apply to RISC-V - // also - MacroOp out; - architecture_->predecode(code_, 4, 0, out); + MacroOp macroOp; + architecture_->predecode(code_, 4, 0, macroOp); // TODO doesn't stop execution so for loop below could access out of bounds - // memory Check that there is one expectation group per micro-op - EXPECT_EQ(out.size(), expectedGroups.size()); - - // std::cout << expectedGroups.size() << std::endl; - // for (auto ent : expectedGroups) { - // std::cout << ent << ","; - // } - // std::cout << "" << std::endl; + // memory + // Check that there is one expectation group per micro-op + EXPECT_EQ(macroOp.size(), expectedGroups.size()); // Check each - for (size_t i = 0; i < out.size(); i++) { - auto group = out[i]->getGroup(); - // std::cout << "actual group " << group << std::endl; - + for (size_t i = 0; i < macroOp.size(); i++) { + auto group = macroOp[i]->getGroup(); EXPECT_EQ(group, expectedGroups[i]); } } diff --git a/test/regression/aarch64/AArch64RegressionTest.hh b/test/regression/aarch64/AArch64RegressionTest.hh index 922a4da1bf..472481c649 100644 --- a/test/regression/aarch64/AArch64RegressionTest.hh +++ b/test/regression/aarch64/AArch64RegressionTest.hh @@ -189,13 +189,12 @@ inline std::vector> genCoreTypeSVLPairs( checkMatrixRegisterCol(tag, index, __VA_ARGS__); \ } -#define EXPECT_GROUP(source, ...) \ - { \ - std::string sourceWithTerminator = source; \ - sourceWithTerminator += "\n.word 0"; \ - checkGroup(sourceWithTerminator.c_str(), {__VA_ARGS__}, \ - ""); \ - } \ +#define EXPECT_GROUP(source, ...) \ + { \ + std::string sourceWithTerminator = source; \ + sourceWithTerminator += "\n.word 0"; \ + checkGroup(sourceWithTerminator.c_str(), {__VA_ARGS__}, ""); \ + } \ if (HasFatalFailure()) return /** The test fixture for all AArch64 regression tests. */ @@ -213,7 +212,7 @@ class AArch64RegressionTest : public RegressionTest { void generateConfig() const override; /** Create an ISA instance from a kernel. */ - virtual std::unique_ptr createArchitecture( + virtual std::unique_ptr instantiateArchitecture( simeng::kernel::Linux& kernel) const override; /** Create a port allocator for an out-of-order core model. */ diff --git a/test/regression/riscv/RISCVRegressionTest.cc b/test/regression/riscv/RISCVRegressionTest.cc index 4a047fc9c4..7b767ba4cc 100644 --- a/test/regression/riscv/RISCVRegressionTest.cc +++ b/test/regression/riscv/RISCVRegressionTest.cc @@ -42,7 +42,8 @@ void RISCVRegressionTest::generateConfig() const { } std::unique_ptr -RISCVRegressionTest::createArchitecture(simeng::kernel::Linux& kernel) const { +RISCVRegressionTest::instantiateArchitecture( + simeng::kernel::Linux& kernel) const { return std::make_unique(kernel); } @@ -72,15 +73,15 @@ void RISCVRegressionTest::checkGroup(const char* source, RegressionTest::createArchitecture(source, "riscv64", extensions); - MacroOp out; - architecture_->predecode(code_, 4, 0, out); + MacroOp macroOp; + architecture_->predecode(code_, 4, 0, macroOp); // Check that there is one expectation group per micro-op - EXPECT_EQ(out.size(), expectedGroups.size()); + EXPECT_EQ(macroOp.size(), expectedGroups.size()); // Check each - for (size_t i = 0; i < out.size(); i++) { - auto group = out[i]->getGroup(); + for (size_t i = 0; i < macroOp.size(); i++) { + auto group = macroOp[i]->getGroup(); EXPECT_EQ(group, expectedGroups[i]); } } diff --git a/test/regression/riscv/RISCVRegressionTest.hh b/test/regression/riscv/RISCVRegressionTest.hh index 68ee64ef5e..9c7ede8b2e 100644 --- a/test/regression/riscv/RISCVRegressionTest.hh +++ b/test/regression/riscv/RISCVRegressionTest.hh @@ -104,7 +104,7 @@ class RISCVRegressionTest : public RegressionTest { void generateConfig() const override; /** Create an ISA instance from a kernel. */ - virtual std::unique_ptr createArchitecture( + virtual std::unique_ptr instantiateArchitecture( simeng::kernel::Linux& kernel) const override; /** Get the value of a general purpose register. */ From 4eefca71303915731cb3caeccbdc6257ed1b7c32 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Mon, 8 Jul 2024 14:53:42 +0100 Subject: [PATCH 06/18] Add comments --- test/regression/RegressionTest.cc | 67 ++++++++++--------- test/regression/RegressionTest.hh | 45 +++++++++---- .../aarch64/AArch64RegressionTest.cc | 4 +- .../aarch64/AArch64RegressionTest.hh | 9 +++ test/regression/riscv/RISCVRegressionTest.cc | 2 +- test/regression/riscv/RISCVRegressionTest.hh | 15 ++++- 6 files changed, 92 insertions(+), 50 deletions(-) diff --git a/test/regression/RegressionTest.cc b/test/regression/RegressionTest.cc index 4d4ee87529..814567bc55 100644 --- a/test/regression/RegressionTest.cc +++ b/test/regression/RegressionTest.cc @@ -21,21 +21,6 @@ void RegressionTest::TearDown() { } } -void RegressionTest::instantiateMemoryInterfaces() { - // Create memory interfaces for instruction and data access. - // For each memory interface, a dereferenced shared_ptr to the - // processImage is passed as argument. - instructionMemory_ = std::make_unique( - processMemory_, processMemorySize_); - - flatDataMemory_ = std::make_unique( - processMemory_, processMemorySize_); - - fixedLatencyDataMemory_ = - std::make_unique( - processMemory_, processMemorySize_, 4); -} - void RegressionTest::createProcess(const char* source, const char* triple, const char* extensions) { // Zero-out process memory from any prior runs @@ -72,27 +57,30 @@ void RegressionTest::createProcess(const char* source, const char* triple, // member processMemory_. std::shared_ptr procImgPtr = process_->getProcessImage(); processMemory_ = procImgPtr.get(); + + // TODO ensure performing this before kernel_.createProcess is ok - Think it's + // fine + // Populate the heap with initial data (specified by the test being run). + ASSERT_LT(process_->getHeapStart() + initialHeapData_.size(), + process_->getInitialStackPointer()); + std::copy(initialHeapData_.begin(), initialHeapData_.end(), + processMemory_ + process_->getHeapStart()); } void RegressionTest::createKernel(const char* source, const char* triple, const char* extensions) { + // Create the process to pass to the kernel createProcess(source, triple, extensions); + ASSERT_TRUE(process_ != nullptr); + // Create the OS kernel and the process kernel_ = std::make_unique( simeng::config::SimInfo::getConfig()["CPU-Info"]["Special-File-Dir-Path"] .as()); kernel_->createProcess(*process_); - - // TODO ensure performing this before kernel_.createProcess is ok - // Populate the heap with initial data (specified by the test being run). - ASSERT_LT(process_->getHeapStart() + initialHeapData_.size(), - process_->getInitialStackPointer()); - std::copy(initialHeapData_.begin(), initialHeapData_.end(), - processMemory_ + process_->getHeapStart()); } -// TODO potential rename void RegressionTest::createArchitecture(const char* source, const char* triple, const char* extensions) { // Create kernel and process @@ -102,15 +90,30 @@ void RegressionTest::createArchitecture(const char* source, const char* triple, architecture_ = instantiateArchitecture(*kernel_); } -// TODO rename ~createSystem -void RegressionTest::createCore(const char* source, const char* triple, - const char* extensions) { +void RegressionTest::instantiateMemoryInterfaces() { + // Create memory interfaces for instruction and data access. + // For each memory interface, a dereferenced shared_ptr to the + // processImage is passed as argument. + + ASSERT_TRUE(processMemory_ != nullptr); + + instructionMemory_ = std::make_unique( + processMemory_, processMemorySize_); + + flatDataMemory_ = std::make_unique( + processMemory_, processMemorySize_); + + fixedLatencyDataMemory_ = + std::make_unique( + processMemory_, processMemorySize_, 4); +} + +void RegressionTest::instantiateSimulationObjects(const char* source, + const char* triple, + const char* extensions) { // Create the architecture, kernel and process createArchitecture(source, triple, extensions); - // Create a port allocator for an out-of-order core - portAllocator_ = createPortAllocator(); - // Create a branch predictor for a pipelined core std::string predictorType = simeng::config::SimInfo::getConfig()["Branch-Predictor"]["Type"] @@ -121,6 +124,7 @@ void RegressionTest::createCore(const char* source, const char* triple, predictor_ = std::make_unique(); } + // Create all possible memory interfaces instantiateMemoryInterfaces(); // Create the core model @@ -138,6 +142,9 @@ void RegressionTest::createCore(const char* source, const char* triple, dataMemory_ = std::move(flatDataMemory_); break; case OUTOFORDER: + // Create a port allocator for an out-of-order core + portAllocator_ = createPortAllocator(); + core_ = std::make_unique( *instructionMemory_, *fixedLatencyDataMemory_, processMemorySize_, entryPoint_, *architecture_, *predictor_, *portAllocator_); @@ -151,7 +158,7 @@ void RegressionTest::run(const char* source, const char* triple, testing::internal::CaptureStdout(); // Create the core, memory interfaces, kernel and process - createCore(source, triple, extensions); + instantiateSimulationObjects(source, triple, extensions); // Run the core model until the program is complete while (!core_->hasHalted() || dataMemory_->hasPendingRequests()) { diff --git a/test/regression/RegressionTest.hh b/test/regression/RegressionTest.hh index d637602f19..71a0b15f53 100644 --- a/test/regression/RegressionTest.hh +++ b/test/regression/RegressionTest.hh @@ -71,6 +71,7 @@ class RegressionTest /** Generate a default YAML-formatted configuration. */ virtual void generateConfig() const = 0; + /** Instantiate the architecture object using the kernel */ void createArchitecture(const char* source, const char* triple, const char* extensions); @@ -90,6 +91,9 @@ class RegressionTest // TODO could make this none virtual (prevent AArch64 from needing to pass // empty extensions param), but this forces all ISA's to implement it which is // probably preferable + + /** Predecode the first instruction in source and check the assigned group + * matches the expectation */ virtual void checkGroup(const char* source, const std::vector expectedGroups, const char* extensions) = 0; @@ -127,46 +131,60 @@ class RegressionTest /** The output written to stdout during the test. */ std::string stdout_; - /** The architecture instance. */ - std::unique_ptr architecture_; + /** The flat binary produced by assembling the test source. */ + uint8_t* code_ = nullptr; /** The number of ticks that were run before the test program completed. */ uint64_t numTicks_ = 0; - /** The flat binary produced by assembling the test source. */ - uint8_t* code_ = nullptr; - /** The maximum number of ticks to run before aborting the test. */ uint64_t maxTicks_ = UINT64_MAX; + /** The architecture instance. */ + std::unique_ptr architecture_; + private: /** Assemble test source to a flat binary for the given triple and ISA * extensions. */ void assemble(const char* source, const char* triple, const char* extensions); + /** Instantiate the process from the source bytes for the given architecture. + */ void createProcess(const char* source, const char* triple, const char* extensions); + /** Instantiate the kernel object using the process. */ void createKernel(const char* source, const char* triple, const char* extensions); + /** Instantiate the memory interfaces. */ void instantiateMemoryInterfaces(); - std::unique_ptr instructionMemory_ = nullptr; - std::unique_ptr flatDataMemory_ = nullptr; - std::unique_ptr fixedLatencyDataMemory_ = - nullptr; - std::unique_ptr dataMemory_ = nullptr; - - void createCore(const char* source, const char* triple, - const char* extensions); + /** Instantiating all of the objects used to setup and run the simulation. */ + void instantiateSimulationObjects(const char* source, const char* triple, + const char* extensions); + /* Instantiation of the kernel. */ std::unique_ptr kernel_ = nullptr; + /* Instantiation of the port allocator. */ std::unique_ptr portAllocator_ = nullptr; + /* Instantiation of the branch predictor. */ std::unique_ptr predictor_ = nullptr; + /** All possible data memory interfaces. dataMemory_ set to one of these + * depending on core type */ + std::unique_ptr flatDataMemory_ = nullptr; + std::unique_ptr fixedLatencyDataMemory_ = + nullptr; + + /** The data memory interface used during the test. */ + std::unique_ptr dataMemory_ = nullptr; + + /** The instruction memory interface used during the test. */ + std::unique_ptr instructionMemory_ = nullptr; + /** The core that was used. */ std::unique_ptr core_ = nullptr; @@ -179,5 +197,6 @@ class RegressionTest /** The size of the assembled flat binary in bytes. */ size_t codeSize_ = 0; + /** The entry point of the process. */ uint64_t entryPoint_ = 0; }; diff --git a/test/regression/aarch64/AArch64RegressionTest.cc b/test/regression/aarch64/AArch64RegressionTest.cc index 2c9f96304d..ff70f75906 100644 --- a/test/regression/aarch64/AArch64RegressionTest.cc +++ b/test/regression/aarch64/AArch64RegressionTest.cc @@ -107,12 +107,10 @@ void AArch64RegressionTest::checkGroup(const char* source, MacroOp macroOp; architecture_->predecode(code_, 4, 0, macroOp); - // TODO doesn't stop execution so for loop below could access out of bounds - // memory // Check that there is one expectation group per micro-op EXPECT_EQ(macroOp.size(), expectedGroups.size()); - // Check each + // Check the assigned and expected group for each micro-op match for (size_t i = 0; i < macroOp.size(); i++) { auto group = macroOp[i]->getGroup(); EXPECT_EQ(group, expectedGroups[i]); diff --git a/test/regression/aarch64/AArch64RegressionTest.hh b/test/regression/aarch64/AArch64RegressionTest.hh index 472481c649..69aaf06772 100644 --- a/test/regression/aarch64/AArch64RegressionTest.hh +++ b/test/regression/aarch64/AArch64RegressionTest.hh @@ -189,6 +189,13 @@ inline std::vector> genCoreTypeSVLPairs( checkMatrixRegisterCol(tag, index, __VA_ARGS__); \ } +/** A helper macro to predecode the first instruction in a snippet of Armv9.2-a + * assembly code and check the assigned group(s) for each micro-op matches the + * expected group(s). Returns from the calling function if a fatal error occurs. + * Four bytes containing zeros are appended to the source to ensure that the + * program will terminate with an unallocated instruction encoding exception + * instead of running into the heap. + */ #define EXPECT_GROUP(source, ...) \ { \ std::string sourceWithTerminator = source; \ @@ -205,6 +212,8 @@ class AArch64RegressionTest : public RegressionTest { /** Run the assembly code in `source`. */ void run(const char* source); + /** Run the first instruction in source through predecode and check the + * groups. */ void checkGroup(const char* source, const std::vector expectedGroups, const char* extensions) override; diff --git a/test/regression/riscv/RISCVRegressionTest.cc b/test/regression/riscv/RISCVRegressionTest.cc index 7b767ba4cc..fb1b4c4f40 100644 --- a/test/regression/riscv/RISCVRegressionTest.cc +++ b/test/regression/riscv/RISCVRegressionTest.cc @@ -79,7 +79,7 @@ void RISCVRegressionTest::checkGroup(const char* source, // Check that there is one expectation group per micro-op EXPECT_EQ(macroOp.size(), expectedGroups.size()); - // Check each + // Check the assigned and expected group for each micro-op match for (size_t i = 0; i < macroOp.size(); i++) { auto group = macroOp[i]->getGroup(); EXPECT_EQ(group, expectedGroups[i]); diff --git a/test/regression/riscv/RISCVRegressionTest.hh b/test/regression/riscv/RISCVRegressionTest.hh index 9c7ede8b2e..15dfc381cb 100644 --- a/test/regression/riscv/RISCVRegressionTest.hh +++ b/test/regression/riscv/RISCVRegressionTest.hh @@ -53,7 +53,7 @@ inline std::string paramToString( return coreString; } -/** A helper macro to run a snippet of RISCV assembly code, returning from +/** A helper macro to run a snippet of RISC-V assembly code, returning from * the calling function if a fatal error occurs. Four bytes containing zeros * are appended to the source to ensure that the program will terminate with * an unallocated instruction encoding exception instead of running into the @@ -66,7 +66,7 @@ inline std::string paramToString( } \ if (HasFatalFailure()) return -/** A helper macro to run a snippet of RISCV assembly code, returning from +/** A helper macro to run a snippet of RISC-V assembly code, returning from * the calling function if a fatal error occurs. Four bytes containing zeros * are appended to the source to ensure that the program will terminate with * an illegal instruction exception instead of running into the heap. This @@ -81,6 +81,13 @@ inline std::string paramToString( } \ if (HasFatalFailure()) return +/** A helper macro to predecode the first instruction in a snippet of RISC-V + * assembly code and check the assigned group(s) for each micro-op matches the + * expected group(s). Returns from the calling function if a fatal error occurs. + * Four bytes containing zeros are appended to the source to ensure that the + * program will terminate with an unallocated instruction encoding exception + * instead of running into the heap. + */ #define EXPECT_GROUP(source, ...) \ { \ std::string sourceWithTerminator = source; \ @@ -89,7 +96,7 @@ inline std::string paramToString( } \ if (HasFatalFailure()) return -/** The test fixture for all RISCV regression tests. */ +/** The test fixture for all RISC-V regression tests. */ class RISCVRegressionTest : public RegressionTest { protected: virtual ~RISCVRegressionTest() {} @@ -97,6 +104,8 @@ class RISCVRegressionTest : public RegressionTest { /** Run the assembly code in `source`. */ void run(const char* source, const char* extensions); + /** Run the first instruction in source through predecode and check the + * groups. */ void checkGroup(const char* source, const std::vector expectedGroups, const char* extensions) override; From 7642a52c7d406e4b531838edee91d16420ef64a8 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Mon, 8 Jul 2024 15:43:22 +0100 Subject: [PATCH 07/18] Further reduce redundant code --- test/regression/RegressionTest.cc | 18 +++++ test/regression/RegressionTest.hh | 6 +- .../aarch64/AArch64RegressionTest.cc | 56 ++++---------- .../aarch64/AArch64RegressionTest.hh | 31 ++++++-- test/regression/riscv/RISCVRegressionTest.cc | 43 ++++------- test/regression/riscv/RISCVRegressionTest.hh | 73 ++++++++++++++----- 6 files changed, 124 insertions(+), 103 deletions(-) diff --git a/test/regression/RegressionTest.cc b/test/regression/RegressionTest.cc index 814567bc55..5d12b9aa78 100644 --- a/test/regression/RegressionTest.cc +++ b/test/regression/RegressionTest.cc @@ -175,6 +175,24 @@ void RegressionTest::run(const char* source, const char* triple, programFinished_ = true; } +void RegressionTest::checkGroup(const char* source, const char* triple, + const char* extensions, + const std::vector expectedGroups) { + createArchitecture(source, triple, extensions); + + std::vector> macroOp; + architecture_->predecode(code_, 4, 0, macroOp); + + // Check that there is one expectation group per micro-op + EXPECT_EQ(macroOp.size(), expectedGroups.size()); + + // Check the assigned and expected group for each micro-op match + for (size_t i = 0; i < macroOp.size(); i++) { + auto group = macroOp[i]->getGroup(); + EXPECT_EQ(group, expectedGroups[i]); + } +} + void RegressionTest::assemble(const char* source, const char* triple, const char* extensions) { // Get LLVM target diff --git a/test/regression/RegressionTest.hh b/test/regression/RegressionTest.hh index 71a0b15f53..d88fa1e6e9 100644 --- a/test/regression/RegressionTest.hh +++ b/test/regression/RegressionTest.hh @@ -94,9 +94,9 @@ class RegressionTest /** Predecode the first instruction in source and check the assigned group * matches the expectation */ - virtual void checkGroup(const char* source, - const std::vector expectedGroups, - const char* extensions) = 0; + void checkGroup(const char* source, const char* triple, + const char* extensions, + const std::vector expectedGroups); /** Get the value of an architectural register. */ template diff --git a/test/regression/aarch64/AArch64RegressionTest.cc b/test/regression/aarch64/AArch64RegressionTest.cc index ff70f75906..d78e297d53 100644 --- a/test/regression/aarch64/AArch64RegressionTest.cc +++ b/test/regression/aarch64/AArch64RegressionTest.cc @@ -7,19 +7,19 @@ using MacroOp = std::vector>; using namespace simeng::arch::aarch64; void AArch64RegressionTest::run(const char* source) { - // Initialise LLVM - LLVMInitializeAArch64TargetInfo(); - LLVMInitializeAArch64TargetMC(); - LLVMInitializeAArch64AsmParser(); - - const char* subtargetFeatures; -#if SIMENG_LLVM_VERSION < 14 - subtargetFeatures = "+sve,+lse"; -#else - subtargetFeatures = "+sve,+lse,+sve2,+sme,+sme-f64"; -#endif - - RegressionTest::run(source, "aarch64", subtargetFeatures); + initialiseLLVM(); + std::string subtargetFeatures = getSubtargetFeaturesString(); + + RegressionTest::run(source, "aarch64", subtargetFeatures.c_str()); +} + +void AArch64RegressionTest::checkGroup(const char* source, + const std::vector expectedGroups) { + initialiseLLVM(); + std::string subtargetFeatures = getSubtargetFeaturesString(); + + RegressionTest::checkGroup(source, "aarch64", subtargetFeatures.c_str(), + expectedGroups); } void AArch64RegressionTest::generateConfig() const { @@ -86,33 +86,3 @@ bool AArch64RegressionTest::getCarryFlag() const { bool AArch64RegressionTest::getOverflowFlag() const { return (getNZCV() >> 0) & 1; } - -void AArch64RegressionTest::checkGroup(const char* source, - const std::vector expectedGroups, - const char* extensions) { - // Initialise LLVM - LLVMInitializeAArch64TargetInfo(); - LLVMInitializeAArch64TargetMC(); - LLVMInitializeAArch64AsmParser(); - - const char* subtargetFeatures; -#if SIMENG_LLVM_VERSION < 14 - subtargetFeatures = "+sve,+lse"; -#else - subtargetFeatures = "+sve,+lse,+sve2,+sme,+sme-f64"; -#endif - - RegressionTest::createArchitecture(source, "aarch64", subtargetFeatures); - - MacroOp macroOp; - architecture_->predecode(code_, 4, 0, macroOp); - - // Check that there is one expectation group per micro-op - EXPECT_EQ(macroOp.size(), expectedGroups.size()); - - // Check the assigned and expected group for each micro-op match - for (size_t i = 0; i < macroOp.size(); i++) { - auto group = macroOp[i]->getGroup(); - EXPECT_EQ(group, expectedGroups[i]); - } -} diff --git a/test/regression/aarch64/AArch64RegressionTest.hh b/test/regression/aarch64/AArch64RegressionTest.hh index 69aaf06772..5e346040db 100644 --- a/test/regression/aarch64/AArch64RegressionTest.hh +++ b/test/regression/aarch64/AArch64RegressionTest.hh @@ -196,12 +196,12 @@ inline std::vector> genCoreTypeSVLPairs( * program will terminate with an unallocated instruction encoding exception * instead of running into the heap. */ -#define EXPECT_GROUP(source, ...) \ - { \ - std::string sourceWithTerminator = source; \ - sourceWithTerminator += "\n.word 0"; \ - checkGroup(sourceWithTerminator.c_str(), {__VA_ARGS__}, ""); \ - } \ +#define EXPECT_GROUP(source, ...) \ + { \ + std::string sourceWithTerminator = source; \ + sourceWithTerminator += "\n.word 0"; \ + checkGroup(sourceWithTerminator.c_str(), {__VA_ARGS__}); \ + } \ if (HasFatalFailure()) return /** The test fixture for all AArch64 regression tests. */ @@ -214,8 +214,7 @@ class AArch64RegressionTest : public RegressionTest { /** Run the first instruction in source through predecode and check the * groups. */ - void checkGroup(const char* source, const std::vector expectedGroups, - const char* extensions) override; + void checkGroup(const char* source, const std::vector expectedGroups); /** Generate a default YAML-formatted configuration. */ void generateConfig() const override; @@ -229,6 +228,22 @@ class AArch64RegressionTest : public RegressionTest { ryml::ConstNodeRef config = simeng::config::SimInfo::getConfig()) const override; + /** Initialise LLVM */ + void initialiseLLVM() { + LLVMInitializeAArch64TargetInfo(); + LLVMInitializeAArch64TargetMC(); + LLVMInitializeAArch64AsmParser(); + } + + /** Get the subtarget feature string based on LLVM version being used */ + std::string getSubtargetFeaturesString() { +#if SIMENG_LLVM_VERSION < 14 + return "+sve,+lse"; +#else + return "+sve,+lse,+sve2,+sme,+sme-f64"; +#endif + } + /** Check the elements of a Neon register. * * This should be invoked via the `CHECK_NEON` macro in order to provide diff --git a/test/regression/riscv/RISCVRegressionTest.cc b/test/regression/riscv/RISCVRegressionTest.cc index fb1b4c4f40..ceb703e8ad 100644 --- a/test/regression/riscv/RISCVRegressionTest.cc +++ b/test/regression/riscv/RISCVRegressionTest.cc @@ -6,13 +6,21 @@ using MacroOp = std::vector>; using namespace simeng::arch::riscv; -void RISCVRegressionTest::run(const char* source, const char* extensions) { - // Initialise LLVM - LLVMInitializeRISCVTargetInfo(); - LLVMInitializeRISCVTargetMC(); - LLVMInitializeRISCVAsmParser(); +void RISCVRegressionTest::run(const char* source, bool compressed) { + initialiseLLVM(); + std::string subtargetFeatures = getSubtargetFeaturesString(compressed); - RegressionTest::run(source, "riscv64", extensions); + RegressionTest::run(source, "riscv64", subtargetFeatures.c_str()); +} + +void RISCVRegressionTest::checkGroup(const char* source, + const std::vector expectedGroups, + bool compressed) { + initialiseLLVM(); + std::string subtargetFeatures = getSubtargetFeaturesString(compressed); + + RegressionTest::checkGroup(source, "riscv64", subtargetFeatures.c_str(), + expectedGroups); } void RISCVRegressionTest::generateConfig() const { @@ -62,26 +70,3 @@ RISCVRegressionTest::createPortAllocator(ryml::ConstNodeRef config) const { return std::make_unique( portArrangement); } - -void RISCVRegressionTest::checkGroup(const char* source, - const std::vector expectedGroups, - const char* extensions) { - // Initialise LLVM - LLVMInitializeRISCVTargetInfo(); - LLVMInitializeRISCVTargetMC(); - LLVMInitializeRISCVAsmParser(); - - RegressionTest::createArchitecture(source, "riscv64", extensions); - - MacroOp macroOp; - architecture_->predecode(code_, 4, 0, macroOp); - - // Check that there is one expectation group per micro-op - EXPECT_EQ(macroOp.size(), expectedGroups.size()); - - // Check the assigned and expected group for each micro-op match - for (size_t i = 0; i < macroOp.size(); i++) { - auto group = macroOp[i]->getGroup(); - EXPECT_EQ(group, expectedGroups[i]); - } -} diff --git a/test/regression/riscv/RISCVRegressionTest.hh b/test/regression/riscv/RISCVRegressionTest.hh index 15dfc381cb..529693f8c4 100644 --- a/test/regression/riscv/RISCVRegressionTest.hh +++ b/test/regression/riscv/RISCVRegressionTest.hh @@ -58,12 +58,12 @@ inline std::string paramToString( * are appended to the source to ensure that the program will terminate with * an unallocated instruction encoding exception instead of running into the * heap. */ -#define RUN_RISCV(source) \ - { \ - std::string sourceWithTerminator = source; \ - sourceWithTerminator += "\n.word 0"; \ - run(sourceWithTerminator.c_str(), "+m,+a,+f,+d"); \ - } \ +#define RUN_RISCV(source) \ + { \ + std::string sourceWithTerminator = source; \ + sourceWithTerminator += "\n.word 0"; \ + run(sourceWithTerminator.c_str(), false); \ + } \ if (HasFatalFailure()) return /** A helper macro to run a snippet of RISC-V assembly code, returning from @@ -73,12 +73,12 @@ inline std::string paramToString( * specifically targets the compressed extension allowing for the RUN_RISCV * macro to ignore it, otherwise LLVM eagerly emits compressed instructions for * non-compressed assembly. */ -#define RUN_RISCV_COMP(source) \ - { \ - std::string sourceWithTerminator = source; \ - sourceWithTerminator += "\n.word 0"; \ - run(sourceWithTerminator.c_str(), "+m,+a,+f,+d,+c"); \ - } \ +#define RUN_RISCV_COMP(source) \ + { \ + std::string sourceWithTerminator = source; \ + sourceWithTerminator += "\n.word 0"; \ + run(sourceWithTerminator.c_str(), true); \ + } \ if (HasFatalFailure()) return /** A helper macro to predecode the first instruction in a snippet of RISC-V @@ -88,12 +88,28 @@ inline std::string paramToString( * program will terminate with an unallocated instruction encoding exception * instead of running into the heap. */ -#define EXPECT_GROUP(source, ...) \ - { \ - std::string sourceWithTerminator = source; \ - sourceWithTerminator += "\n.word 0"; \ - checkGroup(sourceWithTerminator.c_str(), {__VA_ARGS__}, "+m,+a,+f,+d,+c"); \ - } \ +#define EXPECT_GROUP(source, ...) \ + { \ + std::string sourceWithTerminator = source; \ + sourceWithTerminator += "\n.word 0"; \ + checkGroup(sourceWithTerminator.c_str(), {__VA_ARGS__}, false); \ + } \ + if (HasFatalFailure()) return + +/** A helper macro to predecode the first instruction in a snippet of RISC-V + * assembly code and check the assigned group(s) for each micro-op matches the + * expected group(s). Returns from the calling function if a fatal error occurs. + * Four bytes containing zeros are appended to the source to ensure that the + * program will terminate with an unallocated instruction encoding exception + * instead of running into the heap. This specifically targets the compressed + * extension allowing for the EXPECT_GROUP macro to ignore it, otherwise LLVM + * eagerly emits compressed instructions for non-compressed assembly. */ +#define EXPECT_GROUP_COMP(source, ...) \ + { \ + std::string sourceWithTerminator = source; \ + sourceWithTerminator += "\n.word 0"; \ + checkGroup(sourceWithTerminator.c_str(), {__VA_ARGS__}, true); \ + } \ if (HasFatalFailure()) return /** The test fixture for all RISC-V regression tests. */ @@ -102,12 +118,12 @@ class RISCVRegressionTest : public RegressionTest { virtual ~RISCVRegressionTest() {} /** Run the assembly code in `source`. */ - void run(const char* source, const char* extensions); + void run(const char* source, bool compressed); /** Run the first instruction in source through predecode and check the * groups. */ void checkGroup(const char* source, const std::vector expectedGroups, - const char* extensions) override; + bool compressed); /** Generate a default YAML-formatted configuration. */ void generateConfig() const override; @@ -116,6 +132,23 @@ class RISCVRegressionTest : public RegressionTest { virtual std::unique_ptr instantiateArchitecture( simeng::kernel::Linux& kernel) const override; + /** Initialise LLVM */ + void initialiseLLVM() { + LLVMInitializeRISCVTargetInfo(); + LLVMInitializeRISCVTargetMC(); + LLVMInitializeRISCVAsmParser(); + } + + /** Get subtarget feature string. Use compressed instructions only if + * requested */ + std::string getSubtargetFeaturesString(bool compressed) { + std::string subtargetFeatures = "+m,+a,+f,+d"; + if (compressed) { + subtargetFeatures.append(",+c"); + } + return subtargetFeatures; + } + /** Get the value of a general purpose register. */ template T getGeneralRegister(uint8_t tag) const { From 829106d67bbaa5153d641f774461fe96de12a4e9 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Mon, 8 Jul 2024 15:47:22 +0100 Subject: [PATCH 08/18] Remove TODO --- test/regression/RegressionTest.hh | 4 ---- 1 file changed, 4 deletions(-) diff --git a/test/regression/RegressionTest.hh b/test/regression/RegressionTest.hh index d88fa1e6e9..009c7b9ac0 100644 --- a/test/regression/RegressionTest.hh +++ b/test/regression/RegressionTest.hh @@ -88,10 +88,6 @@ class RegressionTest ryml::ConstNodeRef config = simeng::config::SimInfo::getConfig()) const = 0; - // TODO could make this none virtual (prevent AArch64 from needing to pass - // empty extensions param), but this forces all ISA's to implement it which is - // probably preferable - /** Predecode the first instruction in source and check the assigned group * matches the expectation */ void checkGroup(const char* source, const char* triple, From ad3c4cdbea62fd4ce912ed8b355f6c074104eac9 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Tue, 9 Jul 2024 12:48:37 +0100 Subject: [PATCH 09/18] Remove MacroOp --- test/regression/aarch64/AArch64RegressionTest.cc | 1 - test/regression/riscv/RISCVRegressionTest.cc | 1 - 2 files changed, 2 deletions(-) diff --git a/test/regression/aarch64/AArch64RegressionTest.cc b/test/regression/aarch64/AArch64RegressionTest.cc index d78e297d53..acb8ae26b4 100644 --- a/test/regression/aarch64/AArch64RegressionTest.cc +++ b/test/regression/aarch64/AArch64RegressionTest.cc @@ -3,7 +3,6 @@ #include "simeng/arch/aarch64/Architecture.hh" #include "simeng/pipeline/BalancedPortAllocator.hh" -using MacroOp = std::vector>; using namespace simeng::arch::aarch64; void AArch64RegressionTest::run(const char* source) { diff --git a/test/regression/riscv/RISCVRegressionTest.cc b/test/regression/riscv/RISCVRegressionTest.cc index ceb703e8ad..9ba4ca0328 100644 --- a/test/regression/riscv/RISCVRegressionTest.cc +++ b/test/regression/riscv/RISCVRegressionTest.cc @@ -3,7 +3,6 @@ #include "simeng/arch/riscv/Architecture.hh" #include "simeng/pipeline/BalancedPortAllocator.hh" -using MacroOp = std::vector>; using namespace simeng::arch::riscv; void RISCVRegressionTest::run(const char* source, bool compressed) { From 73f0b268b04a20316e82e897b8cbd253d1129a81 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Tue, 16 Jul 2024 13:40:40 +0100 Subject: [PATCH 10/18] PR comments --- test/regression/RegressionTest.cc | 2 +- test/regression/RegressionTest.hh | 30 ++++++++++--------- .../aarch64/AArch64RegressionTest.hh | 2 +- test/regression/riscv/RISCVRegressionTest.hh | 2 +- 4 files changed, 19 insertions(+), 17 deletions(-) diff --git a/test/regression/RegressionTest.cc b/test/regression/RegressionTest.cc index 5d12b9aa78..a61ba00ff2 100644 --- a/test/regression/RegressionTest.cc +++ b/test/regression/RegressionTest.cc @@ -93,7 +93,7 @@ void RegressionTest::createArchitecture(const char* source, const char* triple, void RegressionTest::instantiateMemoryInterfaces() { // Create memory interfaces for instruction and data access. // For each memory interface, a dereferenced shared_ptr to the - // processImage is passed as argument. + // processImage is passed as an argument. ASSERT_TRUE(processMemory_ != nullptr); diff --git a/test/regression/RegressionTest.hh b/test/regression/RegressionTest.hh index 009c7b9ac0..4d36269038 100644 --- a/test/regression/RegressionTest.hh +++ b/test/regression/RegressionTest.hh @@ -71,15 +71,7 @@ class RegressionTest /** Generate a default YAML-formatted configuration. */ virtual void generateConfig() const = 0; - /** Instantiate the architecture object using the kernel */ - void createArchitecture(const char* source, const char* triple, - const char* extensions); - - /** Run the assembly in `source`, building it for the target `triple` and ISA - * extensions. */ - void run(const char* source, const char* triple, const char* extensions); - - /** Create an ISA instance from a kernel. */ + /** Instantiate an ISA specific architecture from a kernel. */ virtual std::unique_ptr instantiateArchitecture( simeng::kernel::Linux& kernel) const = 0; @@ -88,8 +80,17 @@ class RegressionTest ryml::ConstNodeRef config = simeng::config::SimInfo::getConfig()) const = 0; + /** Create the kernel then instantiate an ISA specific architecture. Populates + * the architecture_ member variable. */ + void createArchitecture(const char* source, const char* triple, + const char* extensions); + + /** Run the assembly in `source`, building it for the target `triple` and ISA + * extensions. */ + void run(const char* source, const char* triple, const char* extensions); + /** Predecode the first instruction in source and check the assigned group - * matches the expectation */ + * matches the expectation. */ void checkGroup(const char* source, const char* triple, const char* extensions, const std::vector expectedGroups); @@ -144,12 +145,13 @@ class RegressionTest * extensions. */ void assemble(const char* source, const char* triple, const char* extensions); - /** Instantiate the process from the source bytes for the given architecture. - */ + /** Create the process from the source bytes for the given architecture. + * Populates the process_ and processMemory_ member variables. */ void createProcess(const char* source, const char* triple, const char* extensions); - /** Instantiate the kernel object using the process. */ + /** Creates the process then creates the kernel from this. Populates the + * kernel_ member variable. */ void createKernel(const char* source, const char* triple, const char* extensions); @@ -170,7 +172,7 @@ class RegressionTest std::unique_ptr predictor_ = nullptr; /** All possible data memory interfaces. dataMemory_ set to one of these - * depending on core type */ + * depending on core type. */ std::unique_ptr flatDataMemory_ = nullptr; std::unique_ptr fixedLatencyDataMemory_ = nullptr; diff --git a/test/regression/aarch64/AArch64RegressionTest.hh b/test/regression/aarch64/AArch64RegressionTest.hh index 5e346040db..e6c6f3edc4 100644 --- a/test/regression/aarch64/AArch64RegressionTest.hh +++ b/test/regression/aarch64/AArch64RegressionTest.hh @@ -219,7 +219,7 @@ class AArch64RegressionTest : public RegressionTest { /** Generate a default YAML-formatted configuration. */ void generateConfig() const override; - /** Create an ISA instance from a kernel. */ + /** Instantiate an ISA specific architecture from a kernel. */ virtual std::unique_ptr instantiateArchitecture( simeng::kernel::Linux& kernel) const override; diff --git a/test/regression/riscv/RISCVRegressionTest.hh b/test/regression/riscv/RISCVRegressionTest.hh index 529693f8c4..395b308ed8 100644 --- a/test/regression/riscv/RISCVRegressionTest.hh +++ b/test/regression/riscv/RISCVRegressionTest.hh @@ -128,7 +128,7 @@ class RISCVRegressionTest : public RegressionTest { /** Generate a default YAML-formatted configuration. */ void generateConfig() const override; - /** Create an ISA instance from a kernel. */ + /** Instantiate an ISA specific architecture from a kernel. */ virtual std::unique_ptr instantiateArchitecture( simeng::kernel::Linux& kernel) const override; From 73a8efad4a9fdbd792f0ea6ba641ed9df94be39e Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Fri, 9 Aug 2024 11:43:45 +0100 Subject: [PATCH 11/18] Move core and BP instantiation into their own functions --- test/regression/RegressionTest.cc | 29 ++++++++++++++++++++--------- test/regression/RegressionTest.hh | 6 ++++++ 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/test/regression/RegressionTest.cc b/test/regression/RegressionTest.cc index a61ba00ff2..c18fc81794 100644 --- a/test/regression/RegressionTest.cc +++ b/test/regression/RegressionTest.cc @@ -108,12 +108,7 @@ void RegressionTest::instantiateMemoryInterfaces() { processMemory_, processMemorySize_, 4); } -void RegressionTest::instantiateSimulationObjects(const char* source, - const char* triple, - const char* extensions) { - // Create the architecture, kernel and process - createArchitecture(source, triple, extensions); - +void RegressionTest::createPredictor() { // Create a branch predictor for a pipelined core std::string predictorType = simeng::config::SimInfo::getConfig()["Branch-Predictor"]["Type"] @@ -123,10 +118,9 @@ void RegressionTest::instantiateSimulationObjects(const char* source, } else if (predictorType == "Perceptron") { predictor_ = std::make_unique(); } +} - // Create all possible memory interfaces - instantiateMemoryInterfaces(); - +void RegressionTest::createCore() { // Create the core model switch (std::get<0>(GetParam())) { case EMULATION: @@ -153,6 +147,23 @@ void RegressionTest::instantiateSimulationObjects(const char* source, } } +void RegressionTest::instantiateSimulationObjects(const char* source, + const char* triple, + const char* extensions) { + // Create the architecture, kernel and process + createArchitecture(source, triple, extensions); + + // Create branch predictor from config options + createPredictor(); + + // Create all possible memory interfaces + instantiateMemoryInterfaces(); + + // Create core object from all other simulation objects depending on config + // options + createCore(); +} + void RegressionTest::run(const char* source, const char* triple, const char* extensions) { testing::internal::CaptureStdout(); diff --git a/test/regression/RegressionTest.hh b/test/regression/RegressionTest.hh index 4d36269038..0f1cbb3d1f 100644 --- a/test/regression/RegressionTest.hh +++ b/test/regression/RegressionTest.hh @@ -158,6 +158,12 @@ class RegressionTest /** Instantiate the memory interfaces. */ void instantiateMemoryInterfaces(); + /** Instantiate the branch predictor according to the config. */ + void createPredictor(); + + /** Instantiate the core according to the config. */ + void createCore(); + /** Instantiating all of the objects used to setup and run the simulation. */ void instantiateSimulationObjects(const char* source, const char* triple, const char* extensions); From 835b1466f24f172075b06a91950ec9df9740a948 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Fri, 9 Aug 2024 11:54:01 +0100 Subject: [PATCH 12/18] PR comments --- test/regression/RegressionTest.cc | 2 -- test/regression/RegressionTest.hh | 18 +++++++++--------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/test/regression/RegressionTest.cc b/test/regression/RegressionTest.cc index c18fc81794..3af58508d6 100644 --- a/test/regression/RegressionTest.cc +++ b/test/regression/RegressionTest.cc @@ -58,8 +58,6 @@ void RegressionTest::createProcess(const char* source, const char* triple, std::shared_ptr procImgPtr = process_->getProcessImage(); processMemory_ = procImgPtr.get(); - // TODO ensure performing this before kernel_.createProcess is ok - Think it's - // fine // Populate the heap with initial data (specified by the test being run). ASSERT_LT(process_->getHeapStart() + initialHeapData_.size(), process_->getInitialStackPointer()); diff --git a/test/regression/RegressionTest.hh b/test/regression/RegressionTest.hh index 0f1cbb3d1f..a6c2eaf21c 100644 --- a/test/regression/RegressionTest.hh +++ b/test/regression/RegressionTest.hh @@ -119,7 +119,7 @@ class RegressionTest /** The initial data to populate the heap with. */ std::vector initialHeapData_; - /** The process that was executed. */ + /** The process to be executed. */ std::unique_ptr process_; /** The process memory. */ @@ -137,8 +137,8 @@ class RegressionTest /** The maximum number of ticks to run before aborting the test. */ uint64_t maxTicks_ = UINT64_MAX; - /** The architecture instance. */ - std::unique_ptr architecture_; + /** Pointer to be instantiated for the architecture. */ + std::unique_ptr architecture_ = nullptr; private: /** Assemble test source to a flat binary for the given triple and ISA @@ -168,13 +168,13 @@ class RegressionTest void instantiateSimulationObjects(const char* source, const char* triple, const char* extensions); - /* Instantiation of the kernel. */ + /* Pointer to be instantiated for the kernel. */ std::unique_ptr kernel_ = nullptr; - /* Instantiation of the port allocator. */ + /* Pointer to be instantiated for the port allocator. */ std::unique_ptr portAllocator_ = nullptr; - /* Instantiation of the branch predictor. */ + /* Pointer to be instantiated for the branch predictor. */ std::unique_ptr predictor_ = nullptr; /** All possible data memory interfaces. dataMemory_ set to one of these @@ -183,13 +183,13 @@ class RegressionTest std::unique_ptr fixedLatencyDataMemory_ = nullptr; - /** The data memory interface used during the test. */ + /** Pointer to be instantiated for the data memory interface. */ std::unique_ptr dataMemory_ = nullptr; - /** The instruction memory interface used during the test. */ + /** Pointer to be instantiated for the instruction memory interface. */ std::unique_ptr instructionMemory_ = nullptr; - /** The core that was used. */ + /** Pointer to be instantiated for the core. */ std::unique_ptr core_ = nullptr; /** The size of the process memory in bytes. */ From 83f19b5f70f7c2a57a84017ec6de504ecc79c4de Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Fri, 9 Aug 2024 12:23:31 +0100 Subject: [PATCH 13/18] Combine process, kernel and architecure instantiation --- test/regression/RegressionTest.cc | 21 +++++---------------- test/regression/RegressionTest.hh | 12 +----------- 2 files changed, 6 insertions(+), 27 deletions(-) diff --git a/test/regression/RegressionTest.cc b/test/regression/RegressionTest.cc index 3af58508d6..3b337208cb 100644 --- a/test/regression/RegressionTest.cc +++ b/test/regression/RegressionTest.cc @@ -21,8 +21,8 @@ void RegressionTest::TearDown() { } } -void RegressionTest::createProcess(const char* source, const char* triple, - const char* extensions) { +void RegressionTest::createProcessKernelAndArchitecture( + const char* source, const char* triple, const char* extensions) { // Zero-out process memory from any prior runs if (processMemory_ != nullptr) std::memset(processMemory_, '\0', processMemorySize_); @@ -52,6 +52,7 @@ void RegressionTest::createProcess(const char* source, const char* triple, ASSERT_TRUE(process_->isValid()); entryPoint_ = process_->getEntryPoint(); processMemorySize_ = process_->getProcessImageSize(); + // This instance of procImgPtr pointer needs to be shared because // getMemoryValue in RegressionTest.hh uses reference to the class // member processMemory_. @@ -63,12 +64,6 @@ void RegressionTest::createProcess(const char* source, const char* triple, process_->getInitialStackPointer()); std::copy(initialHeapData_.begin(), initialHeapData_.end(), processMemory_ + process_->getHeapStart()); -} - -void RegressionTest::createKernel(const char* source, const char* triple, - const char* extensions) { - // Create the process to pass to the kernel - createProcess(source, triple, extensions); ASSERT_TRUE(process_ != nullptr); @@ -77,12 +72,6 @@ void RegressionTest::createKernel(const char* source, const char* triple, simeng::config::SimInfo::getConfig()["CPU-Info"]["Special-File-Dir-Path"] .as()); kernel_->createProcess(*process_); -} - -void RegressionTest::createArchitecture(const char* source, const char* triple, - const char* extensions) { - // Create kernel and process - createKernel(source, triple, extensions); // Create the architecture architecture_ = instantiateArchitecture(*kernel_); @@ -149,7 +138,7 @@ void RegressionTest::instantiateSimulationObjects(const char* source, const char* triple, const char* extensions) { // Create the architecture, kernel and process - createArchitecture(source, triple, extensions); + createProcessKernelAndArchitecture(source, triple, extensions); // Create branch predictor from config options createPredictor(); @@ -187,7 +176,7 @@ void RegressionTest::run(const char* source, const char* triple, void RegressionTest::checkGroup(const char* source, const char* triple, const char* extensions, const std::vector expectedGroups) { - createArchitecture(source, triple, extensions); + createProcessKernelAndArchitecture(source, triple, extensions); std::vector> macroOp; architecture_->predecode(code_, 4, 0, macroOp); diff --git a/test/regression/RegressionTest.hh b/test/regression/RegressionTest.hh index a6c2eaf21c..a751a4fcec 100644 --- a/test/regression/RegressionTest.hh +++ b/test/regression/RegressionTest.hh @@ -82,7 +82,7 @@ class RegressionTest /** Create the kernel then instantiate an ISA specific architecture. Populates * the architecture_ member variable. */ - void createArchitecture(const char* source, const char* triple, + void createProcessKernelAndArchitecture(const char* source, const char* triple, const char* extensions); /** Run the assembly in `source`, building it for the target `triple` and ISA @@ -145,16 +145,6 @@ class RegressionTest * extensions. */ void assemble(const char* source, const char* triple, const char* extensions); - /** Create the process from the source bytes for the given architecture. - * Populates the process_ and processMemory_ member variables. */ - void createProcess(const char* source, const char* triple, - const char* extensions); - - /** Creates the process then creates the kernel from this. Populates the - * kernel_ member variable. */ - void createKernel(const char* source, const char* triple, - const char* extensions); - /** Instantiate the memory interfaces. */ void instantiateMemoryInterfaces(); From 90d186159a509b3933c02378976a3a3e481edbcc Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Fri, 9 Aug 2024 12:45:58 +0100 Subject: [PATCH 14/18] Combine functions further --- test/regression/RegressionTest.cc | 55 +++++++++++-------------------- test/regression/RegressionTest.hh | 17 +++------- 2 files changed, 23 insertions(+), 49 deletions(-) diff --git a/test/regression/RegressionTest.cc b/test/regression/RegressionTest.cc index 3b337208cb..f468b12fe2 100644 --- a/test/regression/RegressionTest.cc +++ b/test/regression/RegressionTest.cc @@ -21,8 +21,8 @@ void RegressionTest::TearDown() { } } -void RegressionTest::createProcessKernelAndArchitecture( - const char* source, const char* triple, const char* extensions) { +void RegressionTest::createArchitecture(const char* source, const char* triple, + const char* extensions) { // Zero-out process memory from any prior runs if (processMemory_ != nullptr) std::memset(processMemory_, '\0', processMemorySize_); @@ -77,7 +77,21 @@ void RegressionTest::createProcessKernelAndArchitecture( architecture_ = instantiateArchitecture(*kernel_); } -void RegressionTest::instantiateMemoryInterfaces() { +void RegressionTest::createCore(const char* source, const char* triple, + const char* extensions) { + // Create the architecture, kernel and process + createArchitecture(source, triple, extensions); + + // Create a branch predictor for a pipelined core + std::string predictorType = + simeng::config::SimInfo::getConfig()["Branch-Predictor"]["Type"] + .as(); + if (predictorType == "Generic") { + predictor_ = std::make_unique(); + } else if (predictorType == "Perceptron") { + predictor_ = std::make_unique(); + } + // Create memory interfaces for instruction and data access. // For each memory interface, a dereferenced shared_ptr to the // processImage is passed as an argument. @@ -93,21 +107,7 @@ void RegressionTest::instantiateMemoryInterfaces() { fixedLatencyDataMemory_ = std::make_unique( processMemory_, processMemorySize_, 4); -} - -void RegressionTest::createPredictor() { - // Create a branch predictor for a pipelined core - std::string predictorType = - simeng::config::SimInfo::getConfig()["Branch-Predictor"]["Type"] - .as(); - if (predictorType == "Generic") { - predictor_ = std::make_unique(); - } else if (predictorType == "Perceptron") { - predictor_ = std::make_unique(); - } -} -void RegressionTest::createCore() { // Create the core model switch (std::get<0>(GetParam())) { case EMULATION: @@ -134,29 +134,12 @@ void RegressionTest::createCore() { } } -void RegressionTest::instantiateSimulationObjects(const char* source, - const char* triple, - const char* extensions) { - // Create the architecture, kernel and process - createProcessKernelAndArchitecture(source, triple, extensions); - - // Create branch predictor from config options - createPredictor(); - - // Create all possible memory interfaces - instantiateMemoryInterfaces(); - - // Create core object from all other simulation objects depending on config - // options - createCore(); -} - void RegressionTest::run(const char* source, const char* triple, const char* extensions) { testing::internal::CaptureStdout(); // Create the core, memory interfaces, kernel and process - instantiateSimulationObjects(source, triple, extensions); + createCore(source, triple, extensions); // Run the core model until the program is complete while (!core_->hasHalted() || dataMemory_->hasPendingRequests()) { @@ -176,7 +159,7 @@ void RegressionTest::run(const char* source, const char* triple, void RegressionTest::checkGroup(const char* source, const char* triple, const char* extensions, const std::vector expectedGroups) { - createProcessKernelAndArchitecture(source, triple, extensions); + createArchitecture(source, triple, extensions); std::vector> macroOp; architecture_->predecode(code_, 4, 0, macroOp); diff --git a/test/regression/RegressionTest.hh b/test/regression/RegressionTest.hh index a751a4fcec..fa9eaa827a 100644 --- a/test/regression/RegressionTest.hh +++ b/test/regression/RegressionTest.hh @@ -82,8 +82,8 @@ class RegressionTest /** Create the kernel then instantiate an ISA specific architecture. Populates * the architecture_ member variable. */ - void createProcessKernelAndArchitecture(const char* source, const char* triple, - const char* extensions); + void createArchitecture(const char* source, const char* triple, + const char* extensions); /** Run the assembly in `source`, building it for the target `triple` and ISA * extensions. */ @@ -145,18 +145,9 @@ class RegressionTest * extensions. */ void assemble(const char* source, const char* triple, const char* extensions); - /** Instantiate the memory interfaces. */ - void instantiateMemoryInterfaces(); - - /** Instantiate the branch predictor according to the config. */ - void createPredictor(); - /** Instantiate the core according to the config. */ - void createCore(); - - /** Instantiating all of the objects used to setup and run the simulation. */ - void instantiateSimulationObjects(const char* source, const char* triple, - const char* extensions); + void createCore(const char* source, const char* triple, + const char* extensions); /* Pointer to be instantiated for the kernel. */ std::unique_ptr kernel_ = nullptr; From b4aa2cb1309eb16e65f3084fbb38958e9f5632ac Mon Sep 17 00:00:00 2001 From: Dan Weaver <31134699+dANW34V3R@users.noreply.github.com> Date: Mon, 12 Aug 2024 11:41:58 +0100 Subject: [PATCH 15/18] Add Group Tests (#420) --- src/lib/arch/aarch64/InstructionMetadata.cc | 19 ++- test/regression/RegressionTest.hh | 2 +- .../aarch64/instructions/arithmetic.cc | 7 + .../aarch64/instructions/bitmanip.cc | 12 ++ .../aarch64/instructions/comparison.cc | 15 +++ .../aarch64/instructions/conditional.cc | 12 ++ .../aarch64/instructions/logical.cc | 21 ++- .../aarch64/instructions/multiply.cc | 15 +++ test/regression/aarch64/instructions/neon.cc | 3 + test/regression/aarch64/instructions/sve.cc | 3 + test/regression/riscv/SmokeTest.cc | 4 +- .../riscv/instructions/arithmetic.cc | 64 +++++++++ test/regression/riscv/instructions/atomic.cc | 95 +++++++++++-- test/regression/riscv/instructions/branch.cc | 29 ++++ .../riscv/instructions/compressed.cc | 75 +++++++++++ test/regression/riscv/instructions/float.cc | 127 ++++++++++++++++++ test/regression/riscv/instructions/jump.cc | 14 ++ test/regression/riscv/instructions/load.cc | 15 +++ .../riscv/instructions/multiplyDivide.cc | 29 +++- test/regression/riscv/instructions/store.cc | 9 ++ 20 files changed, 555 insertions(+), 15 deletions(-) diff --git a/src/lib/arch/aarch64/InstructionMetadata.cc b/src/lib/arch/aarch64/InstructionMetadata.cc index 8fbfa74a2b..e0106f97f8 100644 --- a/src/lib/arch/aarch64/InstructionMetadata.cc +++ b/src/lib/arch/aarch64/InstructionMetadata.cc @@ -1798,6 +1798,7 @@ void InstructionMetadata::revertAliasing() { case ARM64_INS_AT: return aliasNYI(); case ARM64_INS_BFI: + // TODO no tests of alias if (opcode == Opcode::AArch64_BFMWri) { // bfi wd, wn, #lsb, #width; alias for // bfm wd, wn, #(-lsb MOD 32), #(width - 1) @@ -1814,6 +1815,7 @@ void InstructionMetadata::revertAliasing() { } return aliasNYI(); case ARM64_INS_BFXIL: + // TODO no tests for alias if (opcode == Opcode::AArch64_BFMWri || opcode == Opcode::AArch64_BFMXri) { // bfxil rd, rn, #lsb, #width; alias for @@ -1896,6 +1898,7 @@ void InstructionMetadata::revertAliasing() { } return aliasNYI(); case ARM64_INS_CSET: + // TODO no usage in regression tests if (opcode == Opcode::AArch64_CSINCWr || opcode == Opcode::AArch64_CSINCXr) { // cset rd, cc; alias for: csinc rd, zr, zr, invert(cc) @@ -1952,6 +1955,7 @@ void InstructionMetadata::revertAliasing() { case ARM64_INS_IC: return aliasNYI(); case ARM64_INS_LSL: + // TODO no usage in regression tests if (opcode == Opcode::AArch64_UBFMWri || opcode == Opcode::AArch64_UBFMXri) { // lsl rd, rn, #shift; alias for: @@ -1998,6 +2002,7 @@ void InstructionMetadata::revertAliasing() { } return aliasNYI(); case ARM64_INS_MNEG: + // TODO no test if (opcode == Opcode::AArch64_MSUBXrrr) { // mneg xd, xn, xm; alias for msub xd, xn, xm, xzr operandCount = 4; @@ -2016,6 +2021,7 @@ void InstructionMetadata::revertAliasing() { } return aliasNYI(); case ARM64_INS_MOV: + // TODO no specific tests if (opcode == Opcode::AArch64_AND_PPzPP) { // mov pd.b, pg/z, pn.b; alias for: and pd.b, pg/z, pn.b, pn.b operandCount = 4; @@ -2272,6 +2278,7 @@ void InstructionMetadata::revertAliasing() { } return aliasNYI(); case ARM64_INS_MUL: + // TODO add comment if (opcode == Opcode::AArch64_MADDXrrr || opcode == Opcode::AArch64_MADDWrrr) { operandCount = 4; @@ -2310,6 +2317,7 @@ void InstructionMetadata::revertAliasing() { } if (opcode == Opcode::AArch64_NOTv16i8 || opcode == Opcode::AArch64_NOTv8i8) { + // TODO needs tests // mvn vd.t, vn.t; alias for : not vd.t, vn.t // Blank entry was for a legitimate alias, however operands were // identical so nothing to alter between the instructions. @@ -2317,6 +2325,7 @@ void InstructionMetadata::revertAliasing() { } return aliasNYI(); case ARM64_INS_NEG: + // TODO needs tests if (opcode == Opcode::AArch64_SUBWrs || opcode == Opcode::AArch64_SUBXrs) { // neg rd, rm{, shift #amount}; alias for: @@ -2364,7 +2373,7 @@ void InstructionMetadata::revertAliasing() { return aliasNYI(); case ARM64_INS_NOT: if (opcode == Opcode::AArch64_EOR_PPzPP) { - // not pd.b, pg/z, pn.b; alisas for: eor pd.b, pg/z, pn.b, pg.b + // not pd.b, pg/z, pn.b; alias for: eor pd.b, pg/z, pn.b, pg.b operandCount = 4; operands[0].access = CS_AC_WRITE; operands[1].access = CS_AC_READ; @@ -2388,6 +2397,7 @@ void InstructionMetadata::revertAliasing() { } return aliasNYI(); case ARM64_INS_ROR: + // TODO needs test if (opcode == Opcode::AArch64_RORVWr || opcode == Opcode::AArch64_RORVXr) { // ror wd, wn, wm; alias for : rorv wd, wn, wm @@ -2398,6 +2408,7 @@ void InstructionMetadata::revertAliasing() { } return aliasNYI(); case ARM64_INS_SBFIZ: + // TODO needs test if (opcode == Opcode::AArch64_SBFMWri || opcode == Opcode::AArch64_SBFMXri) { operands[3].imm -= 1; @@ -2412,6 +2423,7 @@ void InstructionMetadata::revertAliasing() { } return aliasNYI(); case ARM64_INS_SBFX: + // TODO needs test if (opcode == Opcode::AArch64_SBFMWri || opcode == Opcode::AArch64_SBFMXri) { // sbfx rd, rn, #lsb, #width; alias for @@ -2482,6 +2494,7 @@ void InstructionMetadata::revertAliasing() { } return aliasNYI(); case ARM64_INS_SYS: { + // TODO no test // Extract IC/DC/AT/TLBI operation if (std::string(mnemonic) == "dc") { if (operandStr.substr(0, 3) == "zva") { @@ -2502,6 +2515,7 @@ void InstructionMetadata::revertAliasing() { case ARM64_INS_TLBI: return aliasNYI(); case ARM64_INS_TST: + // TODO needs test for register case if (opcode == Opcode::AArch64_ANDSWrs || opcode == Opcode::AArch64_ANDSXrs || opcode == Opcode::AArch64_ANDSWri || @@ -2525,6 +2539,7 @@ void InstructionMetadata::revertAliasing() { } return aliasNYI(); case ARM64_INS_UBFIZ: + // TODO needs test and comment if (opcode == Opcode::AArch64_UBFMWri || opcode == Opcode::AArch64_UBFMXri) { operands[3].imm -= 1; @@ -2539,6 +2554,7 @@ void InstructionMetadata::revertAliasing() { } return aliasNYI(); case ARM64_INS_UBFX: + // TODO needs test if (opcode == Opcode::AArch64_UBFMWri || opcode == Opcode::AArch64_UBFMXri) { // ubfx rd, rn, #lsb, #width; alias for @@ -2560,6 +2576,7 @@ void InstructionMetadata::revertAliasing() { } return aliasNYI(); case ARM64_INS_UXTB: + // TODO needs test // uxtb wd, wn; alias for: ubfm wd, wn, #0, #7 if (opcode == Opcode::AArch64_UBFMWri) { operandCount = 4; diff --git a/test/regression/RegressionTest.hh b/test/regression/RegressionTest.hh index fa9eaa827a..9dfeec783f 100644 --- a/test/regression/RegressionTest.hh +++ b/test/regression/RegressionTest.hh @@ -83,7 +83,7 @@ class RegressionTest /** Create the kernel then instantiate an ISA specific architecture. Populates * the architecture_ member variable. */ void createArchitecture(const char* source, const char* triple, - const char* extensions); + const char* extensions); /** Run the assembly in `source`, building it for the target `triple` and ISA * extensions. */ diff --git a/test/regression/aarch64/instructions/arithmetic.cc b/test/regression/aarch64/instructions/arithmetic.cc index 7127e827f5..0d2552f355 100644 --- a/test/regression/aarch64/instructions/arithmetic.cc +++ b/test/regression/aarch64/instructions/arithmetic.cc @@ -3,6 +3,7 @@ namespace { using InstArithmetic = AArch64RegressionTest; +using namespace simeng::arch::aarch64::InstructionGroups; TEST_P(InstArithmetic, add) { RUN_AARCH64(R"( @@ -353,6 +354,9 @@ TEST_P(InstArithmetic, negsw) { )"); EXPECT_EQ(getNZCV(), 0b1001); EXPECT_EQ(getGeneralRegister(0), static_cast(1ul << 31)); + + EXPECT_GROUP(R"(negs w0, w1)", INT_SIMPLE_ARTH_NOSHIFT); + EXPECT_GROUP(R"(negs w0, w1, lsl 31)", INT_SIMPLE_ARTH); } // Test that NZCV flags are set correctly by 64-bit negs @@ -402,6 +406,9 @@ TEST_P(InstArithmetic, negsx) { )"); EXPECT_EQ(getNZCV(), 0b1001); EXPECT_EQ(getGeneralRegister(0), static_cast(1ul << 63)); + + EXPECT_GROUP(R"(negs x0, x1)", INT_SIMPLE_ARTH_NOSHIFT); + EXPECT_GROUP(R"(negs x0, x1, lsl 31)", INT_SIMPLE_ARTH); } TEST_P(InstArithmetic, sbc) { diff --git a/test/regression/aarch64/instructions/bitmanip.cc b/test/regression/aarch64/instructions/bitmanip.cc index 69e9943f5c..a72dcb64dc 100644 --- a/test/regression/aarch64/instructions/bitmanip.cc +++ b/test/regression/aarch64/instructions/bitmanip.cc @@ -3,6 +3,7 @@ namespace { using InstBitmanip = AArch64RegressionTest; +using namespace simeng::arch::aarch64::InstructionGroups; TEST_P(InstBitmanip, bfm) { // 32-bit @@ -243,6 +244,17 @@ TEST_P(InstBitmanip, sbfm) { EXPECT_EQ(getGeneralRegister(7), 0x78); EXPECT_EQ(getGeneralRegister(8), 0x5678); EXPECT_EQ(getGeneralRegister(9), 0x12345678); + + EXPECT_GROUP(R"(sbfm w4, w0, #30, #27)", INT_SIMPLE_ARTH_NOSHIFT); + EXPECT_GROUP(R"(sbfm x6, x0, #32, #22)", INT_SIMPLE_ARTH_NOSHIFT); + + EXPECT_GROUP(R"(sxtb w7, w0)", INT_SIMPLE_ARTH_NOSHIFT); + EXPECT_GROUP(R"(sxtb x7, w0)", INT_SIMPLE_ARTH_NOSHIFT); + + EXPECT_GROUP(R"(sxth w7, w0)", INT_SIMPLE_ARTH_NOSHIFT); + EXPECT_GROUP(R"(sxth x7, w0)", INT_SIMPLE_ARTH_NOSHIFT); + + EXPECT_GROUP(R"(sxtw x7, w0)", INT_SIMPLE_ARTH_NOSHIFT); } TEST_P(InstBitmanip, ubfm) { diff --git a/test/regression/aarch64/instructions/comparison.cc b/test/regression/aarch64/instructions/comparison.cc index 1acabddfeb..907a1fd3f8 100644 --- a/test/regression/aarch64/instructions/comparison.cc +++ b/test/regression/aarch64/instructions/comparison.cc @@ -3,6 +3,7 @@ namespace { using InstComparison = AArch64RegressionTest; +using namespace simeng::arch::aarch64::InstructionGroups; // Test correct Value stored after comparison for CASAL (32 & 64 bit) TEST_P(InstComparison, casal) { @@ -94,6 +95,8 @@ TEST_P(InstComparison, cmnw) { cmn w0, #0x1 )"); EXPECT_EQ(getNZCV(), 0b0110); + + EXPECT_GROUP(R"(cmn w0, #0x1)", INT_SIMPLE_ARTH_NOSHIFT); } // Test that NZCV flags are set correctly by the 64-bit cmn instruction @@ -119,6 +122,8 @@ TEST_P(InstComparison, cmnx) { cmn x0, #0x1 )"); EXPECT_EQ(getNZCV(), 0b0110); + + EXPECT_GROUP(R"(cmn X0, #0x1)", INT_SIMPLE_ARTH_NOSHIFT); } // Test that NZCV flags are set correctly by the 32-bit ccmn instruction @@ -190,6 +195,9 @@ TEST_P(InstComparison, tstw) { tst w0, #0x80000000 )"); EXPECT_EQ(getNZCV(), 0b1000); + + EXPECT_GROUP(R"(tst w0, w2)", INT_SIMPLE_LOGICAL_NOSHIFT); + EXPECT_GROUP(R"(tst w0, #0x80000000)", INT_SIMPLE_LOGICAL_NOSHIFT); } // Test that NZCV flags are set correctly by 32-bit cmp @@ -243,6 +251,8 @@ TEST_P(InstComparison, cmpw) { cmp w1, #1 )"); EXPECT_EQ(getNZCV(), 0b0011); + + EXPECT_GROUP(R"(cmp w1, #1)", INT_SIMPLE_ARTH_NOSHIFT); } // Test that NZCV flags are set correctly by 64-bit cmp @@ -323,6 +333,8 @@ TEST_P(InstComparison, cmpx) { cmp x0, x2, uxtx 4 )"); EXPECT_EQ(getNZCV(), 0b0010); + + EXPECT_GROUP(R"(cmp x0, x2, uxtx 4)", INT_SIMPLE_ARTH); } // Test that NZCV flags are set correctly by 64-bit tst @@ -347,6 +359,9 @@ TEST_P(InstComparison, tstx) { tst x0, #0x8000000000000000 )"); EXPECT_EQ(getNZCV(), 0b1000); + + EXPECT_GROUP(R"(tst x0, x2)", INT_SIMPLE_LOGICAL_NOSHIFT); + EXPECT_GROUP(R"(tst x0, #0b0010)", INT_SIMPLE_LOGICAL_NOSHIFT); } INSTANTIATE_TEST_SUITE_P(AArch64, InstComparison, diff --git a/test/regression/aarch64/instructions/conditional.cc b/test/regression/aarch64/instructions/conditional.cc index 88022046eb..e10d8b297d 100644 --- a/test/regression/aarch64/instructions/conditional.cc +++ b/test/regression/aarch64/instructions/conditional.cc @@ -3,6 +3,7 @@ namespace { using InstConditional = AArch64RegressionTest; +using namespace simeng::arch::aarch64::InstructionGroups; TEST_P(InstConditional, ccmn) { // 64-bit @@ -120,6 +121,9 @@ TEST_P(InstConditional, csetm) { EXPECT_EQ(getGeneralRegister(4), 0); EXPECT_EQ(getGeneralRegister(5), 0); EXPECT_EQ(getGeneralRegister(6), -1); + + EXPECT_GROUP(R"(csetm w6, le)", INT_SIMPLE_ARTH_NOSHIFT); + EXPECT_GROUP(R"(csetm x6, le)", INT_SIMPLE_ARTH_NOSHIFT); } TEST_P(InstConditional, csinc) { @@ -166,6 +170,11 @@ TEST_P(InstConditional, csinc) { EXPECT_EQ(getGeneralRegister(6), 42u); EXPECT_EQ(getGeneralRegister(7), 42u); EXPECT_EQ(getGeneralRegister(8), 43u); + + EXPECT_GROUP(R"(csinc w6, w1, w2, le)", INT_SIMPLE_ARTH_NOSHIFT); + EXPECT_GROUP(R"(cinc w8, w1, ge)", INT_SIMPLE_ARTH_NOSHIFT); + EXPECT_GROUP(R"(csinc x6, x1, x2, le)", INT_SIMPLE_ARTH_NOSHIFT); + EXPECT_GROUP(R"(cinc x8, x1, ge)", INT_SIMPLE_ARTH_NOSHIFT); } TEST_P(InstConditional, csneg) { @@ -212,6 +221,9 @@ TEST_P(InstConditional, csneg) { EXPECT_EQ(getGeneralRegister(6), 42); EXPECT_EQ(getGeneralRegister(7), 42); EXPECT_EQ(getGeneralRegister(8), -42); + + EXPECT_GROUP(R"(cneg w8, w1, ge)", INT_SIMPLE_ARTH_NOSHIFT); + EXPECT_GROUP(R"(cneg x8, x1, ge)", INT_SIMPLE_ARTH_NOSHIFT); } TEST_P(InstConditional, tbz) { diff --git a/test/regression/aarch64/instructions/logical.cc b/test/regression/aarch64/instructions/logical.cc index 4ecc167a52..b21ca37bb7 100644 --- a/test/regression/aarch64/instructions/logical.cc +++ b/test/regression/aarch64/instructions/logical.cc @@ -3,6 +3,7 @@ namespace { using InstLogical = AArch64RegressionTest; +using namespace simeng::arch::aarch64::InstructionGroups; TEST_P(InstLogical, andw) { // 0 & 0 = 0 @@ -188,6 +189,10 @@ TEST_P(InstLogical, asrw) { asr w0, w0, w1 )"); EXPECT_EQ(getGeneralRegister(0), -8); + + // TODO being noshift seems incorrect - but potentially aliasing to SBF + EXPECT_GROUP(R"(asr w0, w0, wzr)", INT_SIMPLE_ARTH_NOSHIFT); + EXPECT_GROUP(R"(asr w0, w0, #1)", INT_SIMPLE_ARTH_NOSHIFT); } TEST_P(InstLogical, asrx) { @@ -221,6 +226,10 @@ TEST_P(InstLogical, asrx) { asr x0, x0, x1 )"); EXPECT_EQ(getGeneralRegister(0), -8); + + // TODO noshift seems incorrect - but potentially aliasing to SBF + EXPECT_GROUP(R"(asr x0, x0, xzr)", INT_SIMPLE_ARTH_NOSHIFT); + EXPECT_GROUP(R"(asr x0, x0, #2)", INT_SIMPLE_ARTH_NOSHIFT); } TEST_P(InstLogical, bic) { @@ -405,13 +414,18 @@ TEST_P(InstLogical, lsrv) { lsrv x3, x0, xzr lsrv x4, x0, x1 lsrv x5, x0, x2 - # Check lsr alias as xell + # Check lsr alias as well lsr x6, x1, x0 )"); EXPECT_EQ(getGeneralRegister(3), 7ull); EXPECT_EQ(getGeneralRegister(4), 7ull >> 31); EXPECT_EQ(getGeneralRegister(5), 7ull >> 6); EXPECT_EQ(getGeneralRegister(6), 31ull >> 7); + + EXPECT_GROUP(R"(lsr w6, w1, w0)", INT_SIMPLE_ARTH_NOSHIFT); + EXPECT_GROUP(R"(lsr x6, x1, x0)", INT_SIMPLE_ARTH_NOSHIFT); + EXPECT_GROUP(R"(lsr w6, w1, #1)", INT_SIMPLE_ARTH_NOSHIFT); + EXPECT_GROUP(R"(lsr x6, x1, #1)", INT_SIMPLE_ARTH_NOSHIFT); } TEST_P(InstLogical, orn) { @@ -475,6 +489,11 @@ TEST_P(InstLogical, orn) { EXPECT_EQ(getGeneralRegister(6), UINT64_C(-1) & ~UINT64_C(0b0101)); EXPECT_EQ(getGeneralRegister(7), UINT64_C(-1) & ~(UINT64_C(0b0101) << 60)); + + EXPECT_GROUP(R"(mvn w6, w0)", INT_SIMPLE_LOGICAL_NOSHIFT); + EXPECT_GROUP(R"(mvn w7, w0, lsl #28)", INT_SIMPLE_LOGICAL); + EXPECT_GROUP(R"(mvn x6, x1)", INT_SIMPLE_LOGICAL_NOSHIFT); + EXPECT_GROUP(R"(mvn x7, x1, lsl #60)", INT_SIMPLE_LOGICAL); } TEST_P(InstLogical, rorv) { diff --git a/test/regression/aarch64/instructions/multiply.cc b/test/regression/aarch64/instructions/multiply.cc index 9fd2e823c2..6a7bc267f3 100644 --- a/test/regression/aarch64/instructions/multiply.cc +++ b/test/regression/aarch64/instructions/multiply.cc @@ -3,6 +3,7 @@ namespace { using InstMul = AArch64RegressionTest; +using namespace simeng::arch::aarch64::InstructionGroups; TEST_P(InstMul, maddw) { RUN_AARCH64(R"( @@ -41,6 +42,16 @@ TEST_P(InstMul, mulw) { mul w2, w0, w1 )"); EXPECT_EQ(getGeneralRegister(2), 42u); + + RUN_AARCH64(R"( + movz x0, #7 + movz x1, #6 + mul x2, x0, x1 + )"); + EXPECT_EQ(getGeneralRegister(2), 42u); + + EXPECT_GROUP(R"(mul w2, w0, w1)", INT_MUL); + EXPECT_GROUP(R"(mul x2, x0, x1)", INT_MUL); } TEST_P(InstMul, smaddl) { @@ -78,6 +89,8 @@ TEST_P(InstMul, smull) { smull x3, w0, w1 )"); EXPECT_EQ(getGeneralRegister(3), 0x0000002A00000000); + + EXPECT_GROUP(R"(smull x3, w0, w1)", INT_MUL); } TEST_P(InstMul, umaddl) { @@ -93,6 +106,8 @@ TEST_P(InstMul, umaddl) { )"); EXPECT_EQ(getGeneralRegister(3), 0x0005002A00000000); EXPECT_EQ(getGeneralRegister(4), 0x0000002A00000000); + + EXPECT_GROUP(R"(umull x4, w0, w1)", INT_MUL); } INSTANTIATE_TEST_SUITE_P(AArch64, InstMul, diff --git a/test/regression/aarch64/instructions/neon.cc b/test/regression/aarch64/instructions/neon.cc index e23573be9f..a4731f388f 100644 --- a/test/regression/aarch64/instructions/neon.cc +++ b/test/regression/aarch64/instructions/neon.cc @@ -5,6 +5,7 @@ namespace { using InstNeon = AArch64RegressionTest; +using namespace simeng::arch::aarch64::InstructionGroups; TEST_P(InstNeon, add) { // 8-bit vector @@ -3533,6 +3534,8 @@ TEST_P(InstNeon, rev) { 6, uint8_t, {0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00}); + EXPECT_GROUP(R"(rev64 v2.4h, v0.4h)", VECTOR_SIMPLE_ARTH_NOSHIFT); + // REV32 RUN_AARCH64(R"( index z0.b, #0, #1 diff --git a/test/regression/aarch64/instructions/sve.cc b/test/regression/aarch64/instructions/sve.cc index 702979b2dd..a7cee561e3 100644 --- a/test/regression/aarch64/instructions/sve.cc +++ b/test/regression/aarch64/instructions/sve.cc @@ -6,6 +6,7 @@ namespace { using InstSve = AArch64RegressionTest; +using namespace simeng::arch::aarch64::InstructionGroups; TEST_P(InstSve, addvl) { // 64-bits @@ -1890,6 +1891,8 @@ TEST_P(InstSve, eor) { } CHECK_PREDICATE(4, uint64_t, res_p4); + EXPECT_GROUP(R"(not p4.b, p0/z, p1.b)", PREDICATE); + // Vectors, Predicated RUN_AARCH64(R"( # 8-bit diff --git a/test/regression/riscv/SmokeTest.cc b/test/regression/riscv/SmokeTest.cc index ac7b20916b..c990094a9e 100644 --- a/test/regression/riscv/SmokeTest.cc +++ b/test/regression/riscv/SmokeTest.cc @@ -3,7 +3,7 @@ namespace { using SmokeTest = RISCVRegressionTest; -using namespace simeng::arch::riscv; +using namespace simeng::arch::riscv::InstructionGroups; // Test that a trivial instruction will execute TEST_P(SmokeTest, instruction) { @@ -11,7 +11,7 @@ TEST_P(SmokeTest, instruction) { addi a5,a5,32 )"); EXPECT_EQ(getGeneralRegister(15), 32u); - EXPECT_GROUP(R"(addi a5,a5,32)", InstructionGroups::INT_SIMPLE_ARTH); + EXPECT_GROUP(R"(addi a5,a5,32)", INT_SIMPLE_ARTH); } INSTANTIATE_TEST_SUITE_P( diff --git a/test/regression/riscv/instructions/arithmetic.cc b/test/regression/riscv/instructions/arithmetic.cc index 96b97acbaa..703f90133b 100644 --- a/test/regression/riscv/instructions/arithmetic.cc +++ b/test/regression/riscv/instructions/arithmetic.cc @@ -3,6 +3,7 @@ namespace { using InstArithmetic = RISCVRegressionTest; +using namespace simeng::arch::riscv::InstructionGroups; TEST_P(InstArithmetic, sll) { RUN_RISCV(R"( @@ -13,6 +14,9 @@ TEST_P(InstArithmetic, sll) { )"); EXPECT_EQ(getGeneralRegister(30), 48); EXPECT_EQ(getGeneralRegister(31), 192); + + EXPECT_GROUP(R"(sll t5, t4, t3)", INT_SIMPLE_SHIFT); + EXPECT_GROUP(R"(slli t6, t4, 5)", INT_SIMPLE_SHIFT); } TEST_P(InstArithmetic, sllw) { @@ -42,6 +46,9 @@ TEST_P(InstArithmetic, sllw) { EXPECT_EQ(getGeneralRegister(6), 0); EXPECT_EQ(getGeneralRegister(7), 6); // If shamt >= 32 don't change operand as per qemu + + EXPECT_GROUP(R"(sllw t5, t4, t3)", INT_SIMPLE_SHIFT); + EXPECT_GROUP(R"(slliw t1, t4, 31)", INT_SIMPLE_SHIFT); } TEST_P(InstArithmetic, srl) { @@ -53,6 +60,9 @@ TEST_P(InstArithmetic, srl) { )"); EXPECT_EQ(getGeneralRegister(30), 15); EXPECT_EQ(getGeneralRegister(31), 7); + + EXPECT_GROUP(R"(srl t5, t4, t3)", INT_SIMPLE_SHIFT); + EXPECT_GROUP(R"(srli t6, t4, 61)", INT_SIMPLE_SHIFT); } TEST_P(InstArithmetic, srlw) { @@ -70,6 +80,9 @@ TEST_P(InstArithmetic, srlw) { EXPECT_EQ(getGeneralRegister(31), 0b01111111111111111111111111111100); EXPECT_EQ(getGeneralRegister(7), -7); + + EXPECT_GROUP(R"(srlw t1, t4, t3)", INT_SIMPLE_SHIFT); + EXPECT_GROUP(R"(srliw t6, t4, 1)", INT_SIMPLE_SHIFT); } TEST_P(InstArithmetic, sra) { @@ -86,6 +99,9 @@ TEST_P(InstArithmetic, sra) { EXPECT_EQ(getGeneralRegister(31), -2); EXPECT_EQ(getGeneralRegister(6), 1); EXPECT_EQ(getGeneralRegister(7), 2); + + EXPECT_GROUP(R"(sra t5, t4, t3)", INT_SIMPLE_SHIFT); + EXPECT_GROUP(R"(srai t6, t4, 1)", INT_SIMPLE_SHIFT); } TEST_P(InstArithmetic, sraw) { @@ -113,6 +129,9 @@ TEST_P(InstArithmetic, sraw) { )"); EXPECT_EQ(getGeneralRegister(30), -1); EXPECT_EQ(getGeneralRegister(31), 1); + + EXPECT_GROUP(R"(sraw t5, t5, t2)", INT_SIMPLE_SHIFT); + EXPECT_GROUP(R"(sraiw t6, t6, 30)", INT_SIMPLE_SHIFT); } TEST_P(InstArithmetic, add) { @@ -126,6 +145,9 @@ TEST_P(InstArithmetic, add) { EXPECT_EQ(getGeneralRegister(29), 6u); EXPECT_EQ(getGeneralRegister(30), 9u); EXPECT_EQ(getGeneralRegister(0), 0); + + EXPECT_GROUP(R"(add t5, t3, t4)", INT_SIMPLE_ARTH); + EXPECT_GROUP(R"(addi t4, t4, 6)", INT_SIMPLE_ARTH); } TEST_P(InstArithmetic, addw) { @@ -140,6 +162,8 @@ TEST_P(InstArithmetic, addw) { EXPECT_EQ(getGeneralRegister(29), 6u); EXPECT_EQ(getGeneralRegister(30), 9u); EXPECT_EQ(getGeneralRegister(31), -4); + + EXPECT_GROUP(R"(addw t5, t3, t4)", INT_SIMPLE_ARTH); } TEST_P(InstArithmetic, addiw) { @@ -154,6 +178,8 @@ TEST_P(InstArithmetic, addiw) { EXPECT_EQ(getGeneralRegister(29), -5); EXPECT_EQ(getGeneralRegister(30), -1342177285); EXPECT_EQ(getGeneralRegister(31), -5); + + EXPECT_GROUP(R"(addiw t5, t3, -5)", INT_SIMPLE_ARTH); } TEST_P(InstArithmetic, sub) { @@ -165,6 +191,8 @@ TEST_P(InstArithmetic, sub) { )"); EXPECT_EQ(getGeneralRegister(30), -3); EXPECT_EQ(getGeneralRegister(31), 3); + + EXPECT_GROUP(R"(sub t6, t4, t3)", INT_SIMPLE_ARTH); } TEST_P(InstArithmetic, subw) { @@ -185,6 +213,8 @@ TEST_P(InstArithmetic, subw) { EXPECT_EQ(getGeneralRegister(28), 0xFFFFFFFFFFFFFFFF); EXPECT_EQ(getGeneralRegister(29), -2); EXPECT_EQ(getGeneralRegister(6), 0x0000000000000001); + + EXPECT_GROUP(R"(subw t1, t3, t4)", INT_SIMPLE_ARTH); } TEST_P(InstArithmetic, lui) { @@ -194,6 +224,8 @@ TEST_P(InstArithmetic, lui) { )"); EXPECT_EQ(getGeneralRegister(28), 4 << 12); EXPECT_EQ(getGeneralRegister(29), -4ull << 12); + + EXPECT_GROUP(R"(lui t3, 4)", INT_SIMPLE_ARTH); } TEST_P(InstArithmetic, auipc) { @@ -203,6 +235,8 @@ TEST_P(InstArithmetic, auipc) { )"); EXPECT_EQ(getGeneralRegister(28), 4 << 12); EXPECT_EQ(getGeneralRegister(29), (-4ull << 12) + 4); + + EXPECT_GROUP(R"(auipc t4, 1048572)", INT_SIMPLE_ARTH); } TEST_P(InstArithmetic, xor) { @@ -224,6 +258,10 @@ TEST_P(InstArithmetic, xor) { not t1, t3 )"); EXPECT_EQ(getGeneralRegister(6), -4); + + EXPECT_GROUP(R"(xor t5, t3, t4)", INT_SIMPLE_LOGICAL); + EXPECT_GROUP(R"(xori t6, t5, 5)", INT_SIMPLE_LOGICAL); + EXPECT_GROUP(R"(not t1, t3)", INT_SIMPLE_LOGICAL); } TEST_P(InstArithmetic, or) { @@ -237,6 +275,9 @@ TEST_P(InstArithmetic, or) { EXPECT_EQ(getGeneralRegister(30), 0b0111); EXPECT_EQ(getGeneralRegister(31), 0b1111); EXPECT_EQ(getGeneralRegister(7), -5); + + EXPECT_GROUP(R"(or t5, t3, t4)", INT_SIMPLE_LOGICAL); + EXPECT_GROUP(R"(ori t6, t5, 9)", INT_SIMPLE_LOGICAL); } TEST_P(InstArithmetic, and) { @@ -250,6 +291,9 @@ TEST_P(InstArithmetic, and) { EXPECT_EQ(getGeneralRegister(30), 0b0001); EXPECT_EQ(getGeneralRegister(31), 0b0001); EXPECT_EQ(getGeneralRegister(7), 1); + + EXPECT_GROUP(R"(and t5, t3, t4)", INT_SIMPLE_LOGICAL); + EXPECT_GROUP(R"(andi t6, t5, 9)", INT_SIMPLE_LOGICAL); } TEST_P(InstArithmetic, slt) { @@ -265,6 +309,9 @@ TEST_P(InstArithmetic, slt) { EXPECT_EQ(getGeneralRegister(31), 0); EXPECT_EQ(getGeneralRegister(6), 0); EXPECT_EQ(getGeneralRegister(7), 1); + + EXPECT_GROUP(R"(slt t6, t4, t3)", INT_SIMPLE_CMP); + EXPECT_GROUP(R"(sltu t1, t3, t4)", INT_SIMPLE_CMP); } TEST_P(InstArithmetic, slti) { @@ -280,6 +327,9 @@ TEST_P(InstArithmetic, slti) { EXPECT_EQ(getGeneralRegister(31), 0); EXPECT_EQ(getGeneralRegister(6), 0); EXPECT_EQ(getGeneralRegister(7), 1); + + EXPECT_GROUP(R"(slti t6, t4, -3)", INT_SIMPLE_CMP); + EXPECT_GROUP(R"(sltiu t1, t3, 5)", INT_SIMPLE_CMP); } TEST_P(InstArithmetic, addiPseudoinstructions) { @@ -295,6 +345,10 @@ TEST_P(InstArithmetic, addiPseudoinstructions) { EXPECT_EQ(getGeneralRegister(0), 0); EXPECT_EQ(getGeneralRegister(28), -5); EXPECT_EQ(getGeneralRegister(29), -5); + + EXPECT_GROUP(R"(nop)", INT_SIMPLE_ARTH); + EXPECT_GROUP(R"(mv t2, t1)", INT_SIMPLE_ARTH); + EXPECT_GROUP(R"(sext.w t4, t3)", INT_SIMPLE_ARTH); } TEST_P(InstArithmetic, subwPseudoinstructions) { @@ -311,6 +365,9 @@ TEST_P(InstArithmetic, subwPseudoinstructions) { EXPECT_EQ(getGeneralRegister(30), 48586817536); EXPECT_EQ(getGeneralRegister(7), 1342177280); EXPECT_EQ(getGeneralRegister(31), -1342177280); + + EXPECT_GROUP(R"(neg t4, t3)", INT_SIMPLE_ARTH); + EXPECT_GROUP(R"(negw t6, t5)", INT_SIMPLE_ARTH); } TEST_P(InstArithmetic, setPseudoinstructions) { @@ -342,6 +399,11 @@ TEST_P(InstArithmetic, setPseudoinstructions) { EXPECT_EQ(getGeneralRegister(30), 0); EXPECT_EQ(getGeneralRegister(8), 1); EXPECT_EQ(getGeneralRegister(9), 0); + + EXPECT_GROUP(R"(seqz t3, t1)", INT_SIMPLE_CMP); + EXPECT_GROUP(R"(snez t4, t0)", INT_SIMPLE_CMP); + EXPECT_GROUP(R"(sltz t4, t6)", INT_SIMPLE_CMP); + EXPECT_GROUP(R"(sgtz t5, t0)", INT_SIMPLE_CMP); } TEST_P(InstArithmetic, liPseudoinstruction) { @@ -356,6 +418,8 @@ TEST_P(InstArithmetic, liPseudoinstruction) { EXPECT_EQ(getGeneralRegister(15), 0); EXPECT_EQ(getGeneralRegister(14), 192); EXPECT_EQ(getGeneralRegister(13), -180); + + EXPECT_GROUP(R"(li a5, 0)", INT_SIMPLE_ARTH); } INSTANTIATE_TEST_SUITE_P(RISCV, InstArithmetic, diff --git a/test/regression/riscv/instructions/atomic.cc b/test/regression/riscv/instructions/atomic.cc index 9f21d7abf1..bb37d50179 100644 --- a/test/regression/riscv/instructions/atomic.cc +++ b/test/regression/riscv/instructions/atomic.cc @@ -3,6 +3,7 @@ namespace { using InstAtomic = RISCVRegressionTest; +using namespace simeng::arch::riscv::InstructionGroups; TEST_P(InstAtomic, lr) { initialHeapData_.resize(16); @@ -20,11 +21,12 @@ TEST_P(InstAtomic, lr) { lr.w t6, (a0) addi a0, a0, 4 lr.w t5, (a0) - )"); EXPECT_EQ(getGeneralRegister(31), 0xFFFFFFFFDEADBEEF); EXPECT_EQ(getGeneralRegister(30), 0x012345678); + EXPECT_GROUP(R"(lr.w t5, (a0))", LOAD_INT); + RUN_RISCV(R"( # Get heap address li a7, 214 @@ -33,11 +35,12 @@ TEST_P(InstAtomic, lr) { lr.w.aq t6, (a0) addi a0, a0, 4 lr.w.aq t5, (a0) - )"); EXPECT_EQ(getGeneralRegister(31), 0xFFFFFFFFDEADBEEF); EXPECT_EQ(getGeneralRegister(30), 0x012345678); + EXPECT_GROUP(R"(lr.w.aq t5, (a0))", LOAD_INT); + RUN_RISCV(R"( # Get heap address li a7, 214 @@ -46,11 +49,12 @@ TEST_P(InstAtomic, lr) { lr.w.aqrl t6, (a0) addi a0, a0, 4 lr.w.aqrl t5, (a0) - )"); EXPECT_EQ(getGeneralRegister(31), 0xFFFFFFFFDEADBEEF); EXPECT_EQ(getGeneralRegister(30), 0x012345678); + EXPECT_GROUP(R"(lr.w.aqrl t5, (a0))", LOAD_INT); + // Software should not set only the RL bit, but this is not guaranteed RUN_RISCV(R"( # Get heap address @@ -60,11 +64,12 @@ TEST_P(InstAtomic, lr) { lr.w.rl t6, (a0) addi a0, a0, 4 lr.w.rl t5, (a0) - )"); EXPECT_EQ(getGeneralRegister(31), 0xFFFFFFFFDEADBEEF); EXPECT_EQ(getGeneralRegister(30), 0x012345678); + EXPECT_GROUP(R"(lr.w.rl t5, (a0))", LOAD_INT); + RUN_RISCV(R"( # Get heap address li a7, 214 @@ -73,11 +78,12 @@ TEST_P(InstAtomic, lr) { lr.d t6, (a0) addi a0, a0, 4 lr.d t5, (a0) - )"); EXPECT_EQ(getGeneralRegister(31), 0x12345678DEADBEEF); EXPECT_EQ(getGeneralRegister(30), 0xFEEBDAED12345678); + EXPECT_GROUP(R"(lr.d t5, (a0))", LOAD_INT); + RUN_RISCV(R"( # Get heap address li a7, 214 @@ -86,11 +92,12 @@ TEST_P(InstAtomic, lr) { lr.d.aq t6, (a0) addi a0, a0, 4 lr.d.aq t5, (a0) - )"); EXPECT_EQ(getGeneralRegister(31), 0x12345678DEADBEEF); EXPECT_EQ(getGeneralRegister(30), 0xFEEBDAED12345678); + EXPECT_GROUP(R"(lr.d.aq t5, (a0))", LOAD_INT); + RUN_RISCV(R"( # Get heap address li a7, 214 @@ -99,11 +106,12 @@ TEST_P(InstAtomic, lr) { lr.d.aqrl t6, (a0) addi a0, a0, 4 lr.d.aqrl t5, (a0) - )"); EXPECT_EQ(getGeneralRegister(31), 0x12345678DEADBEEF); EXPECT_EQ(getGeneralRegister(30), 0xFEEBDAED12345678); + EXPECT_GROUP(R"(lr.d.aqrl t5, (a0))", LOAD_INT); + RUN_RISCV(R"( # Get heap address li a7, 214 @@ -112,10 +120,11 @@ TEST_P(InstAtomic, lr) { lr.d.rl t6, (a0) addi a0, a0, 4 lr.d.rl t5, (a0) - )"); EXPECT_EQ(getGeneralRegister(31), 0x12345678DEADBEEF); EXPECT_EQ(getGeneralRegister(30), 0xFEEBDAED12345678); + + EXPECT_GROUP(R"(lr.d.rl t5, (a0))", LOAD_INT); } TEST_P(InstAtomic, sc_w) { @@ -142,6 +151,8 @@ TEST_P(InstAtomic, sc_w) { EXPECT_EQ(getGeneralRegister(31), 987); EXPECT_EQ(getMemoryValue(heapStart), 987); EXPECT_EQ(getMemoryValue(heapStart + 4), 0x12345678); + + EXPECT_GROUP(R"(sc.w t5, t6, (a0))", STORE_INT); } TEST_P(InstAtomic, sc_w_aq) { @@ -170,6 +181,8 @@ TEST_P(InstAtomic, sc_w_aq) { EXPECT_EQ(getGeneralRegister(31), 987); EXPECT_EQ(getMemoryValue(heapStart), 987); EXPECT_EQ(getMemoryValue(heapStart + 4), 0x12345678); + + EXPECT_GROUP(R"(sc.w.aq t5, t6, (a0))", STORE_INT); } TEST_P(InstAtomic, sc_w_rl) { @@ -196,6 +209,8 @@ TEST_P(InstAtomic, sc_w_rl) { EXPECT_EQ(getGeneralRegister(31), 987); EXPECT_EQ(getMemoryValue(heapStart), 987); EXPECT_EQ(getMemoryValue(heapStart + 4), 0x12345678); + + EXPECT_GROUP(R"(sc.w.rl t5, t6, (a0))", STORE_INT); } TEST_P(InstAtomic, sc_w_aq_rl) { @@ -222,6 +237,8 @@ TEST_P(InstAtomic, sc_w_aq_rl) { EXPECT_EQ(getGeneralRegister(31), 987); EXPECT_EQ(getMemoryValue(heapStart), 987); EXPECT_EQ(getMemoryValue(heapStart + 4), 0x12345678); + + EXPECT_GROUP(R"(sc.w.aqrl t5, t6, (a0))", STORE_INT); } TEST_P(InstAtomic, sc_d) { @@ -252,6 +269,8 @@ TEST_P(InstAtomic, sc_d) { EXPECT_EQ(getGeneralRegister(31), 0x12365000000001EF); EXPECT_EQ(getMemoryValue(heapStart), 0x5000000001EFBEEF); EXPECT_EQ(getMemoryValue(heapStart + 8), 0xFEEB1236); + + EXPECT_GROUP(R"(sc.d t5, t6, (a0))", STORE_INT); } TEST_P(InstAtomic, sc_d_aq) { @@ -282,6 +301,8 @@ TEST_P(InstAtomic, sc_d_aq) { EXPECT_EQ(getGeneralRegister(31), 0x12365000000001EF); EXPECT_EQ(getMemoryValue(heapStart), 0x5000000001EFBEEF); EXPECT_EQ(getMemoryValue(heapStart + 8), 0xFEEB1236); + + EXPECT_GROUP(R"(sc.d.aq t5, t6, (a0))", STORE_INT); } TEST_P(InstAtomic, sc_d_rl) { @@ -312,6 +333,8 @@ TEST_P(InstAtomic, sc_d_rl) { EXPECT_EQ(getGeneralRegister(31), 0x12365000000001EF); EXPECT_EQ(getMemoryValue(heapStart), 0x5000000001EFBEEF); EXPECT_EQ(getMemoryValue(heapStart + 8), 0xFEEB1236); + + EXPECT_GROUP(R"(sc.d.rl t5, t6, (a0))", STORE_INT); } TEST_P(InstAtomic, sc_d_aq_rl) { @@ -342,6 +365,8 @@ TEST_P(InstAtomic, sc_d_aq_rl) { EXPECT_EQ(getGeneralRegister(31), 0x12365000000001EF); EXPECT_EQ(getMemoryValue(heapStart), 0x5000000001EFBEEF); EXPECT_EQ(getMemoryValue(heapStart + 8), 0xFEEB1236); + + EXPECT_GROUP(R"(sc.d.aqrl t5, t6, (a0))", STORE_INT); } TEST_P(InstAtomic, amoswap_w) { @@ -380,6 +405,8 @@ TEST_P(InstAtomic, amoswap_w) { EXPECT_EQ(getGeneralRegister(31), 987); EXPECT_EQ(getMemoryValue(heapStart + 8), 0xFEEBDAED); EXPECT_EQ(getMemoryValue(heapStart + 12), 987); + + EXPECT_GROUP(R"(amoswap.w t5, t6, (a0))", LOAD_INT); } TEST_P(InstAtomic, amoswap_w_aq) { @@ -418,6 +445,8 @@ TEST_P(InstAtomic, amoswap_w_aq) { EXPECT_EQ(getGeneralRegister(31), 987); EXPECT_EQ(getMemoryValue(heapStart + 8), 0xFEEBDAED); EXPECT_EQ(getMemoryValue(heapStart + 12), 987); + + EXPECT_GROUP(R"(amoswap.w.aq t5, t6, (a0))", LOAD_INT); } TEST_P(InstAtomic, amoswap_w_rl) { @@ -456,6 +485,8 @@ TEST_P(InstAtomic, amoswap_w_rl) { EXPECT_EQ(getGeneralRegister(31), 987); EXPECT_EQ(getMemoryValue(heapStart + 8), 0xFEEBDAED); EXPECT_EQ(getMemoryValue(heapStart + 12), 987); + + EXPECT_GROUP(R"(amoswap.w.rl t5, t6, (a0))", LOAD_INT); } TEST_P(InstAtomic, amoswap_w_aq_rl) { @@ -494,6 +525,8 @@ TEST_P(InstAtomic, amoswap_w_aq_rl) { EXPECT_EQ(getGeneralRegister(31), 987); EXPECT_EQ(getMemoryValue(heapStart + 8), 0xFEEBDAED); EXPECT_EQ(getMemoryValue(heapStart + 12), 987); + + EXPECT_GROUP(R"(amoswap.w.aqrl t5, t6, (a0))", LOAD_INT); } TEST_P(InstAtomic, amoswap_d) { @@ -539,6 +572,8 @@ TEST_P(InstAtomic, amoswap_d) { EXPECT_EQ(getMemoryValue(heapStart + 12), 0x000003DB); EXPECT_EQ(getMemoryValue(heapStart + 16), 0x80000000); EXPECT_EQ(getMemoryValue(heapStart + 20), 0xFFEEFFEE); + + EXPECT_GROUP(R"(amoswap.d t5, t6, (a0))", LOAD_INT); } TEST_P(InstAtomic, amoswap_d_aq) { @@ -584,6 +619,8 @@ TEST_P(InstAtomic, amoswap_d_aq) { EXPECT_EQ(getMemoryValue(heapStart + 12), 0x000003DB); EXPECT_EQ(getMemoryValue(heapStart + 16), 0x80000000); EXPECT_EQ(getMemoryValue(heapStart + 20), 0xFFEEFFEE); + + EXPECT_GROUP(R"(amoswap.d.aq t5, t6, (a0))", LOAD_INT); } TEST_P(InstAtomic, amoswap_d_rl) { @@ -629,6 +666,8 @@ TEST_P(InstAtomic, amoswap_d_rl) { EXPECT_EQ(getMemoryValue(heapStart + 12), 0x000003DB); EXPECT_EQ(getMemoryValue(heapStart + 16), 0x80000000); EXPECT_EQ(getMemoryValue(heapStart + 20), 0xFFEEFFEE); + + EXPECT_GROUP(R"(amoswap.d.rl t5, t6, (a0))", LOAD_INT); } TEST_P(InstAtomic, amoswap_d_aq_rl) { @@ -674,6 +713,8 @@ TEST_P(InstAtomic, amoswap_d_aq_rl) { EXPECT_EQ(getMemoryValue(heapStart + 12), 0x000003DB); EXPECT_EQ(getMemoryValue(heapStart + 16), 0x80000000); EXPECT_EQ(getMemoryValue(heapStart + 20), 0xFFEEFFEE); + + EXPECT_GROUP(R"(amoswap.d.aqrl t5, t6, (a0))", LOAD_INT); } TEST_P(InstAtomic, amoadd_w) { @@ -717,6 +758,8 @@ TEST_P(InstAtomic, amoadd_w) { EXPECT_EQ(getMemoryValue(heapStart + 12), 0x800003DA); // +ve + +ve = -ve as per GDB EXPECT_EQ(getMemoryValue(heapStart + 16), 0x12365478); + + EXPECT_GROUP(R"(amoadd.w t5, t6, (a0))", LOAD_INT); } TEST_P(InstAtomic, amoadd_w_aq) { @@ -760,6 +803,8 @@ TEST_P(InstAtomic, amoadd_w_aq) { EXPECT_EQ(getMemoryValue(heapStart + 12), 0x800003DA); // +ve + +ve = -ve as per GDB EXPECT_EQ(getMemoryValue(heapStart + 16), 0x12365478); + + EXPECT_GROUP(R"(amoadd.w.aq t5, t6, (a0))", LOAD_INT); } TEST_P(InstAtomic, amoadd_w_rl) { @@ -803,6 +848,8 @@ TEST_P(InstAtomic, amoadd_w_rl) { EXPECT_EQ(getMemoryValue(heapStart + 12), 0x800003DA); // +ve + +ve = -ve as per GDB EXPECT_EQ(getMemoryValue(heapStart + 16), 0x12365478); + + EXPECT_GROUP(R"(amoadd.w.rl t5, t6, (a0))", LOAD_INT); } TEST_P(InstAtomic, amoadd_w_aq_rl) { @@ -846,6 +893,8 @@ TEST_P(InstAtomic, amoadd_w_aq_rl) { EXPECT_EQ(getMemoryValue(heapStart + 12), 0x800003DA); // +ve + +ve = -ve as per GDB EXPECT_EQ(getMemoryValue(heapStart + 16), 0x12365478); + + EXPECT_GROUP(R"(amoadd.w.aqrl t5, t6, (a0))", LOAD_INT); } // TODO add aq rl tests for all instructions below, omitted as currently @@ -891,6 +940,8 @@ TEST_P(InstAtomic, amoadd_d) { 0x80000000000003DA); // +ve + +ve = -ve as per GDB EXPECT_EQ(getMemoryValue(heapStart + 20), 0x12365478); // +ve + +ve = -ve as per GDB + + EXPECT_GROUP(R"(amoadd.d t5, t6, (a0))", LOAD_INT); } TEST_P(InstAtomic, amoand_w) { @@ -919,6 +970,8 @@ TEST_P(InstAtomic, amoand_w) { EXPECT_EQ(getGeneralRegister(5), 0x5555555555555555); EXPECT_EQ(getGeneralRegister(6), 0xFFFFFFFFB3333333); EXPECT_EQ(getMemoryValue(heapStart), 0x1234567811111111); // 0b0001 + + EXPECT_GROUP(R"(amoand.w t1, t0, (a0))", LOAD_INT); } TEST_P(InstAtomic, amoand_d) { @@ -948,6 +1001,8 @@ TEST_P(InstAtomic, amoand_d) { EXPECT_EQ(getGeneralRegister(6), 0x3333333333333333); EXPECT_EQ(getMemoryValue(heapStart), 0x1111111111111111); EXPECT_EQ(getMemoryValue(heapStart + 8), 0xFEEBDAED); + + EXPECT_GROUP(R"(amoand.d t1, t0, (a0))", LOAD_INT); } TEST_P(InstAtomic, amoor_w) { @@ -976,6 +1031,8 @@ TEST_P(InstAtomic, amoor_w) { EXPECT_EQ(getGeneralRegister(5), 0x5555555555555555); EXPECT_EQ(getGeneralRegister(6), 0xFFFFFFFFB3333333); EXPECT_EQ(getMemoryValue(heapStart), 0x12345678F7777777); // 0b0111 + + EXPECT_GROUP(R"(amoor.w t1, t0, (a0))", LOAD_INT); } TEST_P(InstAtomic, amoor_d) { @@ -1005,6 +1062,8 @@ TEST_P(InstAtomic, amoor_d) { EXPECT_EQ(getGeneralRegister(6), 0x3333333333333333); EXPECT_EQ(getMemoryValue(heapStart), 0x7777777777777777); EXPECT_EQ(getMemoryValue(heapStart + 8), 0xFEEBDAED); + + EXPECT_GROUP(R"(amoor.d t1, t0, (a0))", LOAD_INT); } TEST_P(InstAtomic, amoxor_w) { @@ -1033,6 +1092,8 @@ TEST_P(InstAtomic, amoxor_w) { EXPECT_EQ(getGeneralRegister(5), 0x5555555555555555); EXPECT_EQ(getGeneralRegister(6), 0xFFFFFFFFB3333333); EXPECT_EQ(getMemoryValue(heapStart), 0x12345678E6666666); // 0b0110 + + EXPECT_GROUP(R"(amoxor.w t1, t0, (a0))", LOAD_INT); } TEST_P(InstAtomic, amoxor_d) { @@ -1062,6 +1123,8 @@ TEST_P(InstAtomic, amoxor_d) { EXPECT_EQ(getGeneralRegister(6), 0x3333333333333333); EXPECT_EQ(getMemoryValue(heapStart), 0x6666666666666666); EXPECT_EQ(getMemoryValue(heapStart + 8), 0xFEEBDAED); + + EXPECT_GROUP(R"(amoxor.d t1, t0, (a0))", LOAD_INT); } TEST_P(InstAtomic, amomin_w) { @@ -1141,6 +1204,8 @@ TEST_P(InstAtomic, amomin_w) { 0xF000000055555555); // (large +ve word), -ve double EXPECT_EQ(getGeneralRegister(6), 0x0000000003333333); // small +ve EXPECT_EQ(getMemoryValue(heapStart), 0x1234567803333333); + + EXPECT_GROUP(R"(amomin.w t1, t0, (a0))", LOAD_INT); } TEST_P(InstAtomic, amomin_d) { @@ -1180,6 +1245,8 @@ TEST_P(InstAtomic, amomin_d) { EXPECT_EQ(getGeneralRegister(30), 0x0034567899999999); // small +ve EXPECT_EQ(getGeneralRegister(31), 0x12345678FEEBDAED); // large +ve EXPECT_EQ(getMemoryValue(heapStart + 8), 0x0034567899999999); + + EXPECT_GROUP(R"(amomin.d t6, t5, (a0))", LOAD_INT); } TEST_P(InstAtomic, amominu_w) { @@ -1260,6 +1327,8 @@ TEST_P(InstAtomic, amominu_w) { 0xF000000055555555); // (large +ve word), -ve double EXPECT_EQ(getGeneralRegister(6), 0x0000000003333333); // small +ve EXPECT_EQ(getMemoryValue(heapStart), 0x1234567803333333); + + EXPECT_GROUP(R"(amominu.w t1, t0, (a0))", LOAD_INT); } TEST_P(InstAtomic, amominu_d) { @@ -1300,6 +1369,8 @@ TEST_P(InstAtomic, amominu_d) { EXPECT_EQ(getGeneralRegister(30), 0x0034567899999999); // small +ve EXPECT_EQ(getGeneralRegister(31), 0x12345678FEEBDAED); // large +ve EXPECT_EQ(getMemoryValue(heapStart + 8), 0x0034567899999999); + + EXPECT_GROUP(R"(amominu.d t6, t5, (a0))", LOAD_INT); } TEST_P(InstAtomic, amomax_w) { @@ -1379,6 +1450,8 @@ TEST_P(InstAtomic, amomax_w) { 0xF000000055555555); // (large +ve word), -ve double EXPECT_EQ(getGeneralRegister(6), 0x0000000003333333); // small +ve EXPECT_EQ(getMemoryValue(heapStart), 0x1234567855555555); + + EXPECT_GROUP(R"(amomax.w t1, t0, (a0))", LOAD_INT); } TEST_P(InstAtomic, amomax_d) { @@ -1418,6 +1491,8 @@ TEST_P(InstAtomic, amomax_d) { EXPECT_EQ(getGeneralRegister(30), 0x0034567899999999); // small +ve EXPECT_EQ(getGeneralRegister(31), 0x12345678FEEBDAED); // large +ve EXPECT_EQ(getMemoryValue(heapStart + 8), 0x12345678FEEBDAED); + + EXPECT_GROUP(R"(amomax.d t6, t5, (a0))", LOAD_INT); } TEST_P(InstAtomic, amomaxu_w) { @@ -1498,6 +1573,8 @@ TEST_P(InstAtomic, amomaxu_w) { 0xF000000055555555); // (large +ve word), -ve double EXPECT_EQ(getGeneralRegister(6), 0x0000000003333333); // small +ve EXPECT_EQ(getMemoryValue(heapStart), 0x1234567855555555); + + EXPECT_GROUP(R"(amomaxu.w t1, t0, (a0))", LOAD_INT); } TEST_P(InstAtomic, amomaxu_d) { @@ -1537,6 +1614,8 @@ TEST_P(InstAtomic, amomaxu_d) { EXPECT_EQ(getGeneralRegister(30), 0x0034567899999999); EXPECT_EQ(getGeneralRegister(31), 0x12345678FEEBDAED); EXPECT_EQ(getMemoryValue(heapStart + 8), 0x12345678FEEBDAED); + + EXPECT_GROUP(R"(amomaxu.d t6, t5, (a0))", LOAD_INT); } INSTANTIATE_TEST_SUITE_P(RISCV, InstAtomic, diff --git a/test/regression/riscv/instructions/branch.cc b/test/regression/riscv/instructions/branch.cc index 16b067f4f1..a31effb676 100644 --- a/test/regression/riscv/instructions/branch.cc +++ b/test/regression/riscv/instructions/branch.cc @@ -3,6 +3,7 @@ namespace { using InstBranch = RISCVRegressionTest; +using namespace simeng::arch::riscv::InstructionGroups; TEST_P(InstBranch, BEQ) { RUN_RISCV(R"( @@ -23,6 +24,9 @@ TEST_P(InstBranch, BEQ) { EXPECT_EQ(getGeneralRegister(29), 7); EXPECT_EQ(getGeneralRegister(28), 5); EXPECT_EQ(getGeneralRegister(7), 0); + + EXPECT_GROUP(R"(beq zero, t4, 8)", BRANCH); + EXPECT_GROUP(R"(beqz s0, -8)", BRANCH); } TEST_P(InstBranch, BNE) { @@ -41,6 +45,9 @@ TEST_P(InstBranch, BNE) { EXPECT_EQ(getGeneralRegister(31), 7); EXPECT_EQ(getGeneralRegister(29), 19); EXPECT_EQ(getGeneralRegister(28), 17); + + EXPECT_GROUP(R"(bne t0, t1, 8)", BRANCH); + EXPECT_GROUP(R"(bnez t0, 4)", BRANCH); } TEST_P(InstBranch, BLT) { @@ -63,6 +70,9 @@ TEST_P(InstBranch, BLT) { EXPECT_EQ(getGeneralRegister(28), 0); EXPECT_EQ(getGeneralRegister(7), 17); + EXPECT_GROUP(R"(blt t0, t1, 8)", BRANCH); + EXPECT_GROUP(R"(bltz t4, 8)", BRANCH); + RUN_RISCV(R"( addi t0, t0, -5 addi t1, t1, 5 @@ -79,6 +89,8 @@ TEST_P(InstBranch, BLT) { EXPECT_EQ(getGeneralRegister(29), 13); EXPECT_EQ(getGeneralRegister(7), 12); + EXPECT_GROUP(R"(bgtz t1, 8)", BRANCH); + RUN_RISCV(R"( addi t0, t0, -5 addi t1, t1, 5 @@ -94,6 +106,8 @@ TEST_P(InstBranch, BLT) { EXPECT_EQ(getGeneralRegister(31), 18); EXPECT_EQ(getGeneralRegister(29), 13); EXPECT_EQ(getGeneralRegister(7), 12); + + EXPECT_GROUP(R"(bgt t1, t0, 8 )", BRANCH); } TEST_P(InstBranch, BLTU) { @@ -112,6 +126,9 @@ TEST_P(InstBranch, BLTU) { EXPECT_EQ(getGeneralRegister(31), 7); EXPECT_EQ(getGeneralRegister(29), 16); EXPECT_EQ(getGeneralRegister(28), 15); + + EXPECT_GROUP(R"(bltu t1, t0, 8)", BRANCH); + EXPECT_GROUP(R"(bgtu t1, t0, 8)", BRANCH); } TEST_P(InstBranch, BGE) { @@ -130,6 +147,8 @@ TEST_P(InstBranch, BGE) { EXPECT_EQ(getGeneralRegister(31), 0); EXPECT_EQ(getGeneralRegister(29), 0); + EXPECT_GROUP(R"(bge t1, t0, 8)", BRANCH); + RUN_RISCV(R"( addi t0, t0, -5 addi t1, t1, 5 @@ -146,6 +165,8 @@ TEST_P(InstBranch, BGE) { EXPECT_EQ(getGeneralRegister(29), 0); EXPECT_EQ(getGeneralRegister(7), 12); + EXPECT_GROUP(R"(blez t1, 8)", BRANCH); + RUN_RISCV(R"( addi t0, t0, -5 addi t1, t1, 5 @@ -162,6 +183,8 @@ TEST_P(InstBranch, BGE) { EXPECT_EQ(getGeneralRegister(29), 0); EXPECT_EQ(getGeneralRegister(7), 12); + EXPECT_GROUP(R"(bgez t3, 8)", BRANCH); + RUN_RISCV(R"( addi t0, t0, -5 addi t1, t1, 5 @@ -177,6 +200,8 @@ TEST_P(InstBranch, BGE) { EXPECT_EQ(getGeneralRegister(31), 18); EXPECT_EQ(getGeneralRegister(29), 0); EXPECT_EQ(getGeneralRegister(7), 12); + + EXPECT_GROUP(R"(ble t3, t3, 8)", BRANCH); } TEST_P(InstBranch, BGEU) { @@ -198,6 +223,8 @@ TEST_P(InstBranch, BGEU) { EXPECT_EQ(getGeneralRegister(28), 14); EXPECT_EQ(getGeneralRegister(7), 11); + EXPECT_GROUP(R"(bgeu t0, t1, 8)", BRANCH); + RUN_RISCV(R"( addi t0, t0, -5 addi t1, t1, 5 @@ -213,6 +240,8 @@ TEST_P(InstBranch, BGEU) { EXPECT_EQ(getGeneralRegister(31), 0); EXPECT_EQ(getGeneralRegister(29), 0); EXPECT_EQ(getGeneralRegister(7), 12); + + EXPECT_GROUP(R"(bleu t3, t3, 8)", BRANCH); } INSTANTIATE_TEST_SUITE_P(RISCV, InstBranch, diff --git a/test/regression/riscv/instructions/compressed.cc b/test/regression/riscv/instructions/compressed.cc index 90335b1d7d..a7387e09b4 100644 --- a/test/regression/riscv/instructions/compressed.cc +++ b/test/regression/riscv/instructions/compressed.cc @@ -3,6 +3,7 @@ namespace { using InstCompressed = RISCVRegressionTest; +using namespace simeng::arch::riscv::InstructionGroups; TEST_P(InstCompressed, lwsp) { // Load word from mem[stack pointer + imm] @@ -24,6 +25,8 @@ TEST_P(InstCompressed, lwsp) { )"); EXPECT_EQ(getGeneralRegister(31), 0xFFFFFFFFDEADBEEF); EXPECT_EQ(getGeneralRegister(29), 0x0000000012345678); + + EXPECT_GROUP_COMP(R"(c.lwsp t4, 4(x2))", LOAD_INT); } TEST_P(InstCompressed, ldsp) { @@ -47,6 +50,8 @@ TEST_P(InstCompressed, ldsp) { )"); EXPECT_EQ(getGeneralRegister(31), 0x12345678DEADBEEF); EXPECT_EQ(getGeneralRegister(29), 0xFEEBDAED12345678); + + EXPECT_GROUP_COMP(R"(c.ldsp t4, 8(x2))", LOAD_INT); } TEST_P(InstCompressed, fldsp) { @@ -75,6 +80,8 @@ TEST_P(InstCompressed, fldsp) { EXPECT_EQ(getFPRegister(1), 123.456); EXPECT_EQ(getFPRegister(2), -0.00032); EXPECT_EQ(getFPRegister(3), 123456); + + EXPECT_GROUP_COMP(R"(c.fldsp ft3, 24(x2))", LOAD_FLOAT); } TEST_P(InstCompressed, swsp) { @@ -92,6 +99,8 @@ TEST_P(InstCompressed, swsp) { 0x000000AA); EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer()), 0x15400AA000000AA); + + EXPECT_GROUP_COMP(R"(c.swsp t6, 4(sp))", STORE_INT); } TEST_P(InstCompressed, sdsp) { @@ -109,6 +118,8 @@ TEST_P(InstCompressed, sdsp) { 0x00000000000000AA); EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() + 8), 0x00000000015400AA); + + EXPECT_GROUP_COMP(R"(c.sdsp t6, 8(sp))", STORE_INT); } TEST_P(InstCompressed, fsdsp) { @@ -128,6 +139,8 @@ TEST_P(InstCompressed, fsdsp) { 0x00000000000000AA); EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() + 8), 0x00000000015400AA); + + EXPECT_GROUP_COMP(R"(c.fsdsp f8, 8(sp))", STORE_FLOAT); } TEST_P(InstCompressed, lw) { @@ -149,6 +162,8 @@ TEST_P(InstCompressed, lw) { )"); EXPECT_EQ(getGeneralRegister(15), 0xFFFFFFFFDEADBEEF); EXPECT_EQ(getGeneralRegister(13), 0x0000000012345678); + + EXPECT_GROUP_COMP(R"(c.lw x13, 4(x8))", LOAD_INT); } TEST_P(InstCompressed, ld) { @@ -171,6 +186,8 @@ TEST_P(InstCompressed, ld) { )"); EXPECT_EQ(getGeneralRegister(15), 0x12345678DEADBEEF); EXPECT_EQ(getGeneralRegister(13), 0xFEEBDAED12345678); + + EXPECT_GROUP_COMP(R"(c.ld x13, 8(x8))", LOAD_INT); } TEST_P(InstCompressed, fld) { @@ -197,6 +214,8 @@ TEST_P(InstCompressed, fld) { EXPECT_EQ(getFPRegister(9), 123.456); EXPECT_EQ(getFPRegister(10), -0.00032); EXPECT_EQ(getFPRegister(11), 123456); + + EXPECT_GROUP_COMP(R"(c.fld f11, 24(a0))", LOAD_FLOAT); } TEST_P(InstCompressed, sw) { @@ -224,6 +243,8 @@ TEST_P(InstCompressed, sw) { EXPECT_EQ(getGeneralRegister(10), 32); EXPECT_EQ(getMemoryValue(32), 0x015400AA000000AA); EXPECT_EQ(getMemoryValue(36), 0x87654321015400AA); + + EXPECT_GROUP_COMP(R"(c.sw x8, 4(a0))", STORE_INT); } TEST_P(InstCompressed, sd) { @@ -251,6 +272,8 @@ TEST_P(InstCompressed, sd) { EXPECT_EQ(getGeneralRegister(10), 32); EXPECT_EQ(getMemoryValue(32), 0x00000000000000AA); EXPECT_EQ(getMemoryValue(40), 0x00000000015400AA); + + EXPECT_GROUP_COMP(R"(c.sd x8, 8(a0))", STORE_INT); } TEST_P(InstCompressed, fsd) { @@ -289,6 +312,8 @@ TEST_P(InstCompressed, fsd) { EXPECT_EQ(getMemoryValue(40), -0.00032); EXPECT_EQ(getMemoryValue(48), 123.456); EXPECT_EQ(getMemoryValue(56), 1.0); + + EXPECT_GROUP_COMP(R"(c.fsd fa3, 0(a0))", STORE_FLOAT); } TEST_P(InstCompressed, j) { @@ -313,6 +338,8 @@ TEST_P(InstCompressed, j) { EXPECT_EQ(getGeneralRegister(6), 8); EXPECT_EQ(getGeneralRegister(1), 14); EXPECT_EQ(getGeneralRegister(0), 0); + + EXPECT_GROUP_COMP(R"(c.j jump)", BRANCH); } TEST_P(InstCompressed, jr) { @@ -326,6 +353,8 @@ TEST_P(InstCompressed, jr) { end: )"); EXPECT_EQ(getGeneralRegister(8), 5); + + EXPECT_GROUP_COMP(R"(c.jr x9)", BRANCH); } TEST_P(InstCompressed, jalr) { @@ -351,6 +380,8 @@ TEST_P(InstCompressed, jalr) { EXPECT_EQ(getGeneralRegister(6), 4); EXPECT_EQ(getGeneralRegister(7), 12); EXPECT_EQ(getGeneralRegister(1), 12); + + EXPECT_GROUP_COMP(R"(c.jalr x8)", BRANCH); } TEST_P(InstCompressed, beqz) { @@ -373,6 +404,8 @@ TEST_P(InstCompressed, beqz) { )"); EXPECT_EQ(getGeneralRegister(10), 10); EXPECT_EQ(getGeneralRegister(11), 10); + + EXPECT_GROUP_COMP(R"(c.beqz x9, b2)", BRANCH); } TEST_P(InstCompressed, bnez) { @@ -393,6 +426,8 @@ TEST_P(InstCompressed, bnez) { addi x11, x11, 5 b4: )"); + + EXPECT_GROUP_COMP(R"(c.bnez x9, b2)", BRANCH); } TEST_P(InstCompressed, li) { @@ -408,6 +443,8 @@ TEST_P(InstCompressed, li) { EXPECT_EQ(getGeneralRegister(15), 0); EXPECT_EQ(getGeneralRegister(14), -32); EXPECT_EQ(getGeneralRegister(13), 31); + + EXPECT_GROUP_COMP(R"(c.li a3, 31)", INT_SIMPLE_ARTH); } TEST_P(InstCompressed, lui) { @@ -419,6 +456,8 @@ TEST_P(InstCompressed, lui) { )"); EXPECT_EQ(getGeneralRegister(28), 4 << 12); EXPECT_EQ(getGeneralRegister(29), -4ull << 12); + + EXPECT_GROUP_COMP(R"(c.lui t4, 0xFFFFC)", INT_SIMPLE_ARTH); } TEST_P(InstCompressed, addi) { @@ -432,6 +471,8 @@ TEST_P(InstCompressed, addi) { EXPECT_EQ(getGeneralRegister(29), 6u); EXPECT_EQ(getGeneralRegister(28), 33u); EXPECT_EQ(getGeneralRegister(0), 0); + + EXPECT_GROUP_COMP(R"(c.addi zero, 16)", INT_SIMPLE_ARTH); } TEST_P(InstCompressed, addiw) { @@ -445,6 +486,8 @@ TEST_P(InstCompressed, addiw) { EXPECT_EQ(getGeneralRegister(28), 24427626496); EXPECT_EQ(getGeneralRegister(30), -1342177285); EXPECT_EQ(getGeneralRegister(31), -5); + + EXPECT_GROUP_COMP(R"(addiw t6, t2, -5)", INT_SIMPLE_ARTH); } TEST_P(InstCompressed, addi16sp) { @@ -458,6 +501,8 @@ TEST_P(InstCompressed, addi16sp) { process_->getInitialStackPointer()); EXPECT_EQ(getGeneralRegister(9), process_->getInitialStackPointer() + 16); + + EXPECT_GROUP_COMP(R"(mv x9, x2)", INT_SIMPLE_ARTH); } TEST_P(InstCompressed, addi4spn) { @@ -470,6 +515,8 @@ TEST_P(InstCompressed, addi4spn) { process_->getInitialStackPointer() + 4); EXPECT_EQ(getGeneralRegister(9), process_->getInitialStackPointer() + 12); + + EXPECT_GROUP_COMP(R"(c.addi4spn x9, x2, 12)", INT_SIMPLE_ARTH); } TEST_P(InstCompressed, slli) { @@ -479,6 +526,8 @@ TEST_P(InstCompressed, slli) { c.slli t4, 5 )"); EXPECT_EQ(getGeneralRegister(29), 192); + + EXPECT_GROUP_COMP(R"(c.slli t4, 5)", INT_SIMPLE_SHIFT); } TEST_P(InstCompressed, srli) { @@ -488,6 +537,8 @@ TEST_P(InstCompressed, srli) { c.srli x8, 61 )"); EXPECT_EQ(getGeneralRegister(8), 7); + + EXPECT_GROUP_COMP(R"(c.srli x8, 61)", INT_SIMPLE_SHIFT); } TEST_P(InstCompressed, srai) { @@ -501,6 +552,8 @@ TEST_P(InstCompressed, srai) { )"); EXPECT_EQ(getGeneralRegister(8), -2); EXPECT_EQ(getGeneralRegister(9), 2); + + EXPECT_GROUP_COMP(R"(c.srai x9, 1)", INT_SIMPLE_SHIFT); } TEST_P(InstCompressed, andi) { @@ -514,6 +567,8 @@ TEST_P(InstCompressed, andi) { )"); EXPECT_EQ(getGeneralRegister(8), 0b0001); EXPECT_EQ(getGeneralRegister(9), 1); + + EXPECT_GROUP_COMP(R"(c.andi x9, -7)", INT_SIMPLE_LOGICAL); } TEST_P(InstCompressed, mv) { @@ -525,6 +580,8 @@ TEST_P(InstCompressed, mv) { )"); EXPECT_EQ(getGeneralRegister(8), 6u); EXPECT_EQ(getGeneralRegister(9), 6u); + + EXPECT_GROUP_COMP(R"(c.mv x8, x9)", INT_SIMPLE_ARTH); } TEST_P(InstCompressed, add) { @@ -536,6 +593,8 @@ TEST_P(InstCompressed, add) { )"); EXPECT_EQ(getGeneralRegister(8), 9u); EXPECT_EQ(getGeneralRegister(9), 6u); + + EXPECT_GROUP_COMP(R"(c.add x8, x9)", INT_SIMPLE_ARTH); } TEST_P(InstCompressed, and) { @@ -546,6 +605,8 @@ TEST_P(InstCompressed, and) { c.and x8, x9 )"); EXPECT_EQ(getGeneralRegister(8), 0b0001); + + EXPECT_GROUP_COMP(R"(c.and x8, x9)", INT_SIMPLE_LOGICAL); } TEST_P(InstCompressed, or) { @@ -556,6 +617,8 @@ TEST_P(InstCompressed, or) { c.or x8, x9 )"); EXPECT_EQ(getGeneralRegister(8), 0b0111); + + EXPECT_GROUP_COMP(R"(c.or x8, x9)", INT_SIMPLE_LOGICAL); } TEST_P(InstCompressed, xor) { @@ -566,6 +629,8 @@ TEST_P(InstCompressed, xor) { c.xor x8, x9 )"); EXPECT_EQ(getGeneralRegister(8), 0b0110); + + EXPECT_GROUP_COMP(R"(c.xor x8, x9)", INT_SIMPLE_LOGICAL); } TEST_P(InstCompressed, sub) { @@ -579,6 +644,8 @@ TEST_P(InstCompressed, sub) { )"); EXPECT_EQ(getGeneralRegister(8), -3); EXPECT_EQ(getGeneralRegister(9), 3); + + EXPECT_GROUP_COMP(R"(c.sub x9, x10)", INT_SIMPLE_ARTH); } TEST_P(InstCompressed, addw) { @@ -594,6 +661,8 @@ TEST_P(InstCompressed, addw) { )"); EXPECT_EQ(getGeneralRegister(8), 9u); EXPECT_EQ(getGeneralRegister(9), -4); + + EXPECT_GROUP_COMP(R"(c.addw x9, x11)", INT_SIMPLE_ARTH); } TEST_P(InstCompressed, subw) { @@ -616,6 +685,8 @@ TEST_P(InstCompressed, subw) { EXPECT_EQ(getGeneralRegister(11), -2); EXPECT_EQ(getGeneralRegister(12), 0x0000000000000001); + + EXPECT_GROUP_COMP(R"(c.subw x12, x11)", INT_SIMPLE_ARTH); } TEST_P(InstCompressed, nop) { @@ -705,6 +776,8 @@ TEST_P(InstCompressed, nop) { EXPECT_EQ(getGeneralRegister(30), 0); EXPECT_EQ(getGeneralRegister(31), 0); EXPECT_EQ(numTicks_, 6); // 5 insns + 1 for unimplemented final insn + + EXPECT_GROUP_COMP(R"(c.nop)", INT_SIMPLE_ARTH); } TEST_P(InstCompressed, ebreak) { @@ -719,6 +792,8 @@ TEST_P(InstCompressed, ebreak) { "exception\n[SimEng:ExceptionHandler] Generated by instruction: " "\n[SimEng:ExceptionHandler] 0x0000000000000000: 02 90 c.ebreak"; EXPECT_EQ(stdout_.substr(0, sizeof(err1) - 1), err1); + + EXPECT_GROUP_COMP(R"(c.ebreak)", INT_SIMPLE_ARTH); } INSTANTIATE_TEST_SUITE_P( diff --git a/test/regression/riscv/instructions/float.cc b/test/regression/riscv/instructions/float.cc index 232e56f551..d5c910d53b 100644 --- a/test/regression/riscv/instructions/float.cc +++ b/test/regression/riscv/instructions/float.cc @@ -3,6 +3,7 @@ namespace { using InstFloat = RISCVRegressionTest; +using namespace simeng::arch::riscv::InstructionGroups; static constexpr uint64_t boxedPositiveNan = 0xffffffff7fc00000; @@ -31,6 +32,8 @@ TEST_P(InstFloat, FLD) { EXPECT_EQ(getFPRegister(1), 123.456); EXPECT_EQ(getFPRegister(2), -0.00032); EXPECT_EQ(getFPRegister(3), 123456); + + EXPECT_GROUP(R"(fld ft3, 24(a0))", LOAD_FLOAT); } TEST_P(InstFloat, FLW) { @@ -70,6 +73,8 @@ TEST_P(InstFloat, FLW) { EXPECT_EQ(getFPRegister(1), 0xffffffff42f6e979); EXPECT_EQ(getFPRegister(2), 0xffffffffb9a7c5ac); EXPECT_EQ(getFPRegister(3), 0xffffffff47f12000); + + EXPECT_GROUP(R"( flw ft3, 12(a0))", LOAD_FLOAT); } TEST_P(InstFloat, FSD) { @@ -107,6 +112,8 @@ TEST_P(InstFloat, FSD) { EXPECT_EQ(getMemoryValue(72), -0.00032); EXPECT_EQ(getMemoryValue(80), 123.456); EXPECT_EQ(getMemoryValue(88), 1.0); + + EXPECT_GROUP(R"(fsd ft0, 24(a0))", STORE_FLOAT); } TEST_P(InstFloat, FSW) { @@ -146,6 +153,8 @@ TEST_P(InstFloat, FSW) { EXPECT_EQ(getMemoryValue(68), (float)-0.00032); EXPECT_EQ(getMemoryValue(72), (float)123.456); EXPECT_EQ(getMemoryValue(76), (float)1.0); + + EXPECT_GROUP(R"(fsw ft0, 12(a0))", STORE_FLOAT); } TEST_P(InstFloat, FDIV_D) { @@ -174,6 +183,8 @@ TEST_P(InstFloat, FDIV_D) { EXPECT_EQ(getFPRegister(15), (double)999.212341); EXPECT_EQ(getFPRegister(16), (double)999.212341 / (double)4.52432537); EXPECT_EQ(getFPRegister(0), (double)999.212341 / (double)-3.78900003); + + EXPECT_GROUP(R"(fdiv.d ft0, fa5, fa4)", FLOAT_DIV_OR_SQRT); } TEST_P(InstFloat, FDIV_S) { @@ -226,6 +237,8 @@ TEST_P(InstFloat, FDIV_S) { EXPECT_EQ(getFPRegister(15), 0xffffffff3f800000); EXPECT_EQ(getFPRegister(16), boxedPositiveNan); + + EXPECT_GROUP(R"(fdiv.s ft0, fa5, fa4)", FLOAT_DIV_OR_SQRT); } TEST_P(InstFloat, FMUL_D) { @@ -254,6 +267,8 @@ TEST_P(InstFloat, FMUL_D) { EXPECT_EQ(getFPRegister(15), (double)999.212341); EXPECT_EQ(getFPRegister(16), (double)999.212341 * (double)4.52432537); EXPECT_EQ(getFPRegister(0), (double)999.212341 * (double)-3.78900003); + + EXPECT_GROUP(R"(fmul.d ft0, fa5, fa4)", FLOAT_MUL); } TEST_P(InstFloat, FMUL_S) { @@ -307,6 +322,8 @@ TEST_P(InstFloat, FMUL_S) { EXPECT_EQ(getFPRegister(15), 0xffffffff3f800000); EXPECT_EQ(getFPRegister(16), boxedPositiveNan); + + EXPECT_GROUP(R"(fmul.s ft0, fa5, fa4)", FLOAT_MUL); } TEST_P(InstFloat, FCVT_D_L) { @@ -325,6 +342,8 @@ TEST_P(InstFloat, FCVT_D_L) { EXPECT_EQ(getFPRegister(0), 0x405EC00000000000); EXPECT_EQ(getFPRegister(1), (double)-1); EXPECT_EQ(getFPRegister(1), 0xBFF0000000000000); + + EXPECT_GROUP(R"(fcvt.d.l ft1, t1)", FLOAT_SIMPLE_CVT); } TEST_P(InstFloat, FCVT_D_W) { @@ -348,6 +367,8 @@ TEST_P(InstFloat, FCVT_D_W) { EXPECT_EQ(getFPRegister(1), 0xBFF0000000000000); EXPECT_EQ(getFPRegister(2), (double)268435455); EXPECT_EQ(getFPRegister(2), 0x41AFFFFFFE000000); + + EXPECT_GROUP(R"(fcvt.d.w ft1, t1)", FLOAT_SIMPLE_CVT); } TEST_P(InstFloat, FCVT_S_L) { @@ -371,6 +392,8 @@ TEST_P(InstFloat, FCVT_S_L) { EXPECT_EQ(getFPRegister(1), 0xFFFFFFFFbf800000); EXPECT_EQ(getFPRegister(2), (float)-4026531841); EXPECT_EQ(getFPRegister(2), 0xFFFFFFFFCF700000); + + EXPECT_GROUP(R"(fcvt.s.l ft1, t1)", FLOAT_SIMPLE_CVT); } TEST_P(InstFloat, FCVT_S_W) { @@ -394,6 +417,8 @@ TEST_P(InstFloat, FCVT_S_W) { EXPECT_EQ(getFPRegister(1), 0xFFFFFFFFbf800000); EXPECT_EQ(getFPRegister(2), (float)268435455); EXPECT_EQ(getFPRegister(2), 0xFFFFFFFF4d800000); + + EXPECT_GROUP(R"(fcvt.s.w ft1, t1)", FLOAT_SIMPLE_CVT); } TEST_P(InstFloat, FCVT_W_D) { @@ -434,6 +459,8 @@ TEST_P(InstFloat, FCVT_W_D) { EXPECT_EQ(getGeneralRegister(6), 0xFFFFFFFFFFFFFFFC); EXPECT_EQ(getGeneralRegister(29), 0xFFFFFFFFFFFFFFFD); EXPECT_EQ(getGeneralRegister(7), 0x000000007FFFFFFF); + + EXPECT_GROUP(R"(fcvt.w.d t0, fa3)", FLOAT_SIMPLE_CVT); } TEST_P(InstFloat, FCVT_W_S) { @@ -496,6 +523,8 @@ TEST_P(InstFloat, FCVT_W_S) { EXPECT_EQ(getGeneralRegister(6), pow(2, 31) - 1); // Expected result from spec EXPECT_EQ(getGeneralRegister(6), 0x000000007fffffff); + + EXPECT_GROUP(R"(fcvt.w.s t0, fa3)", FLOAT_SIMPLE_CVT); } TEST_P(InstFloat, FCVT_L_D) { @@ -532,6 +561,8 @@ TEST_P(InstFloat, FCVT_L_D) { EXPECT_EQ(getGeneralRegister(6), 0xFFFFFFFFFFFFFFFC); EXPECT_EQ(getGeneralRegister(29), 0xFFFFFFFFFFFFFFFD); EXPECT_EQ(getGeneralRegister(7), 0x7FFFFFFFFFFFFFFF); + + EXPECT_GROUP(R"(fcvt.l.d t0, fa3)", FLOAT_SIMPLE_CVT); } TEST_P(InstFloat, FCVT_L_S) { @@ -593,6 +624,8 @@ TEST_P(InstFloat, FCVT_L_S) { EXPECT_EQ(getGeneralRegister(5), 0x0000000000000001); EXPECT_EQ(getGeneralRegister(6), (uint64_t)pow(2, 63) - 1); // Expected result from spec + + EXPECT_GROUP(R"(fcvt.l.s t0, fa3)", FLOAT_SIMPLE_CVT); } TEST_P(InstFloat, FCVT_LU_D) { @@ -632,6 +665,8 @@ TEST_P(InstFloat, FCVT_LU_D) { EXPECT_EQ(getGeneralRegister(29), 0); EXPECT_EQ(getGeneralRegister(7), 0xFFFFFFFFFFFFFFFF); EXPECT_EQ(getGeneralRegister(30), 0xFFFFFFFFFFFFFFFF); + + EXPECT_GROUP(R"(fcvt.lu.d t0, fa3)", FLOAT_SIMPLE_CVT); } TEST_P(InstFloat, FCVT_WU_D) { @@ -671,6 +706,8 @@ TEST_P(InstFloat, FCVT_WU_D) { EXPECT_EQ(getGeneralRegister(29), 0); EXPECT_EQ(getGeneralRegister(7), 0xFFFFFFFFFFFFFFFF); EXPECT_EQ(getGeneralRegister(30), 0xFFFFFFFFFFFFFFFF); + + EXPECT_GROUP(R"(fcvt.wu.d t0, fa3)", FLOAT_SIMPLE_CVT); } TEST_P(InstFloat, FCVT_LU_S) { @@ -735,6 +772,8 @@ TEST_P(InstFloat, FCVT_LU_S) { EXPECT_EQ(getGeneralRegister(5), 0x0000000000000001); EXPECT_EQ(getGeneralRegister(6), 0xFFFFFFFFFFFFFFFF); // Expected result from spec + + EXPECT_GROUP(R"(fcvt.lu.s t0, fa3)", FLOAT_SIMPLE_CVT); } TEST_P(InstFloat, FCVT_WU_S) { @@ -800,6 +839,8 @@ TEST_P(InstFloat, FCVT_WU_S) { EXPECT_EQ(getGeneralRegister(6), pow(2, 32) - 1); // Expected result from spec EXPECT_EQ(getGeneralRegister(6), 0xFFFFFFFFFFFFFFFF); + + EXPECT_GROUP(R"(fcvt.wu.s t0, fa3)", FLOAT_SIMPLE_CVT); } TEST_P(InstFloat, FCVT_D_WU) { @@ -823,6 +864,8 @@ TEST_P(InstFloat, FCVT_D_WU) { EXPECT_EQ(getFPRegister(1), 0x41EFFFFFFFE00000); EXPECT_EQ(getFPRegister(2), (double)268435455); EXPECT_EQ(getFPRegister(2), 0x41AFFFFFFE000000); + + EXPECT_GROUP(R"(fcvt.d.wu ft0, t0)", FLOAT_SIMPLE_CVT); } TEST_P(InstFloat, FCVT_S_WU) { @@ -846,6 +889,8 @@ TEST_P(InstFloat, FCVT_S_WU) { EXPECT_EQ(getFPRegister(1), 0xFFFFFFFF4F800000); EXPECT_EQ(getFPRegister(2), (float)268435456); EXPECT_EQ(getFPRegister(2), 0xFFFFFFFF4D800000); + + EXPECT_GROUP(R"(fcvt.s.wu ft0, t0)", FLOAT_SIMPLE_CVT); } TEST_P(InstFloat, FCVT_D_LU) { @@ -869,6 +914,8 @@ TEST_P(InstFloat, FCVT_D_LU) { EXPECT_EQ(getFPRegister(1), 0x43F0000000000000); EXPECT_EQ(getFPRegister(2), (double)1.8446744069683019776e+19); EXPECT_EQ(getFPRegister(2), 0x43EFFFFFFFE20000); + + EXPECT_GROUP(R"(fcvt.d.lu ft0, t0)", FLOAT_SIMPLE_CVT); } TEST_P(InstFloat, FCVT_S_LU) { @@ -892,6 +939,8 @@ TEST_P(InstFloat, FCVT_S_LU) { EXPECT_EQ(getFPRegister(1), 0xFFFFFFFF5F800000); EXPECT_EQ(getFPRegister(2), (float)1.84467440737e+19); EXPECT_EQ(getFPRegister(2), 0xFFFFFFFF5F800000); + + EXPECT_GROUP(R"(fcvt.s.lu ft0, t0)", FLOAT_SIMPLE_CVT); } TEST_P(InstFloat, FMADD_D) { @@ -920,6 +969,8 @@ TEST_P(InstFloat, FMADD_D) { EXPECT_EQ(getFPRegister(15), (double)999.212341); EXPECT_EQ(getFPRegister(16), (4.52432537 * 999.212341) + -3.78900003); EXPECT_EQ(getFPRegister(17), (999.212341 * -3.78900003) + 4.52432537); + + EXPECT_GROUP(R"(fmadd.d fa6, fa3, fa5, fa4)", FLOAT_MUL); } TEST_P(InstFloat, FMADD_S) { @@ -979,6 +1030,8 @@ TEST_P(InstFloat, FMADD_S) { EXPECT_EQ(getFPRegister(16), boxedPositiveNan); EXPECT_EQ(getFPRegister(17), boxedPositiveNan); EXPECT_EQ(getFPRegister(18), boxedPositiveNan); + + EXPECT_GROUP(R"(fmadd.s fa7, fa4, fa3, fa5)", FLOAT_MUL); } TEST_P(InstFloat, FNMSUB_D) { @@ -1006,6 +1059,8 @@ TEST_P(InstFloat, FNMSUB_D) { EXPECT_EQ(getFPRegister(15), (double)999.212341); EXPECT_EQ(getFPRegister(16), -(999.212341 * -3.78900003) + 4.52432537); + + EXPECT_GROUP(R"(fnmsub.d fa6, fa5, fa4, fa3)", FLOAT_MUL); } TEST_P(InstFloat, FNMSUB_S) { @@ -1062,6 +1117,8 @@ TEST_P(InstFloat, FNMSUB_S) { EXPECT_EQ(getFPRegister(16), boxedPositiveNan); EXPECT_EQ(getFPRegister(17), boxedPositiveNan); EXPECT_EQ(getFPRegister(18), boxedPositiveNan); + + EXPECT_GROUP(R"(fnmsub.s fa6, fa5, fa4, fa3)", FLOAT_MUL); } TEST_P(InstFloat, FMSUB_S) { @@ -1121,6 +1178,8 @@ TEST_P(InstFloat, FMSUB_S) { EXPECT_EQ(getFPRegister(16), boxedPositiveNan); EXPECT_EQ(getFPRegister(17), boxedPositiveNan); EXPECT_EQ(getFPRegister(18), boxedPositiveNan); + + EXPECT_GROUP(R"(fmsub.s fa7, fa4, fa3, fa5)", FLOAT_MUL); } TEST_P(InstFloat, FMSUB_D) { @@ -1153,6 +1212,8 @@ TEST_P(InstFloat, FMSUB_D) { (double)-3790.5399153953703716979362070560455322265625); EXPECT_EQ(getFPRegister(16), 0xC0AD9D146FCA6B72); EXPECT_EQ(getFPRegister(17), 0xC08FC2D70F769B06); + + EXPECT_GROUP(R"(fmsub.d fa7, fa4, fa3, fa5)", FLOAT_MUL); } TEST_P(InstFloat, FNMADD_S) { @@ -1212,6 +1273,8 @@ TEST_P(InstFloat, FNMADD_S) { EXPECT_EQ(getFPRegister(16), boxedPositiveNan); EXPECT_EQ(getFPRegister(17), boxedPositiveNan); EXPECT_EQ(getFPRegister(18), boxedPositiveNan); + + EXPECT_GROUP(R"(fnmadd.s fa7, fa4, fa3, fa5)", FLOAT_MUL); } TEST_P(InstFloat, FNMADD_D) { @@ -1244,6 +1307,8 @@ TEST_P(InstFloat, FNMADD_D) { (double)3781.4912646553702870733104646205902099609375); EXPECT_EQ(getFPRegister(16), 0x40AD8AFB870A78FE); EXPECT_EQ(getFPRegister(17), 0xC08EB08EB0368E94); + + EXPECT_GROUP(R"(fnmadd.d fa6, fa5, fa4, fa3)", FLOAT_MUL); } TEST_P(InstFloat, FCVT_D_S) { @@ -1308,6 +1373,8 @@ TEST_P(InstFloat, FCVT_D_S) { EXPECT_EQ(getFPRegister(0), 0x3FF0000000000000); EXPECT_EQ(getFPRegister(1), 0x7FF8000000000000); + + EXPECT_GROUP(R"(fcvt.d.s ft0, fa3)", FLOAT_SIMPLE_CVT); } TEST_P(InstFloat, FCVT_S_D) { @@ -1346,6 +1413,8 @@ TEST_P(InstFloat, FCVT_S_D) { EXPECT_EQ(getFPRegister(1), 0xFFFFFFFFc0727efa); EXPECT_EQ(getFPRegister(2), (float)999.212341); EXPECT_EQ(getFPRegister(2), 0xFFFFFFFF4479cd97); + + EXPECT_GROUP(R"(fcvt.s.d ft0, fa3)", FLOAT_SIMPLE_CVT); } TEST_P(InstFloat, FSGNJ_D) { @@ -1397,6 +1466,9 @@ TEST_P(InstFloat, FSGNJ_D) { EXPECT_EQ(getFPRegister(14), (double)-3.78900003); EXPECT_EQ(getFPRegister(2), (double)-3.78900003); EXPECT_EQ(getFPRegister(3), (double)4.52432537); + + EXPECT_GROUP(R"(fsgnj.d fa6, fa4, fa5)", FLOAT_SIMPLE_LOGICAL); + EXPECT_GROUP(R"(fmv.d ft2, fa4)", FLOAT_SIMPLE_LOGICAL); } TEST_P(InstFloat, FSGNJ_S) { @@ -1476,6 +1548,9 @@ TEST_P(InstFloat, FSGNJ_S) { EXPECT_EQ(getFPRegister(0), 0xffffffffbf800000); EXPECT_EQ(getFPRegister(1), 0xffffffffffc00000); EXPECT_EQ(getFPRegister(2), 0xffffffff3f800000); + + EXPECT_GROUP(R"(fsgnj.s fa6, fa4, fa5)", FLOAT_SIMPLE_LOGICAL); + EXPECT_GROUP(R"(fmv.s ft2, fa4)", FLOAT_SIMPLE_LOGICAL); } TEST_P(InstFloat, FSGNJX_D) { @@ -1527,6 +1602,9 @@ TEST_P(InstFloat, FSGNJX_D) { EXPECT_EQ(getFPRegister(14), (double)-3.78900003); EXPECT_EQ(getFPRegister(2), (double)3.78900003); EXPECT_EQ(getFPRegister(3), (double)4.52432537); + + EXPECT_GROUP(R"(fsgnjx.d fa6, fa4, fa5)", FLOAT_SIMPLE_LOGICAL); + EXPECT_GROUP(R"(fabs.d ft2, fa4)", FLOAT_SIMPLE_LOGICAL); } TEST_P(InstFloat, FSGNJX_S) { @@ -1604,6 +1682,9 @@ TEST_P(InstFloat, FSGNJX_S) { EXPECT_EQ(getFPRegister(0), 0xffffffff3f800000); EXPECT_EQ(getFPRegister(1), 0xffffffffffc00000); EXPECT_EQ(getFPRegister(2), 0xffffffffbf800000); + + EXPECT_GROUP(R"(fsgnjx.s fa6, fa4, fa5)", FLOAT_SIMPLE_LOGICAL); + EXPECT_GROUP(R"(fabs.s ft2, fa4)", FLOAT_SIMPLE_LOGICAL); } TEST_P(InstFloat, FSGNJN_D) { @@ -1656,6 +1737,9 @@ TEST_P(InstFloat, FSGNJN_D) { EXPECT_EQ(getFPRegister(14), (double)-3.78900003); EXPECT_EQ(getFPRegister(2), (double)3.78900003); EXPECT_EQ(getFPRegister(3), (double)-4.52432537); + + EXPECT_GROUP(R"(fsgnjn.d fa6, fa4, fa5)", FLOAT_SIMPLE_LOGICAL); + EXPECT_GROUP(R"(fneg.d ft2, fa4)", FLOAT_SIMPLE_LOGICAL); } TEST_P(InstFloat, FSGNJN_S) { @@ -1734,6 +1818,9 @@ TEST_P(InstFloat, FSGNJN_S) { EXPECT_EQ(getFPRegister(0), 0xffffffff3f800000); EXPECT_EQ(getFPRegister(1), boxedPositiveNan); EXPECT_EQ(getFPRegister(2), 0xffffffffbf800000); + + EXPECT_GROUP(R"(fsgnjn.s fa6, fa4, fa5)", FLOAT_SIMPLE_LOGICAL); + EXPECT_GROUP(R"(fneg.s ft2, fa4)", FLOAT_SIMPLE_LOGICAL); } TEST_P(InstFloat, FADD_S) { @@ -1789,6 +1876,8 @@ TEST_P(InstFloat, FADD_S) { EXPECT_EQ(getFPRegister(15), 0xffffffff40000000); EXPECT_EQ(getFPRegister(16), boxedPositiveNan); + + EXPECT_GROUP(R"(fadd.s ft0, fa4, fa3)", FLOAT_SIMPLE_ARTH); } TEST_P(InstFloat, FADD_D) { @@ -1815,6 +1904,8 @@ TEST_P(InstFloat, FADD_D) { EXPECT_EQ(getFPRegister(4), 124.456); EXPECT_EQ(getFPRegister(5), 123.456 - 0.00032); + + EXPECT_GROUP(R"(fadd.d ft4, ft0, ft1)", FLOAT_SIMPLE_ARTH); } TEST_P(InstFloat, FSUB_D) { @@ -1844,6 +1935,8 @@ TEST_P(InstFloat, FSUB_D) { EXPECT_EQ(getFPRegister(0), (double)-8.3133254); EXPECT_EQ(getFPRegister(1), (double)8.3133254); + + EXPECT_GROUP(R"(fsub.d ft0, fa4, fa3)", FLOAT_SIMPLE_ARTH); } TEST_P(InstFloat, FSUB_S) { @@ -1899,6 +1992,8 @@ TEST_P(InstFloat, FSUB_S) { EXPECT_EQ(getFPRegister(15), 0xffffffff00000000); EXPECT_EQ(getFPRegister(16), boxedPositiveNan); + + EXPECT_GROUP(R"(fsub.s ft0, fa4, fa3)", FLOAT_SIMPLE_ARTH); } TEST_P(InstFloat, FSQRT_D) { @@ -1933,6 +2028,8 @@ TEST_P(InstFloat, FSQRT_D) { EXPECT_EQ(getFPRegister(1), 0x7FF8000000000000); // NaN EXPECT_EQ(getFPRegister(2), (double)0.067289611417595679432324118352); EXPECT_EQ(getFPRegister(2), 0x3FB139E458662CD6); + + EXPECT_GROUP(R"(fsqrt.d ft0, fa5)", FLOAT_DIV_OR_SQRT); } TEST_P(InstFloat, FSQRT_S) { @@ -1991,6 +2088,8 @@ TEST_P(InstFloat, FSQRT_S) { EXPECT_EQ(getFPRegister(15), 0xffffffff3f800000); EXPECT_EQ(getFPRegister(16), boxedPositiveNan); + + EXPECT_GROUP(R"(fsqrt.s ft0, fa5)", FLOAT_DIV_OR_SQRT); } TEST_P(InstFloat, FMV_X_D) { @@ -2022,6 +2121,8 @@ TEST_P(InstFloat, FMV_X_D) { EXPECT_EQ(getGeneralRegister(5), 0x401218E8BFF273D0); EXPECT_EQ(getGeneralRegister(6), (double)-3.78900003); EXPECT_EQ(getGeneralRegister(6), 0xC00E4FDF3F6B24E7); + + EXPECT_GROUP(R"(fmv.x.d t0, fa3)", FLOAT_SIMPLE_ARTH); } TEST_P(InstFloat, FMV_X_W) { @@ -2055,6 +2156,8 @@ TEST_P(InstFloat, FMV_X_W) { EXPECT_EQ(getGeneralRegister(5), 0x000000004090c746); EXPECT_EQ(getGeneralRegister(6), (float)-3.78900003); EXPECT_EQ(getGeneralRegister(6), 0xffffffffc0727efa); + + EXPECT_GROUP(R"(fmv.x.w t0, fa3)", FLOAT_SIMPLE_ARTH); } TEST_P(InstFloat, FMV_D_X) { @@ -2089,6 +2192,8 @@ TEST_P(InstFloat, FMV_D_X) { EXPECT_EQ(getGeneralRegister(5), 0x401218E8BFF273D0); EXPECT_EQ(getGeneralRegister(6), (double)-3.78900003); EXPECT_EQ(getGeneralRegister(6), 0xC00E4FDF3F6B24E7); + + EXPECT_GROUP(R"(fmv.d.x fa4, t0)", FLOAT_SIMPLE_ARTH); } TEST_P(InstFloat, FMV_W_X) { @@ -2123,6 +2228,8 @@ TEST_P(InstFloat, FMV_W_X) { EXPECT_EQ(getGeneralRegister(5), 0x000000004090c746); EXPECT_EQ(getGeneralRegister(6), (float)-3.78900003); EXPECT_EQ(getGeneralRegister(6), 0xffffffffc0727efa); + + EXPECT_GROUP(R"(fmv.w.x fa4, t0)", FLOAT_SIMPLE_ARTH); } TEST_P(InstFloat, FEQ_D) { @@ -2156,6 +2263,8 @@ TEST_P(InstFloat, FEQ_D) { EXPECT_EQ(getGeneralRegister(6), 0); EXPECT_EQ(getGeneralRegister(7), 0); EXPECT_EQ(getGeneralRegister(28), 0); + + EXPECT_GROUP(R"(feq.d t0, fa3, fa3)", FLOAT_SIMPLE_CMP); } TEST_P(InstFloat, FEQ_S) { @@ -2213,6 +2322,8 @@ TEST_P(InstFloat, FEQ_S) { EXPECT_EQ(getGeneralRegister(5), 0x1); EXPECT_EQ(getGeneralRegister(6), 0x0); + + EXPECT_GROUP(R"(feq.s t0, fa3, fa3)", FLOAT_SIMPLE_CMP); } TEST_P(InstFloat, FLT_D) { @@ -2248,6 +2359,8 @@ TEST_P(InstFloat, FLT_D) { EXPECT_EQ(getGeneralRegister(7), 0); EXPECT_EQ(getGeneralRegister(28), 0); EXPECT_EQ(getGeneralRegister(29), 1); + + EXPECT_GROUP(R"(flt.d t0, fa3, fa3)", FLOAT_SIMPLE_CMP); } TEST_P(InstFloat, FLT_S) { @@ -2307,6 +2420,8 @@ TEST_P(InstFloat, FLT_S) { EXPECT_EQ(getGeneralRegister(5), 0x0); EXPECT_EQ(getGeneralRegister(6), 0x0); + + EXPECT_GROUP(R"(flt.s t0, fa3, fa3)", FLOAT_SIMPLE_CMP); } TEST_P(InstFloat, FLE_D) { @@ -2342,6 +2457,8 @@ TEST_P(InstFloat, FLE_D) { EXPECT_EQ(getGeneralRegister(7), 0); EXPECT_EQ(getGeneralRegister(28), 0); EXPECT_EQ(getGeneralRegister(29), 1); + + EXPECT_GROUP(R"(fle.d t0, fa3, fa3)", FLOAT_SIMPLE_CMP); } TEST_P(InstFloat, FLE_S) { @@ -2401,6 +2518,8 @@ TEST_P(InstFloat, FLE_S) { EXPECT_EQ(getGeneralRegister(5), 0x1); EXPECT_EQ(getGeneralRegister(6), 0x0); + + EXPECT_GROUP(R"(fle.s t0, fa3, fa3)", FLOAT_SIMPLE_CMP); } TEST_P(InstFloat, FMIN_D) { @@ -2444,6 +2563,8 @@ TEST_P(InstFloat, FMIN_D) { EXPECT_EQ(getFPRegister(3), 0x8000000000000000); EXPECT_EQ(getFPRegister(4), (double)-0); EXPECT_EQ(getFPRegister(4), 0x8000000000000000); + + EXPECT_GROUP(R"(fmin.d fa0, fa3, fa4)", FLOAT_SIMPLE_CMP); } TEST_P(InstFloat, FMIN_S) { @@ -2510,6 +2631,8 @@ TEST_P(InstFloat, FMIN_S) { EXPECT_EQ(getFPRegister(15), 0xffffffff3f800000); EXPECT_EQ(getFPRegister(16), boxedPositiveNan); + + EXPECT_GROUP(R"(fmin.s fa0, fa3, fa4)", FLOAT_SIMPLE_CMP); } TEST_P(InstFloat, FMAX_D) { @@ -2551,6 +2674,8 @@ TEST_P(InstFloat, FMAX_D) { EXPECT_EQ(getFPRegister(3), (double)0); EXPECT_EQ(getFPRegister(3), 0x0000000000000000); EXPECT_EQ(getFPRegister(4), 0x0000000000000000); + + EXPECT_GROUP(R"(fmax.d fa0, fa3, fa4)", FLOAT_SIMPLE_CMP); } TEST_P(InstFloat, FMAX_S) { @@ -2618,6 +2743,8 @@ TEST_P(InstFloat, FMAX_S) { EXPECT_EQ(getFPRegister(15), 0xffffffff3f800000); EXPECT_EQ(getFPRegister(16), boxedPositiveNan); + + EXPECT_GROUP(R"(fmax.s fa0, fa3, fa4)", FLOAT_SIMPLE_CMP); } TEST_P(InstFloat, RoundToNearest) { diff --git a/test/regression/riscv/instructions/jump.cc b/test/regression/riscv/instructions/jump.cc index 968e03fd99..5f3c59520b 100644 --- a/test/regression/riscv/instructions/jump.cc +++ b/test/regression/riscv/instructions/jump.cc @@ -3,6 +3,7 @@ namespace { using InstJump = RISCVRegressionTest; +using namespace simeng::arch::riscv::InstructionGroups; TEST_P(InstJump, jalr) { RUN_RISCV(R"( @@ -19,6 +20,8 @@ TEST_P(InstJump, jalr) { EXPECT_EQ(getGeneralRegister(29), 3); EXPECT_EQ(getGeneralRegister(1), 16); EXPECT_EQ(getGeneralRegister(5), 8); + + EXPECT_GROUP(R"(jalr ra, t1, 4)", BRANCH); } TEST_P(InstJump, jalrAlias) { @@ -31,6 +34,8 @@ TEST_P(InstJump, jalrAlias) { EXPECT_EQ(getGeneralRegister(31), 3); EXPECT_EQ(getGeneralRegister(1), 8); + EXPECT_GROUP(R"(jalr t0)", BRANCH); + RUN_RISCV(R"( addi ra, ra, 12 ret # jalr zero, ra, 0 @@ -41,6 +46,8 @@ TEST_P(InstJump, jalrAlias) { EXPECT_EQ(getGeneralRegister(1), 12); EXPECT_EQ(getGeneralRegister(0), 0); + EXPECT_GROUP(R"(ret)", BRANCH); + RUN_RISCV(R"( addi t0, t0, 12 jr t0 # jalr zero, t0, 0 @@ -50,6 +57,8 @@ TEST_P(InstJump, jalrAlias) { EXPECT_EQ(getGeneralRegister(31), 3); EXPECT_EQ(getGeneralRegister(1), 0); EXPECT_EQ(getGeneralRegister(0), 0); + + EXPECT_GROUP(R"(jr t0)", BRANCH); } TEST_P(InstJump, jal) { @@ -66,6 +75,8 @@ TEST_P(InstJump, jal) { EXPECT_EQ(getGeneralRegister(29), 3); EXPECT_EQ(getGeneralRegister(1), 12); EXPECT_EQ(getGeneralRegister(5), 4); + + EXPECT_GROUP(R"(jal ra, 12)", BRANCH); } TEST_P(InstJump, jalAlias) { @@ -84,6 +95,9 @@ TEST_P(InstJump, jalAlias) { EXPECT_EQ(getGeneralRegister(5), 0); EXPECT_EQ(getGeneralRegister(1), 20); EXPECT_EQ(getGeneralRegister(0), 0); + + EXPECT_GROUP(R"(j 12)", BRANCH); + EXPECT_GROUP(R"(jal -12)", BRANCH); } INSTANTIATE_TEST_SUITE_P(RISCV, InstJump, diff --git a/test/regression/riscv/instructions/load.cc b/test/regression/riscv/instructions/load.cc index 9f59fee327..0e2f919cd7 100644 --- a/test/regression/riscv/instructions/load.cc +++ b/test/regression/riscv/instructions/load.cc @@ -3,6 +3,7 @@ namespace { using InstLoad = RISCVRegressionTest; +using namespace simeng::arch::riscv::InstructionGroups; TEST_P(InstLoad, lb) { initialHeapData_.resize(16); @@ -28,6 +29,8 @@ TEST_P(InstLoad, lb) { EXPECT_EQ(getGeneralRegister(28), 0x0000000000000012); EXPECT_EQ(getGeneralRegister(7), 0xFFFFFFFFFFFFFFAD); + EXPECT_GROUP(R"(lb t2, -2(t5))", LOAD_INT); + // Load byte unsigned RUN_RISCV(R"( li a7, 214 @@ -44,6 +47,8 @@ TEST_P(InstLoad, lb) { EXPECT_EQ(getGeneralRegister(29), 0x0000000000000078); EXPECT_EQ(getGeneralRegister(28), 0x0000000000000012); EXPECT_EQ(getGeneralRegister(7), 0x00000000000000AD); + + EXPECT_GROUP(R"(lbu t2, -2(t5))", LOAD_INT); } TEST_P(InstLoad, lh) { @@ -70,6 +75,8 @@ TEST_P(InstLoad, lh) { EXPECT_EQ(getGeneralRegister(28), 0xFFFFFFFFFFFFED12); EXPECT_EQ(getGeneralRegister(7), 0xFFFFFFFFFFFFDEAD); + EXPECT_GROUP(R"(lh t2, -2(t5))", LOAD_INT); + // Load half word unsigned RUN_RISCV(R"( li a7, 214 @@ -86,6 +93,8 @@ TEST_P(InstLoad, lh) { EXPECT_EQ(getGeneralRegister(29), 0x0000000000005678); EXPECT_EQ(getGeneralRegister(28), 0x000000000000ED12); EXPECT_EQ(getGeneralRegister(7), 0x000000000000DEAD); + + EXPECT_GROUP(R"(lhu t2, -2(t5))", LOAD_INT); } TEST_P(InstLoad, lw) { @@ -112,6 +121,8 @@ TEST_P(InstLoad, lw) { EXPECT_EQ(getGeneralRegister(28), 0xFFFFFFFFEBDAED12); EXPECT_EQ(getGeneralRegister(7), 0x000000005678DEAD); + EXPECT_GROUP(R"(lw t2, -2(t5))", LOAD_INT); + RUN_RISCV(R"( li a7, 214 ecall @@ -127,6 +138,8 @@ TEST_P(InstLoad, lw) { EXPECT_EQ(getGeneralRegister(29), 0x0000000012345678); EXPECT_EQ(getGeneralRegister(28), 0x00000000EBDAED12); EXPECT_EQ(getGeneralRegister(7), 0x000000005678DEAD); + + EXPECT_GROUP(R"(lwu t2, -2(t5))", LOAD_INT); } TEST_P(InstLoad, ld) { @@ -152,6 +165,8 @@ TEST_P(InstLoad, ld) { EXPECT_EQ(getGeneralRegister(29), 0xFEEBDAED12345678); EXPECT_EQ(getGeneralRegister(28), 0x654321FEEBDAED12); EXPECT_EQ(getGeneralRegister(7), 0xDAED12345678DEAD); + + EXPECT_GROUP(R"(ld t2, -2(t5))", LOAD_INT); } INSTANTIATE_TEST_SUITE_P(RISCV, InstLoad, diff --git a/test/regression/riscv/instructions/multiplyDivide.cc b/test/regression/riscv/instructions/multiplyDivide.cc index 1016d06517..9894ec485a 100644 --- a/test/regression/riscv/instructions/multiplyDivide.cc +++ b/test/regression/riscv/instructions/multiplyDivide.cc @@ -3,6 +3,7 @@ namespace { using InstMulDiv = RISCVRegressionTest; +using namespace simeng::arch::riscv::InstructionGroups; TEST_P(InstMulDiv, mul) { initialHeapData_.resize(16); @@ -34,6 +35,8 @@ TEST_P(InstMulDiv, mul) { EXPECT_EQ(getGeneralRegister(18), 0x80000000); EXPECT_EQ(getGeneralRegister(19), 0x8000000000000000); // 2^31 * 2^32 = 2^63 (NO overflow) + + EXPECT_GROUP(R"(mul s3, s2, t2)", INT_MUL); } // TODO NYI, tests should fail @@ -54,6 +57,8 @@ TEST_P(InstMulDiv, mul) { // EXPECT_EQ(getGeneralRegister(31), -1); // EXPECT_EQ(getGeneralRegister(29), 0); // EXPECT_EQ(getGeneralRegister(28), 1); +// +// EXPECT_GROUP(R"()", INT_MUL); //} TEST_P(InstMulDiv, mulhu) { @@ -71,6 +76,8 @@ TEST_P(InstMulDiv, mulhu) { )"); EXPECT_EQ(getGeneralRegister(31), -1); EXPECT_EQ(getGeneralRegister(29), 0xFFFFFFFFFFFFFFFE); + + EXPECT_GROUP(R"(mulhu t4, t6, t6)", INT_MUL); } // TODO NYI, tests should fail @@ -89,6 +96,8 @@ TEST_P(InstMulDiv, mulhu) { // )"); // EXPECT_EQ(getGeneralRegister(31), -1); // EXPECT_EQ(getGeneralRegister(29), -1); +// +// EXPECT_GROUP(R"()", INT_MUL); //} TEST_P(InstMulDiv, mulw) { @@ -106,12 +115,13 @@ TEST_P(InstMulDiv, mulw) { li t4, 6 slli t3, t5, 30 mulw t2, t4, t3 - )"); EXPECT_EQ(getGeneralRegister(31), -1); EXPECT_EQ(getGeneralRegister(30), 1); EXPECT_EQ(getGeneralRegister(28), 1 << 30); EXPECT_EQ(getGeneralRegister(7), 0xFFFFFFFF80000000); + + EXPECT_GROUP(R"(mulw t2, t4, t3)", INT_MUL); } TEST_P(InstMulDiv, div) { @@ -136,7 +146,6 @@ TEST_P(InstMulDiv, div) { div t2, s2, s3 ld t1, 8(a0) div s4, t1, t6 - )"); EXPECT_EQ(getGeneralRegister(31), -1); EXPECT_EQ(getGeneralRegister(30), 1); //-1/-1 = 1 @@ -147,6 +156,8 @@ TEST_P(InstMulDiv, div) { EXPECT_EQ(getGeneralRegister(6), 0x8000000000000000); EXPECT_EQ(getGeneralRegister(20), 0x8000000000000000); // division overflow + + EXPECT_GROUP(R"(div s4, t1, t6)", INT_DIV_OR_SQRT); } TEST_P(InstMulDiv, divw) { @@ -181,6 +192,8 @@ TEST_P(InstMulDiv, divw) { EXPECT_EQ(getGeneralRegister(6), 0xFFFFFFFF80000000); EXPECT_EQ(getGeneralRegister(20), 0xFFFFFFFF80000000); // division overflow + + EXPECT_GROUP(R"(divw s4, t1, t6)", INT_DIV_OR_SQRT); } TEST_P(InstMulDiv, divu) { @@ -216,6 +229,8 @@ TEST_P(InstMulDiv, divu) { EXPECT_EQ(getGeneralRegister(7), 8); // 16/2 = 8 EXPECT_EQ(getGeneralRegister(6), 0x8000000000000000); EXPECT_EQ(getGeneralRegister(20), 0); // big / max pos = 0 + + EXPECT_GROUP(R"(divu s4, t1, t6)", INT_DIV_OR_SQRT); } TEST_P(InstMulDiv, divuw) { @@ -251,6 +266,8 @@ TEST_P(InstMulDiv, divuw) { EXPECT_EQ(getGeneralRegister(7), 8); // 16/2 = 8 EXPECT_EQ(getGeneralRegister(6), 0xFFFFFFFF80000000); EXPECT_EQ(getGeneralRegister(20), 0); // // big pos / max pos = 0 + + EXPECT_GROUP(R"(divuw s4, t1, t6)", INT_DIV_OR_SQRT); } TEST_P(InstMulDiv, rem) { @@ -287,6 +304,8 @@ TEST_P(InstMulDiv, rem) { EXPECT_EQ(getGeneralRegister(7), -2); // -16/-7 = -2 EXPECT_EQ(getGeneralRegister(6), 0x8000000000000000); EXPECT_EQ(getGeneralRegister(20), 0); // max pos/-1 = 0 + + EXPECT_GROUP(R"(rem s4, t1, t6)", INT_DIV_OR_SQRT); } TEST_P(InstMulDiv, remw) { @@ -327,6 +346,8 @@ TEST_P(InstMulDiv, remw) { EXPECT_EQ(getGeneralRegister(7), -2); // -16/-7 = 2 EXPECT_EQ(getGeneralRegister(6), 0xFFFFFFFF80000000); EXPECT_EQ(getGeneralRegister(20), 0); // big pos/max pos = 0 + + EXPECT_GROUP(R"(remw s4, t1, t6)", INT_DIV_OR_SQRT); } TEST_P(InstMulDiv, remu) { @@ -364,6 +385,8 @@ TEST_P(InstMulDiv, remu) { EXPECT_EQ(getGeneralRegister(6), 0x8000000000000000); EXPECT_EQ(getGeneralRegister(20), 0x8000000000000000); // big pos/max pos = big pos + + EXPECT_GROUP(R"(remu s4, t1, t6)", INT_DIV_OR_SQRT); } TEST_P(InstMulDiv, remuw) { @@ -405,6 +428,8 @@ TEST_P(InstMulDiv, remuw) { EXPECT_EQ(getGeneralRegister(6), 0xFFFFFFFF80000000); EXPECT_EQ(getGeneralRegister(20), 0xFFFFFFFF80000000); // big pos/max pos = 0 + + EXPECT_GROUP(R"(remuw s4, t1, t6)", INT_DIV_OR_SQRT); } INSTANTIATE_TEST_SUITE_P(RISCV, InstMulDiv, diff --git a/test/regression/riscv/instructions/store.cc b/test/regression/riscv/instructions/store.cc index b53a396d88..ea2260481b 100644 --- a/test/regression/riscv/instructions/store.cc +++ b/test/regression/riscv/instructions/store.cc @@ -3,6 +3,7 @@ namespace { using InstStore = RISCVRegressionTest; +using namespace simeng::arch::riscv::InstructionGroups; TEST_P(InstStore, sb) { initialHeapData_.resize(16); @@ -23,6 +24,8 @@ TEST_P(InstStore, sb) { EXPECT_EQ(getGeneralRegister(10), 32); EXPECT_EQ(getMemoryValue(33), 0x0012AA56); EXPECT_EQ(getMemoryValue(37), 0x00005400); + + EXPECT_GROUP(R"(sb t6, 6(a0))", STORE_INT); } TEST_P(InstStore, sh) { @@ -49,6 +52,8 @@ TEST_P(InstStore, sh) { EXPECT_EQ(getMemoryValue(64), 0x1200AA78); EXPECT_EQ(getMemoryValue(69), 0x00015400); EXPECT_EQ(getMemoryValue(73), 0x0054AA00); + + EXPECT_GROUP(R"(sh t6, 10(a0))", STORE_INT); } TEST_P(InstStore, sw) { @@ -80,6 +85,8 @@ TEST_P(InstStore, sw) { EXPECT_EQ(getMemoryValue(69), 0x0087015400AAADBE); EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer()), 0x5400AA00); + + EXPECT_GROUP(R"(sw t6, 0(sp))", STORE_INT); } TEST_P(InstStore, sd) { @@ -110,6 +117,8 @@ TEST_P(InstStore, sd) { EXPECT_EQ(getMemoryValue(68), 0x8765000001540000); EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() + 4), 0x000154000000AA01); + + EXPECT_GROUP(R"(sd t6, 4(sp))", STORE_INT); } INSTANTIATE_TEST_SUITE_P(RISCV, InstStore, From 6673a512db2e9b3f03dda5cac012cd9727a188a8 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Thu, 15 Aug 2024 18:43:06 +0100 Subject: [PATCH 16/18] Refactor checkGroup signature --- test/regression/RegressionTest.cc | 2 +- test/regression/RegressionTest.hh | 2 +- test/regression/aarch64/AArch64RegressionTest.cc | 4 ++-- test/regression/aarch64/AArch64RegressionTest.hh | 3 ++- test/regression/riscv/RISCVRegressionTest.cc | 6 +++--- test/regression/riscv/RISCVRegressionTest.hh | 4 ++-- 6 files changed, 11 insertions(+), 10 deletions(-) diff --git a/test/regression/RegressionTest.cc b/test/regression/RegressionTest.cc index f468b12fe2..4567a8bc9f 100644 --- a/test/regression/RegressionTest.cc +++ b/test/regression/RegressionTest.cc @@ -158,7 +158,7 @@ void RegressionTest::run(const char* source, const char* triple, void RegressionTest::checkGroup(const char* source, const char* triple, const char* extensions, - const std::vector expectedGroups) { + const std::vector& expectedGroups) { createArchitecture(source, triple, extensions); std::vector> macroOp; diff --git a/test/regression/RegressionTest.hh b/test/regression/RegressionTest.hh index 9dfeec783f..a110ff80d1 100644 --- a/test/regression/RegressionTest.hh +++ b/test/regression/RegressionTest.hh @@ -93,7 +93,7 @@ class RegressionTest * matches the expectation. */ void checkGroup(const char* source, const char* triple, const char* extensions, - const std::vector expectedGroups); + const std::vector& expectedGroups); /** Get the value of an architectural register. */ template diff --git a/test/regression/aarch64/AArch64RegressionTest.cc b/test/regression/aarch64/AArch64RegressionTest.cc index acb8ae26b4..90a1386c23 100644 --- a/test/regression/aarch64/AArch64RegressionTest.cc +++ b/test/regression/aarch64/AArch64RegressionTest.cc @@ -12,8 +12,8 @@ void AArch64RegressionTest::run(const char* source) { RegressionTest::run(source, "aarch64", subtargetFeatures.c_str()); } -void AArch64RegressionTest::checkGroup(const char* source, - const std::vector expectedGroups) { +void AArch64RegressionTest::checkGroup( + const char* source, const std::vector& expectedGroups) { initialiseLLVM(); std::string subtargetFeatures = getSubtargetFeaturesString(); diff --git a/test/regression/aarch64/AArch64RegressionTest.hh b/test/regression/aarch64/AArch64RegressionTest.hh index e6c6f3edc4..b0774c15c6 100644 --- a/test/regression/aarch64/AArch64RegressionTest.hh +++ b/test/regression/aarch64/AArch64RegressionTest.hh @@ -214,7 +214,8 @@ class AArch64RegressionTest : public RegressionTest { /** Run the first instruction in source through predecode and check the * groups. */ - void checkGroup(const char* source, const std::vector expectedGroups); + void checkGroup(const char* source, + const std::vector& expectedGroups); /** Generate a default YAML-formatted configuration. */ void generateConfig() const override; diff --git a/test/regression/riscv/RISCVRegressionTest.cc b/test/regression/riscv/RISCVRegressionTest.cc index 9ba4ca0328..d96dab9bf5 100644 --- a/test/regression/riscv/RISCVRegressionTest.cc +++ b/test/regression/riscv/RISCVRegressionTest.cc @@ -12,9 +12,9 @@ void RISCVRegressionTest::run(const char* source, bool compressed) { RegressionTest::run(source, "riscv64", subtargetFeatures.c_str()); } -void RISCVRegressionTest::checkGroup(const char* source, - const std::vector expectedGroups, - bool compressed) { +void RISCVRegressionTest::checkGroup( + const char* source, const std::vector& expectedGroups, + bool compressed) { initialiseLLVM(); std::string subtargetFeatures = getSubtargetFeaturesString(compressed); diff --git a/test/regression/riscv/RISCVRegressionTest.hh b/test/regression/riscv/RISCVRegressionTest.hh index 395b308ed8..a99abd5c54 100644 --- a/test/regression/riscv/RISCVRegressionTest.hh +++ b/test/regression/riscv/RISCVRegressionTest.hh @@ -122,8 +122,8 @@ class RISCVRegressionTest : public RegressionTest { /** Run the first instruction in source through predecode and check the * groups. */ - void checkGroup(const char* source, const std::vector expectedGroups, - bool compressed); + void checkGroup(const char* source, + const std::vector& expectedGroups, bool compressed); /** Generate a default YAML-formatted configuration. */ void generateConfig() const override; From d29235e1bbbdbcf164c19a56de356c35ef28d2bc Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Mon, 19 Aug 2024 13:38:05 +0100 Subject: [PATCH 17/18] Add comments regarding atomic groups --- test/regression/aarch64/instructions/comparison.cc | 13 +++++++++++++ test/regression/riscv/instructions/atomic.cc | 10 ++++++++++ 2 files changed, 23 insertions(+) diff --git a/test/regression/aarch64/instructions/comparison.cc b/test/regression/aarch64/instructions/comparison.cc index 907a1fd3f8..9c56501ae4 100644 --- a/test/regression/aarch64/instructions/comparison.cc +++ b/test/regression/aarch64/instructions/comparison.cc @@ -5,6 +5,15 @@ namespace { using InstComparison = AArch64RegressionTest; using namespace simeng::arch::aarch64::InstructionGroups; +// Similar to RISC-V atomic instructions, read-modify-write operations i.e. a +// load, comparison and store, is given the group LOAD_INT only. The instruction +// object is tagged with the appropriate identifiers (isLoad and isStore) but +// the group only reflects the first stage of execution. This ensures the +// instruction goes to the correct part of the pipeline i.e. the LSQ. But we +// currently do not model the rest of the atomic behaviour precisely as the +// comparison happens here also. The change of the instructions behaviour over +// its lifetime is currently not reflected in the group it is given. + // Test correct Value stored after comparison for CASAL (32 & 64 bit) TEST_P(InstComparison, casal) { // 32-bit @@ -39,6 +48,8 @@ TEST_P(InstComparison, casal) { EXPECT_EQ(getMemoryValue(getGeneralRegister(3)), 100); EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer()), 89); + EXPECT_GROUP("casal w1, w2, [x0]", LOAD_INT); + // 64-bit initialHeapData_.resize(16); uint64_t* heap64 = reinterpret_cast(initialHeapData_.data()); @@ -70,6 +81,8 @@ TEST_P(InstComparison, casal) { 0xDEADBEEF); EXPECT_EQ(getMemoryValue(getGeneralRegister(3)), 101); EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer()), 76); + + EXPECT_GROUP("casal x1, x7, [sp]", LOAD_INT); } // Test that NZCV flags are set correctly by the 32-bit cmn instruction diff --git a/test/regression/riscv/instructions/atomic.cc b/test/regression/riscv/instructions/atomic.cc index bb37d50179..d8b0bc6151 100644 --- a/test/regression/riscv/instructions/atomic.cc +++ b/test/regression/riscv/instructions/atomic.cc @@ -5,6 +5,16 @@ namespace { using InstAtomic = RISCVRegressionTest; using namespace simeng::arch::riscv::InstructionGroups; +// Whilst most RISC-V atomic instructions perform read-modify-write operations +// i.e. a load, comparison and store, each is given the group LOAD_INT only. The +// instruction object is tagged with the appropriate identifiers (isLoad, +// isStore and isAtomic) but the group only reflects the first stage of +// execution. This ensures the instruction goes to the correct part of the +// pipeline i.e. the LSQ. But we currently do not model the rest of the atomic +// behaviour precisely as the comparison happens here also. The change of the +// instructions behaviour over its lifetime is currently not reflected in the +// group it is given. + TEST_P(InstAtomic, lr) { initialHeapData_.resize(16); uint32_t* heap = reinterpret_cast(initialHeapData_.data()); From e21732691141cc0922a57cb45898999864fc7f8a Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Tue, 20 Aug 2024 10:38:44 +0100 Subject: [PATCH 18/18] Remove full stops --- test/regression/RegressionTest.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/regression/RegressionTest.cc b/test/regression/RegressionTest.cc index 4567a8bc9f..d55c27bed9 100644 --- a/test/regression/RegressionTest.cc +++ b/test/regression/RegressionTest.cc @@ -45,7 +45,7 @@ void RegressionTest::createArchitecture(const char* source, const char* triple, // The process image is finalised by the createStack method // which creates and populates the initial process stack. // The created process image can be accessed via a shared_ptr - // returned by the getProcessImage method. + // returned by the getProcessImage method process_ = std::make_unique( simeng::span(reinterpret_cast(code_), codeSize_)); @@ -55,11 +55,11 @@ void RegressionTest::createArchitecture(const char* source, const char* triple, // This instance of procImgPtr pointer needs to be shared because // getMemoryValue in RegressionTest.hh uses reference to the class - // member processMemory_. + // member processMemory_ std::shared_ptr procImgPtr = process_->getProcessImage(); processMemory_ = procImgPtr.get(); - // Populate the heap with initial data (specified by the test being run). + // Populate the heap with initial data (specified by the test being run) ASSERT_LT(process_->getHeapStart() + initialHeapData_.size(), process_->getInitialStackPointer()); std::copy(initialHeapData_.begin(), initialHeapData_.end(), @@ -94,7 +94,7 @@ void RegressionTest::createCore(const char* source, const char* triple, // Create memory interfaces for instruction and data access. // For each memory interface, a dereferenced shared_ptr to the - // processImage is passed as an argument. + // processImage is passed as an argument ASSERT_TRUE(processMemory_ != nullptr);