From f5f277af692840a50136f0b3e2a8f5b2f3bf24fd Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Fri, 16 Feb 2024 11:31:28 +0000 Subject: [PATCH 1/5] Initial RISC-V OoO implementation --- src/include/simeng/Instruction.hh | 8 +++++ .../simeng/arch/aarch64/Instruction.hh | 2 ++ .../simeng/arch/riscv/ExceptionHandler.hh | 2 +- src/include/simeng/arch/riscv/Instruction.hh | 2 ++ src/include/simeng/pipeline/ReorderBuffer.hh | 1 + src/lib/Instruction.cc | 7 +++++ src/lib/arch/aarch64/Instruction_execute.cc | 3 ++ src/lib/arch/riscv/ExceptionHandler.cc | 12 ++++++-- src/lib/arch/riscv/Instruction.cc | 12 ++++++++ src/lib/models/outoforder/Core.cc | 17 ++++++++++- src/lib/pipeline/DecodeUnit.cc | 2 ++ src/lib/pipeline/DispatchIssueUnit.cc | 4 +++ src/lib/pipeline/ExecuteUnit.cc | 5 ++++ src/lib/pipeline/FetchUnit.cc | 2 ++ src/lib/pipeline/LoadStoreQueue.cc | 2 ++ src/lib/pipeline/MappedRegisterFileSet.cc | 1 + src/lib/pipeline/RenameUnit.cc | 2 ++ src/lib/pipeline/ReorderBuffer.cc | 14 +++++++-- src/lib/pipeline/WritebackUnit.cc | 7 +++++ test/regression/riscv/CMakeLists.txt | 4 ++- test/regression/riscv/instructions/csr.cc | 30 +++++++++++++++++++ 21 files changed, 132 insertions(+), 7 deletions(-) create mode 100644 test/regression/riscv/instructions/csr.cc diff --git a/src/include/simeng/Instruction.hh b/src/include/simeng/Instruction.hh index 0b326f0ee5..423d77aaeb 100644 --- a/src/include/simeng/Instruction.hh +++ b/src/include/simeng/Instruction.hh @@ -23,6 +23,8 @@ class Instruction { * instruction. */ bool exceptionEncountered() const; + void setExceptionEncounteredFalse(); + /** Retrieve the source registers this instruction reads. */ virtual const span getSourceRegisters() const = 0; @@ -63,6 +65,9 @@ class Instruction { /** Mark the instruction as ready to commit. */ void setCommitReady(); + /** Mark the instruction as NOT ready to commit. */ + void setNotCommitReady(); + /** Check whether the instruction has written its values back and is ready to * commit. */ bool canCommit() const; @@ -70,6 +75,9 @@ class Instruction { /** Retrieve register results. */ virtual const span getResults() const = 0; + /** Set results array */ + virtual void setResults(span resultsInput) = 0; + /** Generate memory addresses this instruction wishes to access. */ virtual span generateAddresses() = 0; diff --git a/src/include/simeng/arch/aarch64/Instruction.hh b/src/include/simeng/arch/aarch64/Instruction.hh index 92ac0bc96d..1830d13768 100644 --- a/src/include/simeng/arch/aarch64/Instruction.hh +++ b/src/include/simeng/arch/aarch64/Instruction.hh @@ -283,6 +283,8 @@ class Instruction : public simeng::Instruction { /** Retrieve register results. */ const span getResults() const override; + void setResults(span resultsInput) override; + /** Generate memory addresses this instruction wishes to access. */ span generateAddresses() override; diff --git a/src/include/simeng/arch/riscv/ExceptionHandler.hh b/src/include/simeng/arch/riscv/ExceptionHandler.hh index c422f0e8b6..81153f51b0 100644 --- a/src/include/simeng/arch/riscv/ExceptionHandler.hh +++ b/src/include/simeng/arch/riscv/ExceptionHandler.hh @@ -72,7 +72,7 @@ class ExceptionHandler : public simeng::arch::ExceptionHandler { bool fatal(); /** The instruction generating an exception. */ - const Instruction& instruction_; + Instruction& instruction_; /** The core model object. */ const Core& core; diff --git a/src/include/simeng/arch/riscv/Instruction.hh b/src/include/simeng/arch/riscv/Instruction.hh index b3064d6b48..ba229e5ba1 100644 --- a/src/include/simeng/arch/riscv/Instruction.hh +++ b/src/include/simeng/arch/riscv/Instruction.hh @@ -110,6 +110,8 @@ class Instruction : public simeng::Instruction { /** Retrieve register results. */ const span getResults() const override; + void setResults(span resultsInput) override; + /** Generate memory addresses this instruction wishes to access. */ span generateAddresses() override; diff --git a/src/include/simeng/pipeline/ReorderBuffer.hh b/src/include/simeng/pipeline/ReorderBuffer.hh index a98471c2e8..f9d8399062 100644 --- a/src/include/simeng/pipeline/ReorderBuffer.hh +++ b/src/include/simeng/pipeline/ReorderBuffer.hh @@ -56,6 +56,7 @@ class ReorderBuffer { void commitMicroOps(uint64_t insnId); /** Commit and remove up to `maxCommitSize` instructions. */ + // TODO is return value ever used?? Only in tests !? unsigned int commit(unsigned int maxCommitSize); /** Flush all instructions with a sequence ID greater than `afterSeqId`. */ diff --git a/src/lib/Instruction.cc b/src/lib/Instruction.cc index ac923c11b2..c118ccd281 100644 --- a/src/lib/Instruction.cc +++ b/src/lib/Instruction.cc @@ -44,6 +44,7 @@ bool Instruction::isFlushed() const { return flushed_; } bool Instruction::hasExecuted() const { return executed_; } void Instruction::setCommitReady() { canCommit_ = true; } +void Instruction::setNotCommitReady() { canCommit_ = false; } bool Instruction::canCommit() const { return canCommit_; } bool Instruction::hasAllData() const { return (dataPending_ == 0); } @@ -54,8 +55,14 @@ uint16_t Instruction::getStallCycles() const { return stallCycles_; } bool Instruction::isMicroOp() const { return isMicroOp_; } bool Instruction::isLastMicroOp() const { return isLastMicroOp_; } + void Instruction::setWaitingCommit() { waitingCommit_ = true; } bool Instruction::isWaitingCommit() const { return waitingCommit_; } + int Instruction::getMicroOpIndex() const { return microOpIndex_; } +void Instruction::setExceptionEncounteredFalse() { + exceptionEncountered_ = false; +} + } // namespace simeng diff --git a/src/lib/arch/aarch64/Instruction_execute.cc b/src/lib/arch/aarch64/Instruction_execute.cc index 8df30451b6..38991f6643 100644 --- a/src/lib/arch/aarch64/Instruction_execute.cc +++ b/src/lib/arch/aarch64/Instruction_execute.cc @@ -5735,6 +5735,9 @@ void Instruction::execute() { } #endif } +void Instruction::setResults(span resultsInput) { + // TODO implement this +} } // namespace aarch64 } // namespace arch diff --git a/src/lib/arch/riscv/ExceptionHandler.cc b/src/lib/arch/riscv/ExceptionHandler.cc index b6ebcbb924..c7ad30910e 100644 --- a/src/lib/arch/riscv/ExceptionHandler.cc +++ b/src/lib/arch/riscv/ExceptionHandler.cc @@ -699,9 +699,17 @@ bool ExceptionHandler::init() { // Only update if registers should be written to if (destinationRegs.size() > 0) { + std::cerr << "handler opcode = " + << instruction_.getMetadata().mnemonic + << " id = " << instruction_.getSequenceId() << std::endl; + + RegisterValue r[]{RegisterValue(result, 8)}; + span res{r, std::size(r)}; + instruction_.setResults(res); // Dummy logic to allow progression. Set Rd to 0 - stateChange = { - ChangeType::REPLACEMENT, {destinationRegs[0]}, {result}}; + // stateChange = { + // ChangeType::REPLACEMENT, {destinationRegs[0]}, + // {result}}; } break; default: diff --git a/src/lib/arch/riscv/Instruction.cc b/src/lib/arch/riscv/Instruction.cc index 2c2eaf78cb..9239bf2a3d 100644 --- a/src/lib/arch/riscv/Instruction.cc +++ b/src/lib/arch/riscv/Instruction.cc @@ -92,6 +92,18 @@ const span Instruction::getResults() const { return {const_cast(results.data()), destinationRegisterCount}; } +void Instruction::setResults(span resultsInput) { + assert(resultsInput.size() <= results.size() && + "[SimEng:Instruction] More results than size of array"); + uint8_t n = 0; + for (auto result : resultsInput) { + std::cerr << "result = " << result.get() << std::endl; + + results[n] = result; + n++; + } +} + bool Instruction::isStoreAddress() const { return isStore_; } bool Instruction::isStoreData() const { return isStore_; } bool Instruction::isLoad() const { return isLoad_; } diff --git a/src/lib/models/outoforder/Core.cc b/src/lib/models/outoforder/Core.cc index 83a9dd9cda..cf6df51b98 100644 --- a/src/lib/models/outoforder/Core.cc +++ b/src/lib/models/outoforder/Core.cc @@ -34,7 +34,7 @@ Core::Core(MemoryInterface& instructionMemory, MemoryInterface& dataMemory, issuePorts_(config["Execution-Units"].num_children(), {1, nullptr}), completionSlots_( config["Execution-Units"].num_children() + - config["Pipeline-Widths"]["LSQ-Completion"].as(), + config["Pipeline-Widths"]["LSQ-Completion"].as() + 1, {1, nullptr}), loadStoreQueue_( config["Queue-Sizes"]["Load"].as(), @@ -106,6 +106,8 @@ Core::Core(MemoryInterface& instructionMemory, MemoryInterface& dataMemory, }; void Core::tick() { + std::cerr << "---- core tick ----" << std::endl; + ticks_++; if (hasHalted_) return; @@ -155,6 +157,9 @@ void Core::tick() { if (exceptionGenerated_) { handleException(); + // TODO why do we request from PC when we know we will flush later. Would it + // be quicker to stall. Flush (and no other unit) never ticked until + // exception complete. Process exceptionHandler only flushes loop buffer fetchUnit_.requestFromPC(); return; } @@ -277,6 +282,8 @@ void Core::handleException() { // Flush everything younger than the exception-generating instruction. // This must happen prior to handling the exception to ensure the commit state // is up-to-date with the register mapping table + // TODO THIS BASICALLY JUST EMPTIES THE ROB, exceptionGeneratingInstruction + // has already been removed (in current form) reorderBuffer_.flush(exceptionGeneratingInstruction_->getInstructionId()); decodeUnit_.purgeFlushed(); dispatchIssueUnit_.purgeFlushed(); @@ -285,6 +292,7 @@ void Core::handleException() { eu.purgeFlushed(); } + // TODO possible change here exceptionGenerated_ = false; exceptionHandler_ = isa_.handleException(exceptionGeneratingInstruction_, *this, dataMemory_); @@ -306,6 +314,7 @@ void Core::processExceptionHandler() { return; } + // TODO don't need to get the state change const auto& result = exceptionHandler_->getResult(); if (result.fatal) { @@ -314,6 +323,7 @@ void Core::processExceptionHandler() { } else { fetchUnit_.flushLoopBuffer(); fetchUnit_.updatePC(result.instructionAddress); + // TODO won't need to apply state change applyStateChange(result.stateChange); } @@ -321,6 +331,11 @@ void Core::processExceptionHandler() { } void Core::applyStateChange(const arch::ProcessStateChange& change) { + completionSlots_[completionSlots_.size() - 1].getTailSlots()[0] = + std::move(exceptionGeneratingInstruction_); + + return; + // Update registers in accordance with the ProcessStateChange type switch (change.type) { case arch::ChangeType::INCREMENT: { diff --git a/src/lib/pipeline/DecodeUnit.cc b/src/lib/pipeline/DecodeUnit.cc index 5bb497e653..6541a6e676 100644 --- a/src/lib/pipeline/DecodeUnit.cc +++ b/src/lib/pipeline/DecodeUnit.cc @@ -11,6 +11,8 @@ DecodeUnit::DecodeUnit(PipelineBuffer& input, : input_(input), output_(output), predictor_(predictor){}; void DecodeUnit::tick() { + std::cerr << "decode" << std::endl; + // Stall if output buffer is stalled if (output_.isStalled()) { input_.stall(true); diff --git a/src/lib/pipeline/DispatchIssueUnit.cc b/src/lib/pipeline/DispatchIssueUnit.cc index afd7390215..623dc66c25 100644 --- a/src/lib/pipeline/DispatchIssueUnit.cc +++ b/src/lib/pipeline/DispatchIssueUnit.cc @@ -56,6 +56,8 @@ DispatchIssueUnit::DispatchIssueUnit( } void DispatchIssueUnit::tick() { + std::cerr << "dispatch tick" << std::endl; + input_.stall(false); // Reset the array @@ -134,6 +136,8 @@ void DispatchIssueUnit::tick() { } void DispatchIssueUnit::issue() { + std::cerr << "dispatch issue" << std::endl; + int issued = 0; // Check the ready queues, and issue an instruction from each if the // corresponding port isn't blocked diff --git a/src/lib/pipeline/ExecuteUnit.cc b/src/lib/pipeline/ExecuteUnit.cc index c87c2e1845..3b639c47eb 100644 --- a/src/lib/pipeline/ExecuteUnit.cc +++ b/src/lib/pipeline/ExecuteUnit.cc @@ -26,6 +26,8 @@ ExecuteUnit::ExecuteUnit( blockingGroups_(blockingGroups) {} void ExecuteUnit::tick() { + std::cerr << "execute" << std::endl; + tickCounter_++; shouldFlush_ = false; @@ -133,6 +135,9 @@ void ExecuteUnit::execute(std::shared_ptr& uop) { } if (uop->exceptionEncountered()) { + std::cerr << "Execute exception encountered, don't forward results" + << std::endl; + // Exception; don't forward results, don't pass uop forward raiseException_(uop); return; diff --git a/src/lib/pipeline/FetchUnit.cc b/src/lib/pipeline/FetchUnit.cc index 2da1ada097..c4b0888fed 100644 --- a/src/lib/pipeline/FetchUnit.cc +++ b/src/lib/pipeline/FetchUnit.cc @@ -25,6 +25,8 @@ FetchUnit::FetchUnit(PipelineBuffer& output, FetchUnit::~FetchUnit() { delete[] fetchBuffer_; } void FetchUnit::tick() { + std::cerr << "fetch" << std::endl; + if (output_.isStalled()) { return; } diff --git a/src/lib/pipeline/LoadStoreQueue.cc b/src/lib/pipeline/LoadStoreQueue.cc index 0a5dbb91e3..63cbc8f244 100644 --- a/src/lib/pipeline/LoadStoreQueue.cc +++ b/src/lib/pipeline/LoadStoreQueue.cc @@ -380,6 +380,8 @@ void LoadStoreQueue::purgeFlushed() { } void LoadStoreQueue::tick() { + std::cerr << "lsq" << std::endl; + tickCounter_++; // Send memory requests adhering to set bandwidth and number of permitted // requests per cycle diff --git a/src/lib/pipeline/MappedRegisterFileSet.cc b/src/lib/pipeline/MappedRegisterFileSet.cc index db75641beb..313cb4e0df 100644 --- a/src/lib/pipeline/MappedRegisterFileSet.cc +++ b/src/lib/pipeline/MappedRegisterFileSet.cc @@ -12,6 +12,7 @@ const RegisterValue& MappedRegisterFileSet::get(Register reg) const { } void MappedRegisterFileSet::set(Register reg, const RegisterValue& value) { + assert(!reg.renamed && "renamed register passed to set"); return ArchitecturalRegisterFileSet::set(rat_.getMapping(reg), value); } diff --git a/src/lib/pipeline/RenameUnit.cc b/src/lib/pipeline/RenameUnit.cc index 6cbf0add4a..af5f5f4c6a 100644 --- a/src/lib/pipeline/RenameUnit.cc +++ b/src/lib/pipeline/RenameUnit.cc @@ -18,6 +18,8 @@ RenameUnit::RenameUnit(PipelineBuffer>& fromDecode, freeRegistersAvailable_(registerTypes) {} void RenameUnit::tick() { + std::cerr << "rename" << std::endl; + if (output_.isStalled()) { input_.stall(true); return; diff --git a/src/lib/pipeline/ReorderBuffer.cc b/src/lib/pipeline/ReorderBuffer.cc index a706bab866..839be3fd90 100644 --- a/src/lib/pipeline/ReorderBuffer.cc +++ b/src/lib/pipeline/ReorderBuffer.cc @@ -71,6 +71,8 @@ void ReorderBuffer::commitMicroOps(uint64_t insnId) { } unsigned int ReorderBuffer::commit(unsigned int maxCommitSize) { + std::cerr << "commit" << std::endl; + shouldFlush_ = false; size_t maxCommits = std::min(static_cast(maxCommitSize), buffer_.size()); @@ -82,12 +84,20 @@ unsigned int ReorderBuffer::commit(unsigned int maxCommitSize) { break; } + std::cerr << "attempting commit of id=" << uop->getInstructionId() + << std::endl; + if (uop->isLastMicroOp()) instructionsCommitted_++; if (uop->exceptionEncountered()) { + std::cerr << "EXCEPTION ENCOUNTERED" << std::endl; + raiseException_(uop); - buffer_.pop_front(); - return n + 1; + uop->setExceptionEncounteredFalse(); + uop->setNotCommitReady(); + + // Need to send back through writeback + return n; } const auto& destinations = uop->getDestinationRegisters(); diff --git a/src/lib/pipeline/WritebackUnit.cc b/src/lib/pipeline/WritebackUnit.cc index 1176793fcd..bf78094b46 100644 --- a/src/lib/pipeline/WritebackUnit.cc +++ b/src/lib/pipeline/WritebackUnit.cc @@ -14,6 +14,8 @@ WritebackUnit::WritebackUnit( flagMicroOpCommits_(flagMicroOpCommits) {} void WritebackUnit::tick() { + std::cerr << "writeback" << std::endl; + for (size_t slot = 0; slot < completionSlots_.size(); slot++) { auto& uop = completionSlots_[slot].getHeadSlots()[0]; @@ -21,7 +23,12 @@ void WritebackUnit::tick() { continue; } + std::cerr << "writeback id = " << uop->getSequenceId() << std::endl; + auto& results = uop->getResults(); + std::cerr << "writeback results = " << results[0].get() + << std::endl; + auto& destinations = uop->getDestinationRegisters(); for (size_t i = 0; i < results.size(); i++) { // Write results to register file diff --git a/test/regression/riscv/CMakeLists.txt b/test/regression/riscv/CMakeLists.txt index f97441b867..18faeb0152 100644 --- a/test/regression/riscv/CMakeLists.txt +++ b/test/regression/riscv/CMakeLists.txt @@ -11,9 +11,11 @@ add_executable(regression-riscv instructions/store.cc instructions/jump.cc instructions/branch.cc + instructions/csr.cc instructions/atomic.cc instructions/float.cc - ) + instructions/csr.cc +) target_include_directories(regression-riscv PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) target_link_libraries(regression-riscv regression-test-base) diff --git a/test/regression/riscv/instructions/csr.cc b/test/regression/riscv/instructions/csr.cc new file mode 100644 index 0000000000..a90d708592 --- /dev/null +++ b/test/regression/riscv/instructions/csr.cc @@ -0,0 +1,30 @@ +#include "RISCVRegressionTest.hh" + +namespace { + +using InstCSR = RISCVRegressionTest; + +TEST_P(InstCSR, basicCsr) { + std::cerr << "NEW TEST" << std::endl; + std::cerr << "" << std::endl; + std::cerr << "" << std::endl; + + RUN_RISCV(R"( + li x8, 1 + csrrw x9, frm, x8 + )"); + EXPECT_EQ(getGeneralRegister(8), 1); + EXPECT_EQ(getGeneralRegister(9), 0b100000); +} + +INSTANTIATE_TEST_SUITE_P( + RISCV, InstCSR, + ::testing::Values( + // std::make_tuple(EMULATION, "{}"), + // std::make_tuple(INORDER, "{}"), + std::make_tuple(OUTOFORDER, "{}")), + // "{Ports: {'0': {Portname: 0, Instruction-Group-Support: [INT, + // " "LOAD, STORE, BRANCH]}}}")), + paramToString); + +} // namespace \ No newline at end of file From fd9a8b3195b98b5e6ac5fbbcc3118eba952f89b9 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Fri, 16 Feb 2024 16:46:28 +0000 Subject: [PATCH 2/5] True dependency after pipeline flush fix --- src/include/simeng/Instruction.hh | 4 +- src/include/simeng/arch/Architecture.hh | 2 +- .../simeng/arch/aarch64/Instruction.hh | 3 +- src/include/simeng/arch/riscv/Instruction.hh | 3 +- src/lib/arch/aarch64/Instruction.cc | 5 ++- src/lib/arch/riscv/ExceptionHandler.cc | 3 ++ src/lib/arch/riscv/Instruction.cc | 8 +++- src/lib/arch/riscv/Instruction_execute.cc | 3 ++ src/lib/models/emulation/Core.cc | 10 ++++- src/lib/models/inorder/Core.cc | 4 +- src/lib/models/outoforder/Core.cc | 37 +++++++++++++++++-- src/lib/pipeline/DecodeUnit.cc | 2 +- src/lib/pipeline/DispatchIssueUnit.cc | 20 ++++++++-- src/lib/pipeline/ExecuteUnit.cc | 6 +-- src/lib/pipeline/FetchUnit.cc | 4 +- src/lib/pipeline/LoadStoreQueue.cc | 2 +- src/lib/pipeline/RegisterAliasTable.cc | 10 +++++ src/lib/pipeline/RenameUnit.cc | 17 ++++++++- src/lib/pipeline/ReorderBuffer.cc | 10 ++++- src/lib/pipeline/WritebackUnit.cc | 13 +++++-- test/regression/RegressionTest.cc | 2 + test/regression/riscv/instructions/csr.cc | 6 ++- test/unit/MockInstruction.hh | 4 +- test/unit/aarch64/InstructionTest.cc | 26 ++++++------- test/unit/riscv/InstructionTest.cc | 22 +++++------ 25 files changed, 172 insertions(+), 54 deletions(-) diff --git a/src/include/simeng/Instruction.hh b/src/include/simeng/Instruction.hh index 423d77aaeb..fbfc6afb91 100644 --- a/src/include/simeng/Instruction.hh +++ b/src/include/simeng/Instruction.hh @@ -25,6 +25,8 @@ class Instruction { void setExceptionEncounteredFalse(); + virtual void printInstructionInfo() = 0; + /** Retrieve the source registers this instruction reads. */ virtual const span getSourceRegisters() const = 0; @@ -49,7 +51,7 @@ class Instruction { virtual void supplyOperand(uint16_t i, const RegisterValue& value) = 0; /** Check whether the operand at index `i` has had a value supplied. */ - virtual bool isOperandReady(int i) const = 0; + virtual bool isSourceOperandReady(int i) const = 0; /** Check whether all operand values have been supplied, and the instruction * is ready to execute. */ diff --git a/src/include/simeng/arch/Architecture.hh b/src/include/simeng/arch/Architecture.hh index f7f163815c..79241e416a 100644 --- a/src/include/simeng/arch/Architecture.hh +++ b/src/include/simeng/arch/Architecture.hh @@ -15,7 +15,7 @@ using MacroOp = std::vector>; namespace arch { /** The types of changes that can be made to values within the process state. */ -enum class ChangeType { REPLACEMENT, INCREMENT, DECREMENT }; +enum class ChangeType { REPLACEMENT, INCREMENT, DECREMENT, WRITEBACK }; /** A structure describing a set of changes to the process state. */ struct ProcessStateChange { diff --git a/src/include/simeng/arch/aarch64/Instruction.hh b/src/include/simeng/arch/aarch64/Instruction.hh index 1830d13768..078d4c9509 100644 --- a/src/include/simeng/arch/aarch64/Instruction.hh +++ b/src/include/simeng/arch/aarch64/Instruction.hh @@ -260,7 +260,7 @@ class Instruction : public simeng::Instruction { const span getDestinationRegisters() const override; /** Check whether the operand at index `i` has had a value supplied. */ - bool isOperandReady(int index) const override; + bool isSourceOperandReady(int index) const override; /** Override the specified source register with a renamed physical register. */ @@ -337,6 +337,7 @@ class Instruction : public simeng::Instruction { /** Retrieve the instruction's associated architecture. */ const Architecture& getArchitecture() const; + void printInstructionInfo() override; private: /** A reference to the ISA instance this instruction belongs to. */ diff --git a/src/include/simeng/arch/riscv/Instruction.hh b/src/include/simeng/arch/riscv/Instruction.hh index ba229e5ba1..abae7693ee 100644 --- a/src/include/simeng/arch/riscv/Instruction.hh +++ b/src/include/simeng/arch/riscv/Instruction.hh @@ -87,7 +87,7 @@ class Instruction : public simeng::Instruction { const span getDestinationRegisters() const override; /** Check whether the operand at index `i` has had a value supplied. */ - bool isOperandReady(int index) const override; + bool isSourceOperandReady(int index) const override; /** Override the specified source register with a renamed physical register. */ @@ -170,6 +170,7 @@ class Instruction : public simeng::Instruction { /** Retrieve the instruction's associated architecture. */ const Architecture& getArchitecture() const; + void printInstructionInfo() override; /** The maximum number of source registers any supported RISC-V instruction * can have. */ diff --git a/src/lib/arch/aarch64/Instruction.cc b/src/lib/arch/aarch64/Instruction.cc index df4e55c07f..1800e59714 100644 --- a/src/lib/arch/aarch64/Instruction.cc +++ b/src/lib/arch/aarch64/Instruction.cc @@ -41,6 +41,9 @@ const span Instruction::getSourceRegisters() const { const span Instruction::getSourceOperands() const { return {const_cast(operands.data()), operands.size()}; } +void Instruction::printInstructionInfo() { + std::cerr << metadata.mnemonic << " " << metadata.operandStr << std::endl; +} const span Instruction::getDestinationRegisters() const { // The `destinationRegisterCount` is used here as the span count value because @@ -50,7 +53,7 @@ const span Instruction::getDestinationRegisters() const { return {const_cast(destinationRegisters.data()), destinationRegisterCount}; } -bool Instruction::isOperandReady(int index) const { +bool Instruction::isSourceOperandReady(int index) const { return static_cast(operands[index]); } diff --git a/src/lib/arch/riscv/ExceptionHandler.cc b/src/lib/arch/riscv/ExceptionHandler.cc index c7ad30910e..1abd60f461 100644 --- a/src/lib/arch/riscv/ExceptionHandler.cc +++ b/src/lib/arch/riscv/ExceptionHandler.cc @@ -706,6 +706,9 @@ bool ExceptionHandler::init() { RegisterValue r[]{RegisterValue(result, 8)}; span res{r, std::size(r)}; instruction_.setResults(res); + // Send instruction through writeback for resolution of renamed + // registers + stateChange = {ChangeType::WRITEBACK, {}, {}}; // Dummy logic to allow progression. Set Rd to 0 // stateChange = { // ChangeType::REPLACEMENT, {destinationRegs[0]}, diff --git a/src/lib/arch/riscv/Instruction.cc b/src/lib/arch/riscv/Instruction.cc index 9239bf2a3d..c001738671 100644 --- a/src/lib/arch/riscv/Instruction.cc +++ b/src/lib/arch/riscv/Instruction.cc @@ -42,12 +42,15 @@ const span Instruction::getDestinationRegisters() const { destinationRegisterCount}; } -bool Instruction::isOperandReady(int index) const { +bool Instruction::isSourceOperandReady(int index) const { + // TODO casting registerValue to bool seems bad return static_cast(operands[index]); } void Instruction::renameSource(uint16_t i, Register renamed) { sourceRegisters[i] = renamed; + std::cerr << "renamed source " << renamed << " renamed = " << renamed.renamed + << std::endl; } void Instruction::renameDestination(uint16_t i, Register renamed) { destinationRegisters[i] = renamed; @@ -117,6 +120,9 @@ void Instruction::setMemoryAddresses( memoryAddresses = addresses; dataPending_ = addresses.size(); } +void Instruction::printInstructionInfo() { + std::cerr << metadata.mnemonic << " " << metadata.operandStr << std::endl; +} span Instruction::getGeneratedAddresses() const { return {memoryAddresses.data(), memoryAddresses.size()}; diff --git a/src/lib/arch/riscv/Instruction_execute.cc b/src/lib/arch/riscv/Instruction_execute.cc index d5ae0b37f5..5b694ab71c 100644 --- a/src/lib/arch/riscv/Instruction_execute.cc +++ b/src/lib/arch/riscv/Instruction_execute.cc @@ -179,6 +179,9 @@ void Instruction::execute() { // Implementation of rv64iamfd according to the v. 20191213 unprivileged spec + std::cerr << "execute insn "; + printInstructionInfo(); + executed_ = true; switch (metadata.opcode) { case Opcode::RISCV_LB: { // LB rd,rs1,imm diff --git a/src/lib/models/emulation/Core.cc b/src/lib/models/emulation/Core.cc index 16b79eb375..9294f35e87 100644 --- a/src/lib/models/emulation/Core.cc +++ b/src/lib/models/emulation/Core.cc @@ -67,6 +67,8 @@ void Core::tick() { // Fetch + std::cerr << "fetch" << std::endl; + // Determine if new uops are needed to be fetched if (!microOps_.size()) { // Find fetched memory that matches the current PC @@ -100,15 +102,19 @@ void Core::tick() { auto& uop = microOps_.front(); if (uop->exceptionEncountered()) { + std::cerr << "preissue handle exception" << std::endl; + handleException(uop); return; } + std::cerr << "issue" << std::endl; + // Issue auto registers = uop->getSourceRegisters(); for (size_t i = 0; i < registers.size(); i++) { auto reg = registers[i]; - if (!uop->isOperandReady(i)) { + if (!uop->isSourceOperandReady(i)) { uop->supplyOperand(i, registerFileSet_.get(reg)); } } @@ -166,6 +172,8 @@ void Core::execute(std::shared_ptr& uop) { uop->execute(); if (uop->exceptionEncountered()) { + std::cerr << "post execute handle exception" << std::endl; + handleException(uop); return; } diff --git a/src/lib/models/inorder/Core.cc b/src/lib/models/inorder/Core.cc index 700c7a2e2c..bc0745a230 100644 --- a/src/lib/models/inorder/Core.cc +++ b/src/lib/models/inorder/Core.cc @@ -280,7 +280,7 @@ void Core::forwardOperands(const span& registers, if (uop->canExecute()) { return; } - if (sourceReg == registers[i] && !uop->isOperandReady(operand)) { + if (sourceReg == registers[i] && !uop->isSourceOperandReady(operand)) { // Supply the operand uop->supplyOperand(operand, values[i]); } @@ -303,7 +303,7 @@ void Core::readRegisters() { const auto& sourceRegisters = uop->getSourceRegisters(); for (size_t i = 0; i < sourceRegisters.size(); i++) { const auto& reg = sourceRegisters[i]; - if (!uop->isOperandReady(i)) { + if (!uop->isSourceOperandReady(i)) { uop->supplyOperand(i, registerFileSet_.get(reg)); } } diff --git a/src/lib/models/outoforder/Core.cc b/src/lib/models/outoforder/Core.cc index cf6df51b98..b7a3e4b5af 100644 --- a/src/lib/models/outoforder/Core.cc +++ b/src/lib/models/outoforder/Core.cc @@ -113,6 +113,8 @@ void Core::tick() { if (hasHalted_) return; if (exceptionHandler_ != nullptr) { + std::cerr << "tick process exception handler" << std::endl; + processExceptionHandler(); return; } @@ -265,6 +267,7 @@ bool Core::hasHalted() const { } void Core::raiseException(const std::shared_ptr& instruction) { + assert(instruction && "raise null"); exceptionGenerated_ = true; exceptionGeneratingInstruction_ = instruction; } @@ -331,13 +334,38 @@ void Core::processExceptionHandler() { } void Core::applyStateChange(const arch::ProcessStateChange& change) { - completionSlots_[completionSlots_.size() - 1].getTailSlots()[0] = - std::move(exceptionGeneratingInstruction_); + std::cerr << "apply state change" << std::endl; + + // TODO THIS COULD BE DANGEROUS. APPLY STATE CHANGE NOT ONLY USED DURING + // EXCEPTION HANDLING + if (change.type != arch::ChangeType::WRITEBACK && + exceptionGeneratingInstruction_) { + std::cerr << "APPLY FLUSH FROM ROB" << std::endl; - return; + // Flush instruction from ROB + reorderBuffer_.flush(exceptionGeneratingInstruction_->getInstructionId() - + 1); + } // Update registers in accordance with the ProcessStateChange type switch (change.type) { + case arch::ChangeType::WRITEBACK: { + // Place the exception generating instruction in a completion slot so can + // pass through writeback in next cycle. Results held in internal results + // array + assert(exceptionGeneratingInstruction_ && + "exception generating instruction is NULL"); + std::cerr << "writeback state change" << std::endl; + + // Forwards operands to update dispatch scoreboard as this didn't happen + // in execute + dispatchIssueUnit_.forwardOperands( + exceptionGeneratingInstruction_->getDestinationRegisters(), + exceptionGeneratingInstruction_->getResults()); + + completionSlots_[completionSlots_.size() - 1].getTailSlots()[0] = + std::move(exceptionGeneratingInstruction_); + } case arch::ChangeType::INCREMENT: { for (size_t i = 0; i < change.modifiedRegisters.size(); i++) { mappedRegisterFileSet_.set( @@ -346,6 +374,7 @@ void Core::applyStateChange(const arch::ProcessStateChange& change) { .get() + change.modifiedRegisterValues[i].get()); } + break; } case arch::ChangeType::DECREMENT: { @@ -356,6 +385,7 @@ void Core::applyStateChange(const arch::ProcessStateChange& change) { .get() - change.modifiedRegisterValues[i].get()); } + break; } default: { // arch::ChangeType::REPLACEMENT @@ -364,6 +394,7 @@ void Core::applyStateChange(const arch::ProcessStateChange& change) { mappedRegisterFileSet_.set(change.modifiedRegisters[i], change.modifiedRegisterValues[i]); } + break; } } diff --git a/src/lib/pipeline/DecodeUnit.cc b/src/lib/pipeline/DecodeUnit.cc index 6541a6e676..6fa971b89e 100644 --- a/src/lib/pipeline/DecodeUnit.cc +++ b/src/lib/pipeline/DecodeUnit.cc @@ -11,7 +11,7 @@ DecodeUnit::DecodeUnit(PipelineBuffer& input, : input_(input), output_(output), predictor_(predictor){}; void DecodeUnit::tick() { - std::cerr << "decode" << std::endl; + // std::cerr << "decode" << std::endl; // Stall if output buffer is stalled if (output_.isStalled()) { diff --git a/src/lib/pipeline/DispatchIssueUnit.cc b/src/lib/pipeline/DispatchIssueUnit.cc index 623dc66c25..d532952e46 100644 --- a/src/lib/pipeline/DispatchIssueUnit.cc +++ b/src/lib/pipeline/DispatchIssueUnit.cc @@ -56,7 +56,7 @@ DispatchIssueUnit::DispatchIssueUnit( } void DispatchIssueUnit::tick() { - std::cerr << "dispatch tick" << std::endl; + // std::cerr << "dispatch tick" << std::endl; input_.stall(false); @@ -69,6 +69,9 @@ void DispatchIssueUnit::tick() { continue; } + std::cerr << "dispatch uop = "; + uop->printInstructionInfo(); + const std::vector& supportedPorts = uop->getSupportedPorts(); if (uop->exceptionEncountered()) { // Exception; mark as ready to commit, and remove from pipeline @@ -103,12 +106,20 @@ void DispatchIssueUnit::tick() { for (uint16_t i = 0; i < sourceRegisters.size(); i++) { const auto& reg = sourceRegisters[i]; - if (!uop->isOperandReady(i)) { + std::cerr << "resgister read tag " << (int)reg.tag << std::endl; + + if (!uop->isSourceOperandReady(i)) { + std::cerr << "source operand isn;t ready" << std::endl; + // The operand hasn't already been supplied if (scoreboard_[reg.type][reg.tag]) { // The scoreboard says it's ready; read and supply the register value + std::cerr << "SUPPLY THE OPERANDD" << std::endl; + uop->supplyOperand(i, registerFileSet_.get(reg)); } else { + std::cerr << "OPERAND NOT READY YET, ADD TO DEP MATRIX" << std::endl; + // This register isn't ready yet. Register this uop to the dependency // matrix for a more efficient lookup later dependencyMatrix_[reg.type][reg.tag].push_back({uop, port, i}); @@ -136,7 +147,7 @@ void DispatchIssueUnit::tick() { } void DispatchIssueUnit::issue() { - std::cerr << "dispatch issue" << std::endl; + // std::cerr << "dispatch issue" << std::endl; int issued = 0; // Check the ready queues, and issue an instruction from each if the @@ -153,6 +164,9 @@ void DispatchIssueUnit::issue() { if (queue.size() > 0) { auto& uop = queue.front(); + std::cerr << "issue uop "; + uop->printInstructionInfo(); + issuePorts_[i].getTailSlots()[0] = std::move(uop); queue.pop_front(); diff --git a/src/lib/pipeline/ExecuteUnit.cc b/src/lib/pipeline/ExecuteUnit.cc index 3b639c47eb..cad75ae8c2 100644 --- a/src/lib/pipeline/ExecuteUnit.cc +++ b/src/lib/pipeline/ExecuteUnit.cc @@ -26,7 +26,7 @@ ExecuteUnit::ExecuteUnit( blockingGroups_(blockingGroups) {} void ExecuteUnit::tick() { - std::cerr << "execute" << std::endl; + // std::cerr << "execute" << std::endl; tickCounter_++; shouldFlush_ = false; @@ -135,8 +135,8 @@ void ExecuteUnit::execute(std::shared_ptr& uop) { } if (uop->exceptionEncountered()) { - std::cerr << "Execute exception encountered, don't forward results" - << std::endl; + // std::cerr << "Execute exception encountered, don't forward results" + // << std::endl; // Exception; don't forward results, don't pass uop forward raiseException_(uop); diff --git a/src/lib/pipeline/FetchUnit.cc b/src/lib/pipeline/FetchUnit.cc index c4b0888fed..229642c3ad 100644 --- a/src/lib/pipeline/FetchUnit.cc +++ b/src/lib/pipeline/FetchUnit.cc @@ -25,7 +25,7 @@ FetchUnit::FetchUnit(PipelineBuffer& output, FetchUnit::~FetchUnit() { delete[] fetchBuffer_; } void FetchUnit::tick() { - std::cerr << "fetch" << std::endl; + // std::cerr << "fetch" << std::endl; if (output_.isStalled()) { return; @@ -61,6 +61,8 @@ void FetchUnit::tick() { const uint8_t* buffer; uint16_t bufferOffset; + std::cerr << "fetch from pc_=" << pc_ << std::endl; + // Check if more instruction data is required if (bufferedBytes_ < isa_.getMaxInstructionSize()) { // Calculate the address of the next fetch block diff --git a/src/lib/pipeline/LoadStoreQueue.cc b/src/lib/pipeline/LoadStoreQueue.cc index 63cbc8f244..f7525134bb 100644 --- a/src/lib/pipeline/LoadStoreQueue.cc +++ b/src/lib/pipeline/LoadStoreQueue.cc @@ -380,7 +380,7 @@ void LoadStoreQueue::purgeFlushed() { } void LoadStoreQueue::tick() { - std::cerr << "lsq" << std::endl; + // std::cerr << "lsq" << std::endl; tickCounter_++; // Send memory requests adhering to set bandwidth and number of permitted diff --git a/src/lib/pipeline/RegisterAliasTable.cc b/src/lib/pipeline/RegisterAliasTable.cc index 23bcac3980..c080fec150 100644 --- a/src/lib/pipeline/RegisterAliasTable.cc +++ b/src/lib/pipeline/RegisterAliasTable.cc @@ -1,6 +1,7 @@ #include "simeng/pipeline/RegisterAliasTable.hh" #include +#include namespace simeng { namespace pipeline { @@ -50,6 +51,9 @@ Register RegisterAliasTable::getMapping(Register architectural) const { "Invalid register type. Cannot find RAT mapping."); auto tag = mappingTable_[architectural.type][architectural.tag]; + + std::cerr << "mapping table for arch reg " << (int)architectural.tag << " = " + << tag << std::endl; return {architectural.type, tag, true}; } @@ -75,6 +79,9 @@ Register RegisterAliasTable::allocate(Register architectural) { auto tag = freeQueue.front(); freeQueue.pop(); + std::cerr << "rat.allocate arch reg " << (int)architectural.tag << " to " + << (int)tag << std::endl; + // Keep the old physical register in the history table historyTable_[architectural.type][tag] = mappingTable_[architectural.type][architectural.tag]; @@ -91,6 +98,9 @@ void RegisterAliasTable::commit(Register physical) { // Find the register previously mapped to the same architectural register and // free it auto oldTag = historyTable_[physical.type][physical.tag]; + std::cerr << "rat.commit old tag = " << (int)oldTag << std::endl; + // TODO never update mapping table?? + freeQueues_[physical.type].push(oldTag); } diff --git a/src/lib/pipeline/RenameUnit.cc b/src/lib/pipeline/RenameUnit.cc index af5f5f4c6a..be2f339fce 100644 --- a/src/lib/pipeline/RenameUnit.cc +++ b/src/lib/pipeline/RenameUnit.cc @@ -18,7 +18,7 @@ RenameUnit::RenameUnit(PipelineBuffer>& fromDecode, freeRegistersAvailable_(registerTypes) {} void RenameUnit::tick() { - std::cerr << "rename" << std::endl; + // std::cerr << "rename" << std::endl; if (output_.isStalled()) { input_.stall(true); @@ -37,6 +37,9 @@ void RenameUnit::tick() { if (uop == nullptr) { continue; } + std::cerr << "rename uop="; + uop->printInstructionInfo(); + if (reorderBuffer_.getFreeSpace() == 0) { input_.stall(true); robStalls_++; @@ -74,6 +77,8 @@ void RenameUnit::tick() { // Count the number of each type of destination registers needed, and ensure // enough free registers exist to allocate them. for (const auto& reg : destinationRegisters) { + std::cerr << "destination reg to rename = " << (int)reg.tag << std::endl; + // Check whether renaming is allowed, otherwise we need to serialize if (!rat_.canRename(reg.type)) { serialize = true; @@ -101,7 +106,15 @@ void RenameUnit::tick() { auto& sourceRegisters = uop->getSourceRegisters(); for (size_t i = 0; i < sourceRegisters.size(); i++) { const auto& reg = sourceRegisters[i]; - if (!uop->isOperandReady(i)) { + std::cerr << "rename source = " << (int)reg.tag + << " isSourceOperandReady " << uop->isSourceOperandReady(i) + << std::endl; + + if (!uop->isSourceOperandReady(i)) { + std::cerr << "Not ready so rename source to " + // << (int)rat_.getMapping(reg).tag + << std::endl; + uop->renameSource(i, rat_.getMapping(reg)); } } diff --git a/src/lib/pipeline/ReorderBuffer.cc b/src/lib/pipeline/ReorderBuffer.cc index 839be3fd90..8d938ed61c 100644 --- a/src/lib/pipeline/ReorderBuffer.cc +++ b/src/lib/pipeline/ReorderBuffer.cc @@ -30,6 +30,9 @@ void ReorderBuffer::reserve(const std::shared_ptr& insn) { insn->setInstructionId(insnId_); if (insn->isLastMicroOp()) insnId_++; + std::cerr << "Add insn to ROB id = " << insn->getInstructionId() << " "; + insn->printInstructionInfo(); + buffer_.push_back(insn); } @@ -71,7 +74,7 @@ void ReorderBuffer::commitMicroOps(uint64_t insnId) { } unsigned int ReorderBuffer::commit(unsigned int maxCommitSize) { - std::cerr << "commit" << std::endl; + // std::cerr << "commit" << std::endl; shouldFlush_ = false; size_t maxCommits = @@ -102,6 +105,9 @@ unsigned int ReorderBuffer::commit(unsigned int maxCommitSize) { const auto& destinations = uop->getDestinationRegisters(); for (int i = 0; i < destinations.size(); i++) { + std::cerr << "rat commit physical reg=" << destinations[i].tag + << std::endl; + rat_.commit(destinations[i]); } @@ -159,6 +165,8 @@ unsigned int ReorderBuffer::commit(unsigned int maxCommitSize) { 0}; } } + std::cerr << "buffer pop" << std::endl; + buffer_.pop_front(); } diff --git a/src/lib/pipeline/WritebackUnit.cc b/src/lib/pipeline/WritebackUnit.cc index bf78094b46..bfd31af564 100644 --- a/src/lib/pipeline/WritebackUnit.cc +++ b/src/lib/pipeline/WritebackUnit.cc @@ -14,7 +14,7 @@ WritebackUnit::WritebackUnit( flagMicroOpCommits_(flagMicroOpCommits) {} void WritebackUnit::tick() { - std::cerr << "writeback" << std::endl; + // std::cerr << "writeback" << std::endl; for (size_t slot = 0; slot < completionSlots_.size(); slot++) { auto& uop = completionSlots_[slot].getHeadSlots()[0]; @@ -23,16 +23,21 @@ void WritebackUnit::tick() { continue; } - std::cerr << "writeback id = " << uop->getSequenceId() << std::endl; + // std::cerr << "writeback id = " << uop->getSequenceId() << std::endl; auto& results = uop->getResults(); - std::cerr << "writeback results = " << results[0].get() - << std::endl; + + if (results.size() > 0) { + // std::cerr << "writeback results = " << results[0].get() + // << std::endl; + } auto& destinations = uop->getDestinationRegisters(); for (size_t i = 0; i < results.size(); i++) { // Write results to register file registerFileSet_.set(destinations[i], results[i]); + std::cerr << "write to physical reg " << (int)destinations[i].tag + << " value of " << results[i].get() << std::endl; } if (uop->isMicroOp()) { uop->setWaitingCommit(); diff --git a/test/regression/RegressionTest.cc b/test/regression/RegressionTest.cc index 5b43ac6cd0..c4f1c1386e 100644 --- a/test/regression/RegressionTest.cc +++ b/test/regression/RegressionTest.cc @@ -119,6 +119,8 @@ void RegressionTest::run(const char* source, const char* triple, // Run the core model until the program is complete while (!core_->hasHalted() || dataMemory->hasPendingRequests()) { + // std::cerr << "tick" << std::endl; + ASSERT_LT(numTicks_, maxTicks_) << "Maximum tick count exceeded."; core_->tick(); instructionMemory.tick(); diff --git a/test/regression/riscv/instructions/csr.cc b/test/regression/riscv/instructions/csr.cc index a90d708592..112d079b0c 100644 --- a/test/regression/riscv/instructions/csr.cc +++ b/test/regression/riscv/instructions/csr.cc @@ -10,17 +10,21 @@ TEST_P(InstCSR, basicCsr) { std::cerr << "" << std::endl; RUN_RISCV(R"( + addi x8, x9, 1 li x8, 1 csrrw x9, frm, x8 + addi x10, x9, 10 )"); EXPECT_EQ(getGeneralRegister(8), 1); EXPECT_EQ(getGeneralRegister(9), 0b100000); + EXPECT_EQ(getGeneralRegister(10), 0b101010); } INSTANTIATE_TEST_SUITE_P( RISCV, InstCSR, ::testing::Values( - // std::make_tuple(EMULATION, "{}"), + // std::make_tuple(EMULATION, "{}") + // , // std::make_tuple(INORDER, "{}"), std::make_tuple(OUTOFORDER, "{}")), // "{Ports: {'0': {Portname: 0, Instruction-Group-Support: [INT, diff --git a/test/unit/MockInstruction.hh b/test/unit/MockInstruction.hh index 883c753413..413a394e07 100644 --- a/test/unit/MockInstruction.hh +++ b/test/unit/MockInstruction.hh @@ -8,13 +8,15 @@ namespace simeng { /** Mock implementation of the `Instruction` interface. */ class MockInstruction : public Instruction { public: + MOCK_METHOD0(printInstructionInfo, void()); MOCK_CONST_METHOD0(getSourceRegisters, const span()); + MOCK_METHOD1(setResults, void(span resultsInput)); MOCK_CONST_METHOD0(getSourceOperands, const span()); MOCK_CONST_METHOD0(getDestinationRegisters, const span()); MOCK_METHOD2(renameSource, void(uint16_t i, Register renamed)); MOCK_METHOD2(renameDestination, void(uint16_t i, Register renamed)); MOCK_METHOD2(supplyOperand, void(uint16_t i, const RegisterValue& value)); - MOCK_CONST_METHOD1(isOperandReady, bool(int i)); + MOCK_CONST_METHOD1(isSourceOperandReady, bool(int i)); MOCK_CONST_METHOD0(canExecute, bool()); MOCK_METHOD0(execute, void()); MOCK_CONST_METHOD0(getResults, const span()); diff --git a/test/unit/aarch64/InstructionTest.cc b/test/unit/aarch64/InstructionTest.cc index 20dddcca18..ff5b48d007 100644 --- a/test/unit/aarch64/InstructionTest.cc +++ b/test/unit/aarch64/InstructionTest.cc @@ -136,7 +136,7 @@ TEST_F(AArch64InstructionTest, validInsn) { EXPECT_EQ(insn.getSourceRegisters().size(), srcRegs.size()); for (int i = 0; i < srcRegs.size(); i++) { EXPECT_EQ(insn.getSourceRegisters()[i], srcRegs[i]); - EXPECT_FALSE(insn.isOperandReady(i)); + EXPECT_FALSE(insn.isSourceOperandReady(i)); } EXPECT_EQ(insn.getStallCycles(), 4); EXPECT_EQ(insn.getSupportedPorts(), ports); @@ -200,7 +200,7 @@ TEST_F(AArch64InstructionTest, invalidInsn_1) { EXPECT_EQ(insn.getSourceRegisters().size(), srcRegs.size()); for (int i = 0; i < srcRegs.size(); i++) { EXPECT_EQ(insn.getSourceRegisters()[i], srcRegs[i]); - EXPECT_FALSE(insn.isOperandReady(i)); + EXPECT_FALSE(insn.isSourceOperandReady(i)); } EXPECT_EQ(insn.getStallCycles(), 1); EXPECT_EQ(insn.getSupportedPorts(), ports); @@ -266,7 +266,7 @@ TEST_F(AArch64InstructionTest, invalidInsn_2) { EXPECT_EQ(insn.getSourceRegisters().size(), srcRegs.size()); for (int i = 0; i < srcRegs.size(); i++) { EXPECT_EQ(insn.getSourceRegisters()[i], srcRegs[i]); - EXPECT_FALSE(insn.isOperandReady(i)); + EXPECT_FALSE(insn.isSourceOperandReady(i)); } EXPECT_EQ(insn.getStallCycles(), 1); EXPECT_EQ(insn.getSupportedPorts(), ports); @@ -336,9 +336,9 @@ TEST_F(AArch64InstructionTest, supplyOperand) { {RegisterType::VECTOR, 0}}; // Check initial state is as expected EXPECT_FALSE(insn.canExecute()); - EXPECT_FALSE(insn.isOperandReady(0)); - EXPECT_FALSE(insn.isOperandReady(1)); - EXPECT_FALSE(insn.isOperandReady(2)); + EXPECT_FALSE(insn.isSourceOperandReady(0)); + EXPECT_FALSE(insn.isSourceOperandReady(1)); + EXPECT_FALSE(insn.isSourceOperandReady(2)); // Define mock register values for source registers RegisterValue vec = {0xABBACAFE01234567, 256}; @@ -350,9 +350,9 @@ TEST_F(AArch64InstructionTest, supplyOperand) { insn.supplyOperand(2, vec); // Ensure Instruction state has updated as expected EXPECT_TRUE(insn.canExecute()); - EXPECT_TRUE(insn.isOperandReady(0)); - EXPECT_TRUE(insn.isOperandReady(1)); - EXPECT_TRUE(insn.isOperandReady(2)); + EXPECT_TRUE(insn.isSourceOperandReady(0)); + EXPECT_TRUE(insn.isSourceOperandReady(1)); + EXPECT_TRUE(insn.isSourceOperandReady(2)); auto sourceVals = insn.getSourceOperands(); EXPECT_EQ(sourceVals.size(), 3); EXPECT_EQ(sourceVals[0], pred); @@ -396,10 +396,10 @@ TEST_F(AArch64InstructionTest, supplyData) { } // Supply needed operands - EXPECT_FALSE(insn.isOperandReady(0)); + EXPECT_FALSE(insn.isSourceOperandReady(0)); RegisterValue addr = {0x480, 8}; insn.supplyOperand(0, addr); - EXPECT_TRUE(insn.isOperandReady(0)); + EXPECT_TRUE(insn.isSourceOperandReady(0)); // Generate memory addresses EXPECT_EQ(insn.getGeneratedAddresses().size(), 0); @@ -440,10 +440,10 @@ TEST_F(AArch64InstructionTest, supplyData_dataAbort) { EXPECT_EQ(insn.getGroup(), InstructionGroups::LOAD_INT); // Supply needed operands - EXPECT_FALSE(insn.isOperandReady(0)); + EXPECT_FALSE(insn.isSourceOperandReady(0)); RegisterValue addr = {0x480, 8}; insn.supplyOperand(0, addr); - EXPECT_TRUE(insn.isOperandReady(0)); + EXPECT_TRUE(insn.isSourceOperandReady(0)); // Generate memory addresses EXPECT_EQ(insn.getGeneratedAddresses().size(), 0); diff --git a/test/unit/riscv/InstructionTest.cc b/test/unit/riscv/InstructionTest.cc index 37580c4f80..fa215a30b8 100644 --- a/test/unit/riscv/InstructionTest.cc +++ b/test/unit/riscv/InstructionTest.cc @@ -132,7 +132,7 @@ TEST_F(RiscVInstructionTest, validInsn) { EXPECT_EQ(insn.getSourceRegisters().size(), srcRegs.size()); for (int i = 0; i < srcRegs.size(); i++) { EXPECT_EQ(insn.getSourceRegisters()[i], srcRegs[i]); - EXPECT_FALSE(insn.isOperandReady(i)); + EXPECT_FALSE(insn.isSourceOperandReady(i)); } EXPECT_EQ(insn.getStallCycles(), 4); EXPECT_EQ(insn.getSupportedPorts(), ports); @@ -196,7 +196,7 @@ TEST_F(RiscVInstructionTest, invalidInsn_1) { EXPECT_EQ(insn.getSourceRegisters().size(), srcRegs.size()); for (int i = 0; i < srcRegs.size(); i++) { EXPECT_EQ(insn.getSourceRegisters()[i], srcRegs[i]); - EXPECT_FALSE(insn.isOperandReady(i)); + EXPECT_FALSE(insn.isSourceOperandReady(i)); } EXPECT_EQ(insn.getStallCycles(), 1); EXPECT_EQ(insn.getSupportedPorts(), ports); @@ -262,7 +262,7 @@ TEST_F(RiscVInstructionTest, invalidInsn_2) { EXPECT_EQ(insn.getSourceRegisters().size(), srcRegs.size()); for (int i = 0; i < srcRegs.size(); i++) { EXPECT_EQ(insn.getSourceRegisters()[i], srcRegs[i]); - EXPECT_FALSE(insn.isOperandReady(i)); + EXPECT_FALSE(insn.isSourceOperandReady(i)); } EXPECT_EQ(insn.getStallCycles(), 1); EXPECT_EQ(insn.getSupportedPorts(), ports); @@ -331,8 +331,8 @@ TEST_F(RiscVInstructionTest, supplyOperand) { {RegisterType::GENERAL, 10}}; // Check initial state is as expected EXPECT_FALSE(insn.canExecute()); - EXPECT_FALSE(insn.isOperandReady(0)); - EXPECT_FALSE(insn.isOperandReady(1)); + EXPECT_FALSE(insn.isSourceOperandReady(0)); + EXPECT_FALSE(insn.isSourceOperandReady(1)); // Define mock register values for source registers RegisterValue val = {0xABBACAFE, 8}; @@ -341,8 +341,8 @@ TEST_F(RiscVInstructionTest, supplyOperand) { insn.supplyOperand(1, val); // Ensure Instruction state has updated as expected EXPECT_TRUE(insn.canExecute()); - EXPECT_TRUE(insn.isOperandReady(0)); - EXPECT_TRUE(insn.isOperandReady(1)); + EXPECT_TRUE(insn.isSourceOperandReady(0)); + EXPECT_TRUE(insn.isSourceOperandReady(1)); auto sourceVals = insn.getSourceOperands(); EXPECT_EQ(sourceVals.size(), 2); EXPECT_EQ(sourceVals[0], val); @@ -383,10 +383,10 @@ TEST_F(RiscVInstructionTest, supplyData) { } // Supply needed operands - EXPECT_FALSE(insn.isOperandReady(0)); + EXPECT_FALSE(insn.isSourceOperandReady(0)); RegisterValue addr = {0x480, 8}; insn.supplyOperand(0, addr); - EXPECT_TRUE(insn.isOperandReady(0)); + EXPECT_TRUE(insn.isSourceOperandReady(0)); // Generate memory addresses EXPECT_EQ(insn.getGeneratedAddresses().size(), 0); @@ -422,10 +422,10 @@ TEST_F(RiscVInstructionTest, supplyData_dataAbort) { EXPECT_EQ(insn.getGroup(), InstructionGroups::LOAD_INT); // Supply needed operands - EXPECT_FALSE(insn.isOperandReady(0)); + EXPECT_FALSE(insn.isSourceOperandReady(0)); RegisterValue addr = {0x480, 8}; insn.supplyOperand(0, addr); - EXPECT_TRUE(insn.isOperandReady(0)); + EXPECT_TRUE(insn.isSourceOperandReady(0)); // Generate memory addresses EXPECT_EQ(insn.getGeneratedAddresses().size(), 0); From c3e0aa133573129ec5dcc2f68673cf0f022cfb84 Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Fri, 16 Feb 2024 22:41:59 +0000 Subject: [PATCH 3/5] Fix emulation and inorder cores --- src/include/simeng/models/emulation/Core.hh | 2 ++ src/lib/arch/riscv/Instruction.cc | 7 +++--- src/lib/arch/riscv/Instruction_execute.cc | 4 ++-- src/lib/models/emulation/Core.cc | 23 ++++++++++++++---- src/lib/models/inorder/Core.cc | 26 ++++++++++++++++----- src/lib/models/outoforder/Core.cc | 10 ++++---- src/lib/pipeline/DispatchIssueUnit.cc | 17 +++++++------- src/lib/pipeline/ExecuteUnit.cc | 4 ++-- src/lib/pipeline/FetchUnit.cc | 2 +- src/lib/pipeline/RegisterAliasTable.cc | 11 +++++---- src/lib/pipeline/RenameUnit.cc | 20 +++++++++------- src/lib/pipeline/ReorderBuffer.cc | 19 ++++++++------- src/lib/pipeline/WritebackUnit.cc | 5 ++-- test/regression/riscv/instructions/csr.cc | 15 ++++-------- 14 files changed, 99 insertions(+), 66 deletions(-) diff --git a/src/include/simeng/models/emulation/Core.hh b/src/include/simeng/models/emulation/Core.hh index 9152c6df03..67dd02c885 100644 --- a/src/include/simeng/models/emulation/Core.hh +++ b/src/include/simeng/models/emulation/Core.hh @@ -94,6 +94,8 @@ class Core : public simeng::Core { /** The active exception handler. */ std::shared_ptr exceptionHandler_; + std::shared_ptr exceptionGeneratingInstruction_; + /** Is the core waiting on a data read? */ unsigned int pendingReads_ = 0; diff --git a/src/lib/arch/riscv/Instruction.cc b/src/lib/arch/riscv/Instruction.cc index c001738671..cbcd54ce98 100644 --- a/src/lib/arch/riscv/Instruction.cc +++ b/src/lib/arch/riscv/Instruction.cc @@ -49,8 +49,9 @@ bool Instruction::isSourceOperandReady(int index) const { void Instruction::renameSource(uint16_t i, Register renamed) { sourceRegisters[i] = renamed; - std::cerr << "renamed source " << renamed << " renamed = " << renamed.renamed - << std::endl; + // std::cerr << "renamed source " << renamed << " renamed = " << + // renamed.renamed + // << std::endl; } void Instruction::renameDestination(uint16_t i, Register renamed) { destinationRegisters[i] = renamed; @@ -100,7 +101,7 @@ void Instruction::setResults(span resultsInput) { "[SimEng:Instruction] More results than size of array"); uint8_t n = 0; for (auto result : resultsInput) { - std::cerr << "result = " << result.get() << std::endl; + // std::cerr << "result = " << result.get() << std::endl; results[n] = result; n++; diff --git a/src/lib/arch/riscv/Instruction_execute.cc b/src/lib/arch/riscv/Instruction_execute.cc index 5b694ab71c..6e069375df 100644 --- a/src/lib/arch/riscv/Instruction_execute.cc +++ b/src/lib/arch/riscv/Instruction_execute.cc @@ -179,8 +179,8 @@ void Instruction::execute() { // Implementation of rv64iamfd according to the v. 20191213 unprivileged spec - std::cerr << "execute insn "; - printInstructionInfo(); + // std::cerr << "execute insn "; + // printInstructionInfo(); executed_ = true; switch (metadata.opcode) { diff --git a/src/lib/models/emulation/Core.cc b/src/lib/models/emulation/Core.cc index 9294f35e87..d163b92af3 100644 --- a/src/lib/models/emulation/Core.cc +++ b/src/lib/models/emulation/Core.cc @@ -67,7 +67,7 @@ void Core::tick() { // Fetch - std::cerr << "fetch" << std::endl; + // std::cerr << "fetch" << std::endl; // Determine if new uops are needed to be fetched if (!microOps_.size()) { @@ -102,13 +102,13 @@ void Core::tick() { auto& uop = microOps_.front(); if (uop->exceptionEncountered()) { - std::cerr << "preissue handle exception" << std::endl; + // std::cerr << "preissue handle exception" << std::endl; handleException(uop); return; } - std::cerr << "issue" << std::endl; + // std::cerr << "issue" << std::endl; // Issue auto registers = uop->getSourceRegisters(); @@ -172,7 +172,7 @@ void Core::execute(std::shared_ptr& uop) { uop->execute(); if (uop->exceptionEncountered()) { - std::cerr << "post execute handle exception" << std::endl; + // std::cerr << "post execute handle exception" << std::endl; handleException(uop); return; @@ -212,6 +212,7 @@ void Core::execute(std::shared_ptr& uop) { void Core::handleException(const std::shared_ptr& instruction) { exceptionHandler_ = isa_.handleException(instruction, *this, dataMemory_); + exceptionGeneratingInstruction_ = instruction; processExceptionHandler(); } @@ -252,6 +253,20 @@ void Core::processExceptionHandler() { void Core::applyStateChange(const arch::ProcessStateChange& change) { // Update registers in accordance with the ProcessStateChange type switch (change.type) { + case arch::ChangeType::WRITEBACK: { + // Writeback + auto results = exceptionGeneratingInstruction_->getResults(); + auto destinations = + exceptionGeneratingInstruction_->getDestinationRegisters(); + + for (size_t i = 0; i < results.size(); i++) { + auto reg = destinations[i]; + registerFileSet_.set(reg, results[i]); + } + + instructionsExecuted_++; + break; + } case arch::ChangeType::INCREMENT: { for (size_t i = 0; i < change.modifiedRegisters.size(); i++) { registerFileSet_.set( diff --git a/src/lib/models/inorder/Core.cc b/src/lib/models/inorder/Core.cc index bc0745a230..309ee8cd2b 100644 --- a/src/lib/models/inorder/Core.cc +++ b/src/lib/models/inorder/Core.cc @@ -180,18 +180,20 @@ void Core::raiseException(const std::shared_ptr& instruction) { } void Core::handleException() { - exceptionGenerated_ = false; - - exceptionHandler_ = - isa_.handleException(exceptionGeneratingInstruction_, *this, dataMemory_); - - processExceptionHandler(); + std::cerr << "handle exception inorder" << std::endl; // Flush pipeline fetchToDecodeBuffer_.fill({}); decodeToExecuteBuffer_.fill(nullptr); decodeUnit_.purgeFlushed(); completionSlots_[0].fill(nullptr); + + exceptionGenerated_ = false; + + exceptionHandler_ = + isa_.handleException(exceptionGeneratingInstruction_, *this, dataMemory_); + + processExceptionHandler(); } void Core::processExceptionHandler() { @@ -312,6 +314,18 @@ void Core::readRegisters() { void Core::applyStateChange(const arch::ProcessStateChange& change) { // Update registers in accordance with the ProcessStateChange type switch (change.type) { + case arch::ChangeType::WRITEBACK: { + forwardOperands( + exceptionGeneratingInstruction_->getDestinationRegisters(), + exceptionGeneratingInstruction_->getResults()); + + assert(completionSlots_[0].getTailSlots()[0] == nullptr && + "Don't overwrite what is there"); + completionSlots_[0].getTailSlots()[0] = + std::move(exceptionGeneratingInstruction_); + + break; + } case arch::ChangeType::INCREMENT: { for (size_t i = 0; i < change.modifiedRegisters.size(); i++) { registerFileSet_.set( diff --git a/src/lib/models/outoforder/Core.cc b/src/lib/models/outoforder/Core.cc index b7a3e4b5af..de4a5bc6c6 100644 --- a/src/lib/models/outoforder/Core.cc +++ b/src/lib/models/outoforder/Core.cc @@ -106,14 +106,14 @@ Core::Core(MemoryInterface& instructionMemory, MemoryInterface& dataMemory, }; void Core::tick() { - std::cerr << "---- core tick ----" << std::endl; + // std::cerr << "---- core tick ----" << std::endl; ticks_++; if (hasHalted_) return; if (exceptionHandler_ != nullptr) { - std::cerr << "tick process exception handler" << std::endl; + // std::cerr << "tick process exception handler" << std::endl; processExceptionHandler(); return; @@ -334,13 +334,13 @@ void Core::processExceptionHandler() { } void Core::applyStateChange(const arch::ProcessStateChange& change) { - std::cerr << "apply state change" << std::endl; + // std::cerr << "apply state change" << std::endl; // TODO THIS COULD BE DANGEROUS. APPLY STATE CHANGE NOT ONLY USED DURING // EXCEPTION HANDLING if (change.type != arch::ChangeType::WRITEBACK && exceptionGeneratingInstruction_) { - std::cerr << "APPLY FLUSH FROM ROB" << std::endl; + // std::cerr << "APPLY FLUSH FROM ROB" << std::endl; // Flush instruction from ROB reorderBuffer_.flush(exceptionGeneratingInstruction_->getInstructionId() - @@ -355,7 +355,7 @@ void Core::applyStateChange(const arch::ProcessStateChange& change) { // array assert(exceptionGeneratingInstruction_ && "exception generating instruction is NULL"); - std::cerr << "writeback state change" << std::endl; + // std::cerr << "writeback state change" << std::endl; // Forwards operands to update dispatch scoreboard as this didn't happen // in execute diff --git a/src/lib/pipeline/DispatchIssueUnit.cc b/src/lib/pipeline/DispatchIssueUnit.cc index d532952e46..796a7c2dd7 100644 --- a/src/lib/pipeline/DispatchIssueUnit.cc +++ b/src/lib/pipeline/DispatchIssueUnit.cc @@ -69,8 +69,8 @@ void DispatchIssueUnit::tick() { continue; } - std::cerr << "dispatch uop = "; - uop->printInstructionInfo(); + // std::cerr << "dispatch uop = "; + // uop->printInstructionInfo(); const std::vector& supportedPorts = uop->getSupportedPorts(); if (uop->exceptionEncountered()) { @@ -106,19 +106,20 @@ void DispatchIssueUnit::tick() { for (uint16_t i = 0; i < sourceRegisters.size(); i++) { const auto& reg = sourceRegisters[i]; - std::cerr << "resgister read tag " << (int)reg.tag << std::endl; + // std::cerr << "resgister read tag " << (int)reg.tag << std::endl; if (!uop->isSourceOperandReady(i)) { - std::cerr << "source operand isn;t ready" << std::endl; + // std::cerr << "source operand isn;t ready" << std::endl; // The operand hasn't already been supplied if (scoreboard_[reg.type][reg.tag]) { // The scoreboard says it's ready; read and supply the register value - std::cerr << "SUPPLY THE OPERANDD" << std::endl; + // std::cerr << "SUPPLY THE OPERANDD" << std::endl; uop->supplyOperand(i, registerFileSet_.get(reg)); } else { - std::cerr << "OPERAND NOT READY YET, ADD TO DEP MATRIX" << std::endl; + // std::cerr << "OPERAND NOT READY YET, ADD TO DEP MATRIX" << + // std::endl; // This register isn't ready yet. Register this uop to the dependency // matrix for a more efficient lookup later @@ -164,8 +165,8 @@ void DispatchIssueUnit::issue() { if (queue.size() > 0) { auto& uop = queue.front(); - std::cerr << "issue uop "; - uop->printInstructionInfo(); + // std::cerr << "issue uop "; + // uop->printInstructionInfo(); issuePorts_[i].getTailSlots()[0] = std::move(uop); queue.pop_front(); diff --git a/src/lib/pipeline/ExecuteUnit.cc b/src/lib/pipeline/ExecuteUnit.cc index cad75ae8c2..12a09b3a0b 100644 --- a/src/lib/pipeline/ExecuteUnit.cc +++ b/src/lib/pipeline/ExecuteUnit.cc @@ -135,8 +135,8 @@ void ExecuteUnit::execute(std::shared_ptr& uop) { } if (uop->exceptionEncountered()) { - // std::cerr << "Execute exception encountered, don't forward results" - // << std::endl; + std::cerr << "Execute exception encountered, don't forward results" + << std::endl; // Exception; don't forward results, don't pass uop forward raiseException_(uop); diff --git a/src/lib/pipeline/FetchUnit.cc b/src/lib/pipeline/FetchUnit.cc index 229642c3ad..3deb9b853a 100644 --- a/src/lib/pipeline/FetchUnit.cc +++ b/src/lib/pipeline/FetchUnit.cc @@ -61,7 +61,7 @@ void FetchUnit::tick() { const uint8_t* buffer; uint16_t bufferOffset; - std::cerr << "fetch from pc_=" << pc_ << std::endl; + // std::cerr << "fetch from pc_=" << pc_ << std::endl; // Check if more instruction data is required if (bufferedBytes_ < isa_.getMaxInstructionSize()) { diff --git a/src/lib/pipeline/RegisterAliasTable.cc b/src/lib/pipeline/RegisterAliasTable.cc index c080fec150..976962d911 100644 --- a/src/lib/pipeline/RegisterAliasTable.cc +++ b/src/lib/pipeline/RegisterAliasTable.cc @@ -52,8 +52,9 @@ Register RegisterAliasTable::getMapping(Register architectural) const { auto tag = mappingTable_[architectural.type][architectural.tag]; - std::cerr << "mapping table for arch reg " << (int)architectural.tag << " = " - << tag << std::endl; + // std::cerr << "mapping table for arch reg " << (int)architectural.tag << " + // = " + // << tag << std::endl; return {architectural.type, tag, true}; } @@ -79,8 +80,8 @@ Register RegisterAliasTable::allocate(Register architectural) { auto tag = freeQueue.front(); freeQueue.pop(); - std::cerr << "rat.allocate arch reg " << (int)architectural.tag << " to " - << (int)tag << std::endl; + // std::cerr << "rat.allocate arch reg " << (int)architectural.tag << " to " + // << (int)tag << std::endl; // Keep the old physical register in the history table historyTable_[architectural.type][tag] = @@ -98,7 +99,7 @@ void RegisterAliasTable::commit(Register physical) { // Find the register previously mapped to the same architectural register and // free it auto oldTag = historyTable_[physical.type][physical.tag]; - std::cerr << "rat.commit old tag = " << (int)oldTag << std::endl; + // std::cerr << "rat.commit old tag = " << (int)oldTag << std::endl; // TODO never update mapping table?? freeQueues_[physical.type].push(oldTag); diff --git a/src/lib/pipeline/RenameUnit.cc b/src/lib/pipeline/RenameUnit.cc index be2f339fce..e6c9090957 100644 --- a/src/lib/pipeline/RenameUnit.cc +++ b/src/lib/pipeline/RenameUnit.cc @@ -37,8 +37,8 @@ void RenameUnit::tick() { if (uop == nullptr) { continue; } - std::cerr << "rename uop="; - uop->printInstructionInfo(); + // std::cerr << "rename uop="; + // uop->printInstructionInfo(); if (reorderBuffer_.getFreeSpace() == 0) { input_.stall(true); @@ -77,7 +77,8 @@ void RenameUnit::tick() { // Count the number of each type of destination registers needed, and ensure // enough free registers exist to allocate them. for (const auto& reg : destinationRegisters) { - std::cerr << "destination reg to rename = " << (int)reg.tag << std::endl; + // std::cerr << "destination reg to rename = " << (int)reg.tag << + // std::endl; // Check whether renaming is allowed, otherwise we need to serialize if (!rat_.canRename(reg.type)) { @@ -106,14 +107,15 @@ void RenameUnit::tick() { auto& sourceRegisters = uop->getSourceRegisters(); for (size_t i = 0; i < sourceRegisters.size(); i++) { const auto& reg = sourceRegisters[i]; - std::cerr << "rename source = " << (int)reg.tag - << " isSourceOperandReady " << uop->isSourceOperandReady(i) - << std::endl; + // std::cerr << "rename source = " << (int)reg.tag + // << " isSourceOperandReady " << + // uop->isSourceOperandReady(i) + // << std::endl; if (!uop->isSourceOperandReady(i)) { - std::cerr << "Not ready so rename source to " - // << (int)rat_.getMapping(reg).tag - << std::endl; + // std::cerr << "Not ready so rename source to " + // // << (int)rat_.getMapping(reg).tag + // << std::endl; uop->renameSource(i, rat_.getMapping(reg)); } diff --git a/src/lib/pipeline/ReorderBuffer.cc b/src/lib/pipeline/ReorderBuffer.cc index 8d938ed61c..3072947ae6 100644 --- a/src/lib/pipeline/ReorderBuffer.cc +++ b/src/lib/pipeline/ReorderBuffer.cc @@ -30,8 +30,8 @@ void ReorderBuffer::reserve(const std::shared_ptr& insn) { insn->setInstructionId(insnId_); if (insn->isLastMicroOp()) insnId_++; - std::cerr << "Add insn to ROB id = " << insn->getInstructionId() << " "; - insn->printInstructionInfo(); + // std::cerr << "Add insn to ROB id = " << insn->getInstructionId() << " "; + // insn->printInstructionInfo(); buffer_.push_back(insn); } @@ -87,26 +87,27 @@ unsigned int ReorderBuffer::commit(unsigned int maxCommitSize) { break; } - std::cerr << "attempting commit of id=" << uop->getInstructionId() - << std::endl; + // std::cerr << "attempting commit of id=" << uop->getInstructionId() + // << std::endl; if (uop->isLastMicroOp()) instructionsCommitted_++; if (uop->exceptionEncountered()) { - std::cerr << "EXCEPTION ENCOUNTERED" << std::endl; + // std::cerr << "EXCEPTION ENCOUNTERED" << std::endl; + // Don't remove from ROB immediately as may need to send through writeback + // and commit successfully later raiseException_(uop); uop->setExceptionEncounteredFalse(); uop->setNotCommitReady(); - // Need to send back through writeback return n; } const auto& destinations = uop->getDestinationRegisters(); for (int i = 0; i < destinations.size(); i++) { - std::cerr << "rat commit physical reg=" << destinations[i].tag - << std::endl; + // std::cerr << "rat commit physical reg=" << destinations[i].tag + // << std::endl; rat_.commit(destinations[i]); } @@ -165,7 +166,7 @@ unsigned int ReorderBuffer::commit(unsigned int maxCommitSize) { 0}; } } - std::cerr << "buffer pop" << std::endl; + // std::cerr << "buffer pop" << std::endl; buffer_.pop_front(); } diff --git a/src/lib/pipeline/WritebackUnit.cc b/src/lib/pipeline/WritebackUnit.cc index bfd31af564..f1bcba7c70 100644 --- a/src/lib/pipeline/WritebackUnit.cc +++ b/src/lib/pipeline/WritebackUnit.cc @@ -36,8 +36,9 @@ void WritebackUnit::tick() { for (size_t i = 0; i < results.size(); i++) { // Write results to register file registerFileSet_.set(destinations[i], results[i]); - std::cerr << "write to physical reg " << (int)destinations[i].tag - << " value of " << results[i].get() << std::endl; + // std::cerr << "write to physical reg " << (int)destinations[i].tag + // << " value of " << results[i].get() << + // std::endl; } if (uop->isMicroOp()) { uop->setWaitingCommit(); diff --git a/test/regression/riscv/instructions/csr.cc b/test/regression/riscv/instructions/csr.cc index 112d079b0c..f7e572cf7a 100644 --- a/test/regression/riscv/instructions/csr.cc +++ b/test/regression/riscv/instructions/csr.cc @@ -20,15 +20,10 @@ TEST_P(InstCSR, basicCsr) { EXPECT_EQ(getGeneralRegister(10), 0b101010); } -INSTANTIATE_TEST_SUITE_P( - RISCV, InstCSR, - ::testing::Values( - // std::make_tuple(EMULATION, "{}") - // , - // std::make_tuple(INORDER, "{}"), - std::make_tuple(OUTOFORDER, "{}")), - // "{Ports: {'0': {Portname: 0, Instruction-Group-Support: [INT, - // " "LOAD, STORE, BRANCH]}}}")), - paramToString); +INSTANTIATE_TEST_SUITE_P(RISCV, InstCSR, + ::testing::Values(std::make_tuple(EMULATION, "{}"), + std::make_tuple(INORDER, "{}"), + std::make_tuple(OUTOFORDER, "{}")), + paramToString); } // namespace \ No newline at end of file From 00eab11d53570174fe746c25813081d0716f04aa Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Sat, 17 Feb 2024 13:09:24 +0000 Subject: [PATCH 4/5] cleanup AArch OoO tests fail --- src/lib/arch/riscv/ExceptionHandler.cc | 5 +---- src/lib/arch/riscv/Instruction.cc | 5 ----- src/lib/arch/riscv/Instruction_execute.cc | 3 --- src/lib/models/emulation/Core.cc | 8 -------- src/lib/models/inorder/Core.cc | 4 ---- src/lib/models/outoforder/Core.cc | 24 ++--------------------- src/lib/pipeline/DecodeUnit.cc | 2 -- src/lib/pipeline/DispatchIssueUnit.cc | 19 ------------------ src/lib/pipeline/ExecuteUnit.cc | 5 ----- src/lib/pipeline/FetchUnit.cc | 4 ---- src/lib/pipeline/LoadStoreQueue.cc | 2 -- src/lib/pipeline/RegisterAliasTable.cc | 10 ---------- src/lib/pipeline/RenameUnit.cc | 16 --------------- src/lib/pipeline/ReorderBuffer.cc | 15 -------------- src/lib/pipeline/WritebackUnit.cc | 12 ------------ test/regression/RegressionTest.cc | 2 -- test/regression/riscv/instructions/csr.cc | 4 ---- 17 files changed, 3 insertions(+), 137 deletions(-) diff --git a/src/lib/arch/riscv/ExceptionHandler.cc b/src/lib/arch/riscv/ExceptionHandler.cc index 1abd60f461..d2a7bf761f 100644 --- a/src/lib/arch/riscv/ExceptionHandler.cc +++ b/src/lib/arch/riscv/ExceptionHandler.cc @@ -703,16 +703,13 @@ bool ExceptionHandler::init() { << instruction_.getMetadata().mnemonic << " id = " << instruction_.getSequenceId() << std::endl; + // TODO improve this span initialisation RegisterValue r[]{RegisterValue(result, 8)}; span res{r, std::size(r)}; instruction_.setResults(res); // Send instruction through writeback for resolution of renamed // registers stateChange = {ChangeType::WRITEBACK, {}, {}}; - // Dummy logic to allow progression. Set Rd to 0 - // stateChange = { - // ChangeType::REPLACEMENT, {destinationRegs[0]}, - // {result}}; } break; default: diff --git a/src/lib/arch/riscv/Instruction.cc b/src/lib/arch/riscv/Instruction.cc index cbcd54ce98..5598559279 100644 --- a/src/lib/arch/riscv/Instruction.cc +++ b/src/lib/arch/riscv/Instruction.cc @@ -49,9 +49,6 @@ bool Instruction::isSourceOperandReady(int index) const { void Instruction::renameSource(uint16_t i, Register renamed) { sourceRegisters[i] = renamed; - // std::cerr << "renamed source " << renamed << " renamed = " << - // renamed.renamed - // << std::endl; } void Instruction::renameDestination(uint16_t i, Register renamed) { destinationRegisters[i] = renamed; @@ -101,8 +98,6 @@ void Instruction::setResults(span resultsInput) { "[SimEng:Instruction] More results than size of array"); uint8_t n = 0; for (auto result : resultsInput) { - // std::cerr << "result = " << result.get() << std::endl; - results[n] = result; n++; } diff --git a/src/lib/arch/riscv/Instruction_execute.cc b/src/lib/arch/riscv/Instruction_execute.cc index 6e069375df..d5ae0b37f5 100644 --- a/src/lib/arch/riscv/Instruction_execute.cc +++ b/src/lib/arch/riscv/Instruction_execute.cc @@ -179,9 +179,6 @@ void Instruction::execute() { // Implementation of rv64iamfd according to the v. 20191213 unprivileged spec - // std::cerr << "execute insn "; - // printInstructionInfo(); - executed_ = true; switch (metadata.opcode) { case Opcode::RISCV_LB: { // LB rd,rs1,imm diff --git a/src/lib/models/emulation/Core.cc b/src/lib/models/emulation/Core.cc index d163b92af3..67ce0e8cf4 100644 --- a/src/lib/models/emulation/Core.cc +++ b/src/lib/models/emulation/Core.cc @@ -67,8 +67,6 @@ void Core::tick() { // Fetch - // std::cerr << "fetch" << std::endl; - // Determine if new uops are needed to be fetched if (!microOps_.size()) { // Find fetched memory that matches the current PC @@ -102,14 +100,10 @@ void Core::tick() { auto& uop = microOps_.front(); if (uop->exceptionEncountered()) { - // std::cerr << "preissue handle exception" << std::endl; - handleException(uop); return; } - // std::cerr << "issue" << std::endl; - // Issue auto registers = uop->getSourceRegisters(); for (size_t i = 0; i < registers.size(); i++) { @@ -172,8 +166,6 @@ void Core::execute(std::shared_ptr& uop) { uop->execute(); if (uop->exceptionEncountered()) { - // std::cerr << "post execute handle exception" << std::endl; - handleException(uop); return; } diff --git a/src/lib/models/inorder/Core.cc b/src/lib/models/inorder/Core.cc index 309ee8cd2b..8d511ca362 100644 --- a/src/lib/models/inorder/Core.cc +++ b/src/lib/models/inorder/Core.cc @@ -180,8 +180,6 @@ void Core::raiseException(const std::shared_ptr& instruction) { } void Core::handleException() { - std::cerr << "handle exception inorder" << std::endl; - // Flush pipeline fetchToDecodeBuffer_.fill({}); decodeToExecuteBuffer_.fill(nullptr); @@ -319,8 +317,6 @@ void Core::applyStateChange(const arch::ProcessStateChange& change) { exceptionGeneratingInstruction_->getDestinationRegisters(), exceptionGeneratingInstruction_->getResults()); - assert(completionSlots_[0].getTailSlots()[0] == nullptr && - "Don't overwrite what is there"); completionSlots_[0].getTailSlots()[0] = std::move(exceptionGeneratingInstruction_); diff --git a/src/lib/models/outoforder/Core.cc b/src/lib/models/outoforder/Core.cc index de4a5bc6c6..d9d02f721f 100644 --- a/src/lib/models/outoforder/Core.cc +++ b/src/lib/models/outoforder/Core.cc @@ -106,15 +106,11 @@ Core::Core(MemoryInterface& instructionMemory, MemoryInterface& dataMemory, }; void Core::tick() { - // std::cerr << "---- core tick ----" << std::endl; - ticks_++; if (hasHalted_) return; if (exceptionHandler_ != nullptr) { - // std::cerr << "tick process exception handler" << std::endl; - processExceptionHandler(); return; } @@ -159,9 +155,6 @@ void Core::tick() { if (exceptionGenerated_) { handleException(); - // TODO why do we request from PC when we know we will flush later. Would it - // be quicker to stall. Flush (and no other unit) never ticked until - // exception complete. Process exceptionHandler only flushes loop buffer fetchUnit_.requestFromPC(); return; } @@ -267,7 +260,7 @@ bool Core::hasHalted() const { } void Core::raiseException(const std::shared_ptr& instruction) { - assert(instruction && "raise null"); + assert(instruction && "Raised exception on null instruction"); exceptionGenerated_ = true; exceptionGeneratingInstruction_ = instruction; } @@ -295,7 +288,6 @@ void Core::handleException() { eu.purgeFlushed(); } - // TODO possible change here exceptionGenerated_ = false; exceptionHandler_ = isa_.handleException(exceptionGeneratingInstruction_, *this, dataMemory_); @@ -317,7 +309,6 @@ void Core::processExceptionHandler() { return; } - // TODO don't need to get the state change const auto& result = exceptionHandler_->getResult(); if (result.fatal) { @@ -326,7 +317,6 @@ void Core::processExceptionHandler() { } else { fetchUnit_.flushLoopBuffer(); fetchUnit_.updatePC(result.instructionAddress); - // TODO won't need to apply state change applyStateChange(result.stateChange); } @@ -334,14 +324,8 @@ void Core::processExceptionHandler() { } void Core::applyStateChange(const arch::ProcessStateChange& change) { - // std::cerr << "apply state change" << std::endl; - - // TODO THIS COULD BE DANGEROUS. APPLY STATE CHANGE NOT ONLY USED DURING - // EXCEPTION HANDLING if (change.type != arch::ChangeType::WRITEBACK && exceptionGeneratingInstruction_) { - // std::cerr << "APPLY FLUSH FROM ROB" << std::endl; - // Flush instruction from ROB reorderBuffer_.flush(exceptionGeneratingInstruction_->getInstructionId() - 1); @@ -354,8 +338,7 @@ void Core::applyStateChange(const arch::ProcessStateChange& change) { // pass through writeback in next cycle. Results held in internal results // array assert(exceptionGeneratingInstruction_ && - "exception generating instruction is NULL"); - // std::cerr << "writeback state change" << std::endl; + "Exception generating instruction is NULL"); // Forwards operands to update dispatch scoreboard as this didn't happen // in execute @@ -374,7 +357,6 @@ void Core::applyStateChange(const arch::ProcessStateChange& change) { .get() + change.modifiedRegisterValues[i].get()); } - break; } case arch::ChangeType::DECREMENT: { @@ -385,7 +367,6 @@ void Core::applyStateChange(const arch::ProcessStateChange& change) { .get() - change.modifiedRegisterValues[i].get()); } - break; } default: { // arch::ChangeType::REPLACEMENT @@ -394,7 +375,6 @@ void Core::applyStateChange(const arch::ProcessStateChange& change) { mappedRegisterFileSet_.set(change.modifiedRegisters[i], change.modifiedRegisterValues[i]); } - break; } } diff --git a/src/lib/pipeline/DecodeUnit.cc b/src/lib/pipeline/DecodeUnit.cc index 6fa971b89e..5bb497e653 100644 --- a/src/lib/pipeline/DecodeUnit.cc +++ b/src/lib/pipeline/DecodeUnit.cc @@ -11,8 +11,6 @@ DecodeUnit::DecodeUnit(PipelineBuffer& input, : input_(input), output_(output), predictor_(predictor){}; void DecodeUnit::tick() { - // std::cerr << "decode" << std::endl; - // Stall if output buffer is stalled if (output_.isStalled()) { input_.stall(true); diff --git a/src/lib/pipeline/DispatchIssueUnit.cc b/src/lib/pipeline/DispatchIssueUnit.cc index 796a7c2dd7..c362de8205 100644 --- a/src/lib/pipeline/DispatchIssueUnit.cc +++ b/src/lib/pipeline/DispatchIssueUnit.cc @@ -56,8 +56,6 @@ DispatchIssueUnit::DispatchIssueUnit( } void DispatchIssueUnit::tick() { - // std::cerr << "dispatch tick" << std::endl; - input_.stall(false); // Reset the array @@ -69,9 +67,6 @@ void DispatchIssueUnit::tick() { continue; } - // std::cerr << "dispatch uop = "; - // uop->printInstructionInfo(); - const std::vector& supportedPorts = uop->getSupportedPorts(); if (uop->exceptionEncountered()) { // Exception; mark as ready to commit, and remove from pipeline @@ -106,21 +101,12 @@ void DispatchIssueUnit::tick() { for (uint16_t i = 0; i < sourceRegisters.size(); i++) { const auto& reg = sourceRegisters[i]; - // std::cerr << "resgister read tag " << (int)reg.tag << std::endl; - if (!uop->isSourceOperandReady(i)) { - // std::cerr << "source operand isn;t ready" << std::endl; - // The operand hasn't already been supplied if (scoreboard_[reg.type][reg.tag]) { // The scoreboard says it's ready; read and supply the register value - // std::cerr << "SUPPLY THE OPERANDD" << std::endl; - uop->supplyOperand(i, registerFileSet_.get(reg)); } else { - // std::cerr << "OPERAND NOT READY YET, ADD TO DEP MATRIX" << - // std::endl; - // This register isn't ready yet. Register this uop to the dependency // matrix for a more efficient lookup later dependencyMatrix_[reg.type][reg.tag].push_back({uop, port, i}); @@ -148,8 +134,6 @@ void DispatchIssueUnit::tick() { } void DispatchIssueUnit::issue() { - // std::cerr << "dispatch issue" << std::endl; - int issued = 0; // Check the ready queues, and issue an instruction from each if the // corresponding port isn't blocked @@ -165,9 +149,6 @@ void DispatchIssueUnit::issue() { if (queue.size() > 0) { auto& uop = queue.front(); - // std::cerr << "issue uop "; - // uop->printInstructionInfo(); - issuePorts_[i].getTailSlots()[0] = std::move(uop); queue.pop_front(); diff --git a/src/lib/pipeline/ExecuteUnit.cc b/src/lib/pipeline/ExecuteUnit.cc index 12a09b3a0b..c87c2e1845 100644 --- a/src/lib/pipeline/ExecuteUnit.cc +++ b/src/lib/pipeline/ExecuteUnit.cc @@ -26,8 +26,6 @@ ExecuteUnit::ExecuteUnit( blockingGroups_(blockingGroups) {} void ExecuteUnit::tick() { - // std::cerr << "execute" << std::endl; - tickCounter_++; shouldFlush_ = false; @@ -135,9 +133,6 @@ void ExecuteUnit::execute(std::shared_ptr& uop) { } if (uop->exceptionEncountered()) { - std::cerr << "Execute exception encountered, don't forward results" - << std::endl; - // Exception; don't forward results, don't pass uop forward raiseException_(uop); return; diff --git a/src/lib/pipeline/FetchUnit.cc b/src/lib/pipeline/FetchUnit.cc index 3deb9b853a..2da1ada097 100644 --- a/src/lib/pipeline/FetchUnit.cc +++ b/src/lib/pipeline/FetchUnit.cc @@ -25,8 +25,6 @@ FetchUnit::FetchUnit(PipelineBuffer& output, FetchUnit::~FetchUnit() { delete[] fetchBuffer_; } void FetchUnit::tick() { - // std::cerr << "fetch" << std::endl; - if (output_.isStalled()) { return; } @@ -61,8 +59,6 @@ void FetchUnit::tick() { const uint8_t* buffer; uint16_t bufferOffset; - // std::cerr << "fetch from pc_=" << pc_ << std::endl; - // Check if more instruction data is required if (bufferedBytes_ < isa_.getMaxInstructionSize()) { // Calculate the address of the next fetch block diff --git a/src/lib/pipeline/LoadStoreQueue.cc b/src/lib/pipeline/LoadStoreQueue.cc index f7525134bb..0a5dbb91e3 100644 --- a/src/lib/pipeline/LoadStoreQueue.cc +++ b/src/lib/pipeline/LoadStoreQueue.cc @@ -380,8 +380,6 @@ void LoadStoreQueue::purgeFlushed() { } void LoadStoreQueue::tick() { - // std::cerr << "lsq" << std::endl; - tickCounter_++; // Send memory requests adhering to set bandwidth and number of permitted // requests per cycle diff --git a/src/lib/pipeline/RegisterAliasTable.cc b/src/lib/pipeline/RegisterAliasTable.cc index 976962d911..fb40c8d9b4 100644 --- a/src/lib/pipeline/RegisterAliasTable.cc +++ b/src/lib/pipeline/RegisterAliasTable.cc @@ -1,7 +1,6 @@ #include "simeng/pipeline/RegisterAliasTable.hh" #include -#include namespace simeng { namespace pipeline { @@ -51,10 +50,6 @@ Register RegisterAliasTable::getMapping(Register architectural) const { "Invalid register type. Cannot find RAT mapping."); auto tag = mappingTable_[architectural.type][architectural.tag]; - - // std::cerr << "mapping table for arch reg " << (int)architectural.tag << " - // = " - // << tag << std::endl; return {architectural.type, tag, true}; } @@ -80,9 +75,6 @@ Register RegisterAliasTable::allocate(Register architectural) { auto tag = freeQueue.front(); freeQueue.pop(); - // std::cerr << "rat.allocate arch reg " << (int)architectural.tag << " to " - // << (int)tag << std::endl; - // Keep the old physical register in the history table historyTable_[architectural.type][tag] = mappingTable_[architectural.type][architectural.tag]; @@ -99,8 +91,6 @@ void RegisterAliasTable::commit(Register physical) { // Find the register previously mapped to the same architectural register and // free it auto oldTag = historyTable_[physical.type][physical.tag]; - // std::cerr << "rat.commit old tag = " << (int)oldTag << std::endl; - // TODO never update mapping table?? freeQueues_[physical.type].push(oldTag); } diff --git a/src/lib/pipeline/RenameUnit.cc b/src/lib/pipeline/RenameUnit.cc index e6c9090957..d8a33697b5 100644 --- a/src/lib/pipeline/RenameUnit.cc +++ b/src/lib/pipeline/RenameUnit.cc @@ -18,8 +18,6 @@ RenameUnit::RenameUnit(PipelineBuffer>& fromDecode, freeRegistersAvailable_(registerTypes) {} void RenameUnit::tick() { - // std::cerr << "rename" << std::endl; - if (output_.isStalled()) { input_.stall(true); return; @@ -37,8 +35,6 @@ void RenameUnit::tick() { if (uop == nullptr) { continue; } - // std::cerr << "rename uop="; - // uop->printInstructionInfo(); if (reorderBuffer_.getFreeSpace() == 0) { input_.stall(true); @@ -77,9 +73,6 @@ void RenameUnit::tick() { // Count the number of each type of destination registers needed, and ensure // enough free registers exist to allocate them. for (const auto& reg : destinationRegisters) { - // std::cerr << "destination reg to rename = " << (int)reg.tag << - // std::endl; - // Check whether renaming is allowed, otherwise we need to serialize if (!rat_.canRename(reg.type)) { serialize = true; @@ -107,16 +100,7 @@ void RenameUnit::tick() { auto& sourceRegisters = uop->getSourceRegisters(); for (size_t i = 0; i < sourceRegisters.size(); i++) { const auto& reg = sourceRegisters[i]; - // std::cerr << "rename source = " << (int)reg.tag - // << " isSourceOperandReady " << - // uop->isSourceOperandReady(i) - // << std::endl; - if (!uop->isSourceOperandReady(i)) { - // std::cerr << "Not ready so rename source to " - // // << (int)rat_.getMapping(reg).tag - // << std::endl; - uop->renameSource(i, rat_.getMapping(reg)); } } diff --git a/src/lib/pipeline/ReorderBuffer.cc b/src/lib/pipeline/ReorderBuffer.cc index 3072947ae6..00daefd96b 100644 --- a/src/lib/pipeline/ReorderBuffer.cc +++ b/src/lib/pipeline/ReorderBuffer.cc @@ -30,9 +30,6 @@ void ReorderBuffer::reserve(const std::shared_ptr& insn) { insn->setInstructionId(insnId_); if (insn->isLastMicroOp()) insnId_++; - // std::cerr << "Add insn to ROB id = " << insn->getInstructionId() << " "; - // insn->printInstructionInfo(); - buffer_.push_back(insn); } @@ -74,8 +71,6 @@ void ReorderBuffer::commitMicroOps(uint64_t insnId) { } unsigned int ReorderBuffer::commit(unsigned int maxCommitSize) { - // std::cerr << "commit" << std::endl; - shouldFlush_ = false; size_t maxCommits = std::min(static_cast(maxCommitSize), buffer_.size()); @@ -87,14 +82,9 @@ unsigned int ReorderBuffer::commit(unsigned int maxCommitSize) { break; } - // std::cerr << "attempting commit of id=" << uop->getInstructionId() - // << std::endl; - if (uop->isLastMicroOp()) instructionsCommitted_++; if (uop->exceptionEncountered()) { - // std::cerr << "EXCEPTION ENCOUNTERED" << std::endl; - // Don't remove from ROB immediately as may need to send through writeback // and commit successfully later raiseException_(uop); @@ -106,9 +96,6 @@ unsigned int ReorderBuffer::commit(unsigned int maxCommitSize) { const auto& destinations = uop->getDestinationRegisters(); for (int i = 0; i < destinations.size(); i++) { - // std::cerr << "rat commit physical reg=" << destinations[i].tag - // << std::endl; - rat_.commit(destinations[i]); } @@ -166,8 +153,6 @@ unsigned int ReorderBuffer::commit(unsigned int maxCommitSize) { 0}; } } - // std::cerr << "buffer pop" << std::endl; - buffer_.pop_front(); } diff --git a/src/lib/pipeline/WritebackUnit.cc b/src/lib/pipeline/WritebackUnit.cc index f1bcba7c70..adafe35193 100644 --- a/src/lib/pipeline/WritebackUnit.cc +++ b/src/lib/pipeline/WritebackUnit.cc @@ -14,8 +14,6 @@ WritebackUnit::WritebackUnit( flagMicroOpCommits_(flagMicroOpCommits) {} void WritebackUnit::tick() { - // std::cerr << "writeback" << std::endl; - for (size_t slot = 0; slot < completionSlots_.size(); slot++) { auto& uop = completionSlots_[slot].getHeadSlots()[0]; @@ -23,22 +21,12 @@ void WritebackUnit::tick() { continue; } - // std::cerr << "writeback id = " << uop->getSequenceId() << std::endl; - auto& results = uop->getResults(); - if (results.size() > 0) { - // std::cerr << "writeback results = " << results[0].get() - // << std::endl; - } - auto& destinations = uop->getDestinationRegisters(); for (size_t i = 0; i < results.size(); i++) { // Write results to register file registerFileSet_.set(destinations[i], results[i]); - // std::cerr << "write to physical reg " << (int)destinations[i].tag - // << " value of " << results[i].get() << - // std::endl; } if (uop->isMicroOp()) { uop->setWaitingCommit(); diff --git a/test/regression/RegressionTest.cc b/test/regression/RegressionTest.cc index c4f1c1386e..5b43ac6cd0 100644 --- a/test/regression/RegressionTest.cc +++ b/test/regression/RegressionTest.cc @@ -119,8 +119,6 @@ void RegressionTest::run(const char* source, const char* triple, // Run the core model until the program is complete while (!core_->hasHalted() || dataMemory->hasPendingRequests()) { - // std::cerr << "tick" << std::endl; - ASSERT_LT(numTicks_, maxTicks_) << "Maximum tick count exceeded."; core_->tick(); instructionMemory.tick(); diff --git a/test/regression/riscv/instructions/csr.cc b/test/regression/riscv/instructions/csr.cc index f7e572cf7a..cbd48daf7b 100644 --- a/test/regression/riscv/instructions/csr.cc +++ b/test/regression/riscv/instructions/csr.cc @@ -5,10 +5,6 @@ namespace { using InstCSR = RISCVRegressionTest; TEST_P(InstCSR, basicCsr) { - std::cerr << "NEW TEST" << std::endl; - std::cerr << "" << std::endl; - std::cerr << "" << std::endl; - RUN_RISCV(R"( addi x8, x9, 1 li x8, 1 From 3598f1aaf14d44bc9aca8498fd7be6b09ee0aebd Mon Sep 17 00:00:00 2001 From: dANW34V3R Date: Mon, 19 Feb 2024 12:22:31 +0000 Subject: [PATCH 5/5] Correctly flush instructions with id=0 --- src/include/simeng/pipeline/ReorderBuffer.hh | 4 ++++ src/lib/arch/aarch64/Instruction_execute.cc | 1 + src/lib/models/outoforder/Core.cc | 4 ++-- src/lib/pipeline/ReorderBuffer.cc | 5 +++++ 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/include/simeng/pipeline/ReorderBuffer.hh b/src/include/simeng/pipeline/ReorderBuffer.hh index 2e0e76dc26..8c27e97e71 100644 --- a/src/include/simeng/pipeline/ReorderBuffer.hh +++ b/src/include/simeng/pipeline/ReorderBuffer.hh @@ -62,6 +62,10 @@ class ReorderBuffer { /** Flush all instructions with a sequence ID greater than `afterSeqId`. */ void flush(uint64_t afterInsnId); + /** Flush all instructions with a sequence ID greater than or equal to + * `afterSeqId`. */ + void flushIncluding(uint64_t InsnId); + /** Retrieve the current size of the ROB. */ unsigned int size() const; diff --git a/src/lib/arch/aarch64/Instruction_execute.cc b/src/lib/arch/aarch64/Instruction_execute.cc index 0426ba79e0..92811718bc 100644 --- a/src/lib/arch/aarch64/Instruction_execute.cc +++ b/src/lib/arch/aarch64/Instruction_execute.cc @@ -66,6 +66,7 @@ void Instruction::execute() { assert( canExecute() && "Attempted to execute an instruction before all operands were provided"); + // TODO potentially better suited as a function based on frequency of usage // 0th bit of SVCR register determines if streaming-mode is enabled. const bool SMenabled = architecture_.getSVCRval() & 1; // 1st bit of SVCR register determines if ZA register is enabled. diff --git a/src/lib/models/outoforder/Core.cc b/src/lib/models/outoforder/Core.cc index b05e409d68..f24226aa7a 100644 --- a/src/lib/models/outoforder/Core.cc +++ b/src/lib/models/outoforder/Core.cc @@ -326,8 +326,8 @@ void Core::applyStateChange(const arch::ProcessStateChange& change) { if (change.type != arch::ChangeType::WRITEBACK && exceptionGeneratingInstruction_) { // Flush instruction from ROB - reorderBuffer_.flush(exceptionGeneratingInstruction_->getInstructionId() - - 1); + reorderBuffer_.flushIncluding( + exceptionGeneratingInstruction_->getInstructionId()); } // Update registers in accordance with the ProcessStateChange type diff --git a/src/lib/pipeline/ReorderBuffer.cc b/src/lib/pipeline/ReorderBuffer.cc index 53a0c08025..b74183e3b4 100644 --- a/src/lib/pipeline/ReorderBuffer.cc +++ b/src/lib/pipeline/ReorderBuffer.cc @@ -159,6 +159,11 @@ unsigned int ReorderBuffer::commit(uint64_t maxCommitSize) { return n; } +void ReorderBuffer::flushIncluding(uint64_t InsnId) { + flush(insnId_); + buffer_.pop_back(); +} + void ReorderBuffer::flush(uint64_t afterInsnId) { // Iterate backwards from the tail of the queue to find and remove ops newer // than `afterInsnId`