diff --git a/src/include/simeng/Instruction.hh b/src/include/simeng/Instruction.hh index 0b326f0ee5..426e28b4b7 100644 --- a/src/include/simeng/Instruction.hh +++ b/src/include/simeng/Instruction.hh @@ -13,6 +13,19 @@ using InstructionException = short; namespace simeng { +/** A struct holding user-defined execution information for an + * instruction. */ +struct ExecutionInfo { + /** The latency for the instruction. */ + uint16_t latency = 1; + + /** The execution throughput for the instruction. */ + uint16_t stallCycles = 1; + + /** The ports that support the instruction. */ + std::vector ports = {}; +}; + /** An abstract instruction definition. * Each supported ISA should provide a derived implementation of this class. */ class Instruction { diff --git a/src/include/simeng/arch/Architecture.hh b/src/include/simeng/arch/Architecture.hh index f7f163815c..02b293bf25 100644 --- a/src/include/simeng/arch/Architecture.hh +++ b/src/include/simeng/arch/Architecture.hh @@ -7,6 +7,7 @@ #include "simeng/Core.hh" #include "simeng/Instruction.hh" #include "simeng/MemoryInterface.hh" +#include "simeng/kernel/Linux.hh" namespace simeng { @@ -59,6 +60,8 @@ class ExceptionHandler { * ISA should provide a derived implementation of this class. */ class Architecture { public: + Architecture(kernel::Linux& kernel) : linux_(kernel) {} + virtual ~Architecture(){}; /** Attempt to pre-decode from `bytesAvailable` bytes of instruction memory. @@ -90,6 +93,24 @@ class Architecture { /** Updates System registers of any system-based timers. */ virtual void updateSystemTimerRegisters(RegisterFileSet* regFile, const uint64_t iterations) const = 0; + + protected: + /** A Capstone decoding library handle, for decoding instructions. */ + csh capstoneHandle_; + + /** A reference to a Linux kernel object to forward syscalls to. */ + kernel::Linux& linux_; + + /** A mapping from system register encoding to a zero-indexed tag. */ + std::unordered_map systemRegisterMap_; + + /** A map to hold the relationship between instruction groups and + * user-defined execution information. */ + std::unordered_map groupExecutionInfo_; + + /** A map to hold the relationship between instruction opcode and + * user-defined execution information. */ + std::unordered_map opcodeExecutionInfo_; }; } // namespace arch diff --git a/src/include/simeng/arch/aarch64/Architecture.hh b/src/include/simeng/arch/aarch64/Architecture.hh index 6a46482e8e..cfba757341 100644 --- a/src/include/simeng/arch/aarch64/Architecture.hh +++ b/src/include/simeng/arch/aarch64/Architecture.hh @@ -7,7 +7,6 @@ #include "simeng/arch/Architecture.hh" #include "simeng/arch/aarch64/ExceptionHandler.hh" #include "simeng/arch/aarch64/MicroDecoder.hh" -#include "simeng/kernel/Linux.hh" using csh = size_t; @@ -20,7 +19,9 @@ class Architecture : public arch::Architecture { public: Architecture(kernel::Linux& kernel, ryml::ConstNodeRef config = config::SimInfo::getConfig()); + ~Architecture(); + /** Pre-decode instruction memory into a macro-op of `Instruction` * instances. Returns the number of bytes consumed to produce it (always 4), * and writes into the supplied macro-op vector. */ @@ -46,13 +47,6 @@ class Architecture : public arch::Architecture { /** Returns the maximum size of a valid instruction in bytes. */ uint8_t getMaxInstructionSize() const override; - /** Returns the current vector length set by the provided configuration. */ - uint64_t getVectorLength() const; - - /** Returns the current streaming vector length set by the provided - * configuration. */ - uint64_t getStreamingVectorLength() const; - /** Updates System registers of any system-based timers. */ void updateSystemTimerRegisters(RegisterFileSet* regFile, const uint64_t iterations) const override; @@ -61,7 +55,14 @@ class Architecture : public arch::Architecture { * opcode-based override has been defined for the latency and/or * port information, return that instead of the group-defined execution * information. */ - ExecutionInfo getExecutionInfo(Instruction& insn) const; + virtual ExecutionInfo getExecutionInfo(const Instruction& insn) const; + + /** Returns the current vector length set by the provided configuration. */ + uint64_t getVectorLength() const; + + /** Returns the current streaming vector length set by the provided + * configuration. */ + uint64_t getStreamingVectorLength() const; /** Returns the current value of SVCRval_. */ uint64_t getSVCRval() const; @@ -73,31 +74,12 @@ class Architecture : public arch::Architecture { /** A decoding cache, mapping an instruction word to a previously decoded * instruction. Instructions are added to the cache as they're decoded, to * reduce the overhead of future decoding. */ - static std::unordered_map decodeCache_; + mutable std::unordered_map decodeCache_; + /** A decoding metadata cache, mapping an instruction word to a previously * decoded instruction metadata bundle. Metadata is added to the cache as it's * decoded, to reduce the overhead of future decoding. */ - static std::forward_list metadataCache_; - - /** A copy of the value of the SVCR system register. */ - static uint64_t SVCRval_; - - /** A mapping from system register encoding to a zero-indexed tag. */ - std::unordered_map systemRegisterMap_; - - /** A map to hold the relationship between aarch64 instruction groups and - * user-defined execution information. */ - std::unordered_map groupExecutionInfo_; - - /** A map to hold the relationship between aarch64 instruction opcode and - * user-defined execution information. */ - std::unordered_map opcodeExecutionInfo_; - - /** A Capstone decoding library handle, for decoding instructions. */ - csh capstoneHandle_; - - /** A reference to a Linux kernel object to forward syscalls to. */ - kernel::Linux& linux_; + mutable std::forward_list metadataCache_; /** A reference to a micro decoder object to split macro operations. */ std::unique_ptr microDecoder_; @@ -108,6 +90,9 @@ class Architecture : public arch::Architecture { /** The streaming vector length used by the SME extension in bits. */ uint64_t SVL_; + /** A copy of the value of the SVCR system register. */ + mutable uint64_t SVCRval_ = 0; + /** System Register of Virtual Counter Timer. */ simeng::Register VCTreg_; diff --git a/src/include/simeng/arch/aarch64/Instruction.hh b/src/include/simeng/arch/aarch64/Instruction.hh index ddefb0ceb6..01224b3a72 100644 --- a/src/include/simeng/arch/aarch64/Instruction.hh +++ b/src/include/simeng/arch/aarch64/Instruction.hh @@ -176,19 +176,6 @@ const uint8_t MATRIX = 5; const Register ZERO_REGISTER = {GENERAL, (uint16_t)-1}; } // namespace RegisterType -/** A struct holding user-defined execution information for a aarch64 - * instruction. */ -struct ExecutionInfo { - /** The latency for the instruction. */ - uint16_t latency = 1; - - /** The execution throughput for the instruction. */ - uint16_t stallCycles = 1; - - /** The ports that support the instruction. */ - std::vector ports = {}; -}; - /** The various exceptions that can be raised by an individual instruction. */ enum class InstructionException { None = 0, diff --git a/src/include/simeng/arch/riscv/Architecture.hh b/src/include/simeng/arch/riscv/Architecture.hh index c78498a3f8..2e45be7cfa 100644 --- a/src/include/simeng/arch/riscv/Architecture.hh +++ b/src/include/simeng/arch/riscv/Architecture.hh @@ -6,7 +6,6 @@ #include "simeng/arch/Architecture.hh" #include "simeng/arch/riscv/ExceptionHandler.hh" #include "simeng/arch/riscv/Instruction.hh" -#include "simeng/kernel/Linux.hh" using csh = size_t; @@ -19,7 +18,9 @@ class Architecture : public arch::Architecture { public: Architecture(kernel::Linux& kernel, ryml::ConstNodeRef config = config::SimInfo::getConfig()); + ~Architecture(); + /** Pre-decode instruction memory into a macro-op of `Instruction` * instances. Returns the number of bytes consumed to produce it (always 4), * and writes into the supplied macro-op vector. */ @@ -49,37 +50,21 @@ class Architecture : public arch::Architecture { const uint64_t iterations) const override; private: - /** Retrieve an executionInfo object for the requested instruction. If a + /** Retrieve an ExecutionInfo object for the requested instruction. If a * opcode-based override has been defined for the latency and/or * port information, return that instead of the group-defined execution * information. */ - executionInfo getExecutionInfo(Instruction& insn) const; + ExecutionInfo getExecutionInfo(const Instruction& insn) const; /** A decoding cache, mapping an instruction word to a previously decoded * instruction. Instructions are added to the cache as they're decoded, to * reduce the overhead of future decoding. */ - static std::unordered_map decodeCache_; + mutable std::unordered_map decodeCache_; + /** A decoding metadata cache, mapping an instruction word to a previously * decoded instruction metadata bundle. Metadata is added to the cache as it's * decoded, to reduce the overhead of future decoding. */ - static std::forward_list metadataCache_; - - /** A mapping from system register encoding to a zero-indexed tag. */ - std::unordered_map systemRegisterMap_; - - /** A map to hold the relationship between aarch64 instruction groups and - * user-defined execution information. */ - std::unordered_map groupExecutionInfo_; - - /** A map to hold the relationship between aarch64 instruction opcode and - * user-defined execution information. */ - std::unordered_map opcodeExecutionInfo_; - - /** A Capstone decoding library handle, for decoding instructions. */ - csh capstoneHandle_; - - /** A reference to a Linux kernel object to forward syscalls to. */ - kernel::Linux& linux_; + mutable std::forward_list metadataCache_; /** System Register of Processor Cycle Counter. */ simeng::Register cycleSystemReg_; diff --git a/src/include/simeng/arch/riscv/Instruction.hh b/src/include/simeng/arch/riscv/Instruction.hh index d769fa7f69..93a90799ce 100644 --- a/src/include/simeng/arch/riscv/Instruction.hh +++ b/src/include/simeng/arch/riscv/Instruction.hh @@ -28,19 +28,6 @@ const uint8_t SYSTEM = 2; const Register ZERO_REGISTER = {GENERAL, (uint16_t)0}; } // namespace RegisterType -/** A struct holding user-defined execution information for a aarch64 - * instruction. */ -struct executionInfo { - /** The latency for the instruction. */ - uint16_t latency = 1; - - /** The execution throughput for the instruction. */ - uint16_t stallCycles = 1; - - /** The ports that support the instruction. */ - std::vector ports = {}; -}; - /** The various exceptions that can be raised by an individual instruction. */ enum class InstructionException { None = 0, @@ -158,7 +145,7 @@ class Instruction : public simeng::Instruction { /** Set this instruction's execution information including it's execution * latency and throughput, and the set of ports which support it. */ - void setExecutionInfo(const executionInfo& info); + void setExecutionInfo(const ExecutionInfo& info); /** Get this instruction's supported set of ports. */ const std::vector& getSupportedPorts() override; diff --git a/src/lib/arch/aarch64/Architecture.cc b/src/lib/arch/aarch64/Architecture.cc index abb02f0d14..9de2742594 100644 --- a/src/lib/arch/aarch64/Architecture.cc +++ b/src/lib/arch/aarch64/Architecture.cc @@ -7,12 +7,8 @@ namespace simeng { namespace arch { namespace aarch64 { -std::unordered_map Architecture::decodeCache_; -std::forward_list Architecture::metadataCache_; -uint64_t Architecture::SVCRval_; - Architecture::Architecture(kernel::Linux& kernel, ryml::ConstNodeRef config) - : linux_(kernel), + : arch::Architecture(kernel), microDecoder_(std::make_unique()), VL_(config["Core"]["Vector-Length"].as()), SVL_(config["Core"]["Streaming-Vector-Length"].as()), @@ -40,8 +36,8 @@ Architecture::Architecture(kernel::Linux& kernel, ryml::ConstNodeRef config) RegisterType::SYSTEM, static_cast(getSystemRegisterTag(ARM64_SYSREG_PMCCNTR_EL0))}; - // Instantiate an ExecutionInfo entry for each group in the InstructionGroup - // namespace. + // Instantiate an ExecutionInfo entry for each group in the + // InstructionGroup namespace. for (int i = 0; i < NUM_GROUPS; i++) { groupExecutionInfo_[i] = {1, 1, {}}; } @@ -56,8 +52,8 @@ Architecture::Architecture(kernel::Linux& kernel, ryml::ConstNodeRef config) uint16_t group = port_node["Instruction-Group-Nums"][j].as(); groupExecutionInfo_[group].latency = latency; groupExecutionInfo_[group].stallCycles = throughput; - // Set zero inheritance distance for latency assignment as it's explicitly - // defined + // Set zero inheritance distance for latency assignment as it's + // explicitly defined inheritanceDistance[group] = 0; // Add inherited support for those appropriate groups std::queue groups; @@ -127,23 +123,17 @@ Architecture::Architecture(kernel::Linux& kernel, ryml::ConstNodeRef config) ryml::ConstNodeRef opcode_node = config["Ports"][i]["Instruction-Opcode-Support"]; for (size_t j = 0; j < opcode_node.num_children(); j++) { - // If latency information hasn't been defined, set to zero as to inform - // later access to use group defined latencies instead + // If latency information hasn't been defined, set to zero as to + // inform later access to use group defined latencies instead uint16_t opcode = opcode_node[j].as(); - opcodeExecutionInfo_.try_emplace( - opcode, simeng::arch::aarch64::ExecutionInfo{0, 0, {}}); + opcodeExecutionInfo_.try_emplace(opcode, ExecutionInfo{0, 0, {}}); opcodeExecutionInfo_[opcode].ports.push_back(static_cast(i)); } } } } -Architecture::~Architecture() { - cs_close(&capstoneHandle_); - decodeCache_.clear(); - metadataCache_.clear(); - groupExecutionInfo_.clear(); - SVCRval_ = 0; -} + +Architecture::~Architecture() { cs_close(&capstoneHandle_); } uint8_t Architecture::predecode(const void* ptr, uint16_t bytesAvailable, uint64_t instructionAddress, @@ -212,27 +202,6 @@ uint8_t Architecture::predecode(const void* ptr, uint16_t bytesAvailable, return 4; } -ExecutionInfo Architecture::getExecutionInfo(Instruction& insn) const { - // Assume no opcode-based override - ExecutionInfo exeInfo = groupExecutionInfo_.at(insn.getGroup()); - if (opcodeExecutionInfo_.find(insn.getMetadata().opcode) != - opcodeExecutionInfo_.end()) { - // Replace with overrided values - ExecutionInfo overrideInfo = - opcodeExecutionInfo_.at(insn.getMetadata().opcode); - if (overrideInfo.latency != 0) exeInfo.latency = overrideInfo.latency; - if (overrideInfo.stallCycles != 0) - exeInfo.stallCycles = overrideInfo.stallCycles; - if (overrideInfo.ports.size()) exeInfo.ports = overrideInfo.ports; - } - return exeInfo; -} - -std::shared_ptr Architecture::handleException( - const std::shared_ptr& instruction, const Core& core, - MemoryInterface& memory) const { - return std::make_shared(instruction, core, memory, linux_); -} int32_t Architecture::getSystemRegisterTag(uint16_t reg) const { // Check below is done for speculative instructions that may be passed into // the function but will not be executed. If such invalid speculative @@ -241,6 +210,12 @@ int32_t Architecture::getSystemRegisterTag(uint16_t reg) const { return systemRegisterMap_.at(reg); } +std::shared_ptr Architecture::handleException( + const std::shared_ptr& instruction, const Core& core, + MemoryInterface& memory) const { + return std::make_shared(instruction, core, memory, linux_); +} + ProcessStateChange Architecture::getInitialState() const { ProcessStateChange changes; // Set ProcessStateChange type @@ -264,10 +239,6 @@ ProcessStateChange Architecture::getInitialState() const { uint8_t Architecture::getMaxInstructionSize() const { return 4; } -uint64_t Architecture::getVectorLength() const { return VL_; } - -uint64_t Architecture::getStreamingVectorLength() const { return SVL_; } - void Architecture::updateSystemTimerRegisters(RegisterFileSet* regFile, const uint64_t iterations) const { // Update the Processor Cycle Counter to total cycles completed. @@ -278,6 +249,26 @@ void Architecture::updateSystemTimerRegisters(RegisterFileSet* regFile, } } +ExecutionInfo Architecture::getExecutionInfo(const Instruction& insn) const { + // Assume no opcode-based override + ExecutionInfo exeInfo = groupExecutionInfo_.at(insn.getGroup()); + if (opcodeExecutionInfo_.find(insn.getMetadata().opcode) != + opcodeExecutionInfo_.end()) { + // Replace with overrided values + ExecutionInfo overrideInfo = + opcodeExecutionInfo_.at(insn.getMetadata().opcode); + if (overrideInfo.latency != 0) exeInfo.latency = overrideInfo.latency; + if (overrideInfo.stallCycles != 0) + exeInfo.stallCycles = overrideInfo.stallCycles; + if (overrideInfo.ports.size()) exeInfo.ports = overrideInfo.ports; + } + return exeInfo; +} + +uint64_t Architecture::getVectorLength() const { return VL_; } + +uint64_t Architecture::getStreamingVectorLength() const { return SVL_; } + /** The SVCR value is stored in Architecture to allow the value to be * retrieved within execution pipeline. This prevents adding an implicit * operand to every SME instruction; reducing the amount of complexity when diff --git a/src/lib/arch/riscv/Architecture.cc b/src/lib/arch/riscv/Architecture.cc index 81e720118a..01bce46fed 100644 --- a/src/lib/arch/riscv/Architecture.cc +++ b/src/lib/arch/riscv/Architecture.cc @@ -11,11 +11,8 @@ namespace simeng { namespace arch { namespace riscv { -std::unordered_map Architecture::decodeCache_; -std::forward_list Architecture::metadataCache_; - Architecture::Architecture(kernel::Linux& kernel, ryml::ConstNodeRef config) - : linux_(kernel) { + : arch::Architecture(kernel) { // Set initial rounding mode for F/D extensions // TODO set fcsr accordingly when Zicsr extension supported fesetround(FE_TONEAREST); @@ -40,7 +37,7 @@ Architecture::Architecture(kernel::Linux& kernel, ryml::ConstNodeRef config) RegisterType::SYSTEM, static_cast(getSystemRegisterTag(RISCV_SYSREG_CYCLE))}; - // Instantiate an executionInfo entry for each group in the InstructionGroup + // Instantiate an ExecutionInfo entry for each group in the InstructionGroup // namespace. for (int i = 0; i < NUM_GROUPS; i++) { groupExecutionInfo_[i] = {1, 1, {}}; @@ -131,19 +128,14 @@ Architecture::Architecture(kernel::Linux& kernel, ryml::ConstNodeRef config) // If latency information hasn't been defined, set to zero as to inform // later access to use group defined latencies instead uint16_t opcode = opcode_node[j].as(); - opcodeExecutionInfo_.try_emplace( - opcode, simeng::arch::riscv::executionInfo{0, 0, {}}); + opcodeExecutionInfo_.try_emplace(opcode, ExecutionInfo{0, 0, {}}); opcodeExecutionInfo_[opcode].ports.push_back(static_cast(i)); } } } } -Architecture::~Architecture() { - cs_close(&capstoneHandle_); - decodeCache_.clear(); - metadataCache_.clear(); - groupExecutionInfo_.clear(); -} + +Architecture::~Architecture() { cs_close(&capstoneHandle_); } uint8_t Architecture::predecode(const void* ptr, uint16_t bytesAvailable, uint64_t instructionAddress, @@ -210,28 +202,6 @@ uint8_t Architecture::predecode(const void* ptr, uint16_t bytesAvailable, return 4; } -executionInfo Architecture::getExecutionInfo(Instruction& insn) const { - // Assume no opcode-based override - executionInfo exeInfo = groupExecutionInfo_.at(insn.getGroup()); - if (opcodeExecutionInfo_.find(insn.getMetadata().opcode) != - opcodeExecutionInfo_.end()) { - // Replace with overrided values - executionInfo overrideInfo = - opcodeExecutionInfo_.at(insn.getMetadata().opcode); - if (overrideInfo.latency != 0) exeInfo.latency = overrideInfo.latency; - if (overrideInfo.stallCycles != 0) - exeInfo.stallCycles = overrideInfo.stallCycles; - if (overrideInfo.ports.size()) exeInfo.ports = overrideInfo.ports; - } - return exeInfo; -} - -std::shared_ptr Architecture::handleException( - const std::shared_ptr& instruction, const Core& core, - MemoryInterface& memory) const { - return std::make_shared(instruction, core, memory, linux_); -} - int32_t Architecture::getSystemRegisterTag(uint16_t reg) const { // Check below is done for speculative instructions that may be passed into // the function but will not be executed. If such invalid speculative @@ -240,6 +210,12 @@ int32_t Architecture::getSystemRegisterTag(uint16_t reg) const { return systemRegisterMap_.at(reg); } +std::shared_ptr Architecture::handleException( + const std::shared_ptr& instruction, const Core& core, + MemoryInterface& memory) const { + return std::make_shared(instruction, core, memory, linux_); +} + ProcessStateChange Architecture::getInitialState() const { ProcessStateChange changes; // Set ProcessStateChange type @@ -260,6 +236,22 @@ void Architecture::updateSystemTimerRegisters(RegisterFileSet* regFile, regFile->set(cycleSystemReg_, iterations); } +ExecutionInfo Architecture::getExecutionInfo(const Instruction& insn) const { + // Assume no opcode-based override + ExecutionInfo exeInfo = groupExecutionInfo_.at(insn.getGroup()); + if (opcodeExecutionInfo_.find(insn.getMetadata().opcode) != + opcodeExecutionInfo_.end()) { + // Replace with overrided values + ExecutionInfo overrideInfo = + opcodeExecutionInfo_.at(insn.getMetadata().opcode); + if (overrideInfo.latency != 0) exeInfo.latency = overrideInfo.latency; + if (overrideInfo.stallCycles != 0) + exeInfo.stallCycles = overrideInfo.stallCycles; + if (overrideInfo.ports.size()) exeInfo.ports = overrideInfo.ports; + } + return exeInfo; +} + } // namespace riscv } // namespace arch } // namespace simeng diff --git a/src/lib/arch/riscv/Instruction.cc b/src/lib/arch/riscv/Instruction.cc index cccba60b86..fdf6ce680d 100644 --- a/src/lib/arch/riscv/Instruction.cc +++ b/src/lib/arch/riscv/Instruction.cc @@ -149,7 +149,7 @@ uint16_t Instruction::getGroup() const { return base + 2; // Default return is {Data type}_SIMPLE_ARTH } -void Instruction::setExecutionInfo(const executionInfo& info) { +void Instruction::setExecutionInfo(const ExecutionInfo& info) { if (isLoad_ || isStore_) { lsqExecutionLatency_ = info.latency; } else { diff --git a/test/unit/MockArchitecture.hh b/test/unit/MockArchitecture.hh index 7795571f2f..fb26a60b91 100644 --- a/test/unit/MockArchitecture.hh +++ b/test/unit/MockArchitecture.hh @@ -8,6 +8,7 @@ namespace simeng { /** Mock implementation of the `Architecture` interface. */ class MockArchitecture : public arch::Architecture { public: + MockArchitecture(kernel::Linux& kernel) : arch::Architecture(kernel) {} MOCK_CONST_METHOD4(predecode, uint8_t(const void* ptr, uint16_t bytesAvailable, uint64_t instructionAddress, MacroOp& output)); diff --git a/test/unit/aarch64/InstructionTest.cc b/test/unit/aarch64/InstructionTest.cc index 20dddcca18..1613262588 100644 --- a/test/unit/aarch64/InstructionTest.cc +++ b/test/unit/aarch64/InstructionTest.cc @@ -1,5 +1,4 @@ #include "../ConfigInit.hh" -#include "../MockArchitecture.hh" #include "arch/aarch64/InstructionMetadata.hh" #include "gmock/gmock.h" #include "simeng/arch/aarch64/Instruction.hh" diff --git a/test/unit/pipeline/FetchUnitTest.cc b/test/unit/pipeline/FetchUnitTest.cc index f404029640..5ef3e23ed3 100644 --- a/test/unit/pipeline/FetchUnitTest.cc +++ b/test/unit/pipeline/FetchUnitTest.cc @@ -29,6 +29,9 @@ class PipelineFetchUnitTest : public testing::Test { public: PipelineFetchUnitTest() : output(1, {}), + linux(config::SimInfo::getConfig()["CPU-Info"]["Special-File-Dir-Path"] + .as()), + isa(linux), fetchBuffer({{0, 16}, 0, 0}), completedReads(&fetchBuffer, 1), fetchUnit(output, memory, 1024, 0, blockSize, isa, predictor), @@ -45,6 +48,7 @@ class PipelineFetchUnitTest : public testing::Test { PipelineBuffer output; MockMemoryInterface memory; + kernel::Linux linux; MockArchitecture isa; MockBranchPredictor predictor; diff --git a/test/unit/riscv/InstructionTest.cc b/test/unit/riscv/InstructionTest.cc index 37580c4f80..baf8073402 100644 --- a/test/unit/riscv/InstructionTest.cc +++ b/test/unit/riscv/InstructionTest.cc @@ -1,5 +1,4 @@ #include "../ConfigInit.hh" -#include "../MockArchitecture.hh" #include "arch/riscv/InstructionMetadata.hh" #include "gmock/gmock.h" #include "simeng/arch/riscv/Instruction.hh"