diff --git a/src/include/simeng/Core.hh b/src/include/simeng/Core.hh index cba2df9b97..91be2df1bc 100644 --- a/src/include/simeng/Core.hh +++ b/src/include/simeng/Core.hh @@ -55,45 +55,7 @@ class Core { protected: /** Apply changes to the process state. */ - void applyStateChange(const arch::ProcessStateChange& change) const { - auto& regFile = const_cast( - getArchitecturalRegisterFileSet()); - // Update registers in accordance with the ProcessStateChange type - switch (change.type) { - case arch::ChangeType::INCREMENT: { - for (size_t i = 0; i < change.modifiedRegisters.size(); i++) { - regFile.set(change.modifiedRegisters[i], - regFile.get(change.modifiedRegisters[i]).get() + - change.modifiedRegisterValues[i].get()); - } - break; - } - case arch::ChangeType::DECREMENT: { - for (size_t i = 0; i < change.modifiedRegisters.size(); i++) { - regFile.set(change.modifiedRegisters[i], - regFile.get(change.modifiedRegisters[i]).get() - - change.modifiedRegisterValues[i].get()); - } - break; - } - default: { // arch::ChangeType::REPLACEMENT - // If type is ChangeType::REPLACEMENT, set new values - for (size_t i = 0; i < change.modifiedRegisters.size(); i++) { - regFile.set(change.modifiedRegisters[i], - change.modifiedRegisterValues[i]); - } - break; - } - } - - // Update memory - // TODO: Analyse if ChangeType::INCREMENT or ChangeType::DECREMENT case is - // required for memory changes - for (size_t i = 0; i < change.memoryAddresses.size(); i++) { - dataMemory_.requestWrite(change.memoryAddresses[i], - change.memoryAddressValues[i]); - } - } + virtual void applyStateChange(const arch::ProcessStateChange& change) = 0; /** A memory interface to access data. */ memory::MemoryInterface& dataMemory_; diff --git a/src/include/simeng/Instruction.hh b/src/include/simeng/Instruction.hh index 1b2f7cdb79..ac1d30cea3 100644 --- a/src/include/simeng/Instruction.hh +++ b/src/include/simeng/Instruction.hh @@ -36,6 +36,10 @@ class Instruction { * instruction. */ bool exceptionEncountered() const; + void setExceptionEncounteredFalse(); + + virtual void printInstructionInfo() = 0; + /** Retrieve the source registers this instruction reads. */ virtual const span getSourceRegisters() const = 0; @@ -60,7 +64,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. */ @@ -76,6 +80,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; @@ -83,6 +90,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/ProcessStateChange.hh b/src/include/simeng/arch/ProcessStateChange.hh index 08302a8233..9bd989c363 100644 --- a/src/include/simeng/arch/ProcessStateChange.hh +++ b/src/include/simeng/arch/ProcessStateChange.hh @@ -11,7 +11,7 @@ namespace simeng { 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 7e5f99f2d1..032049eed6 100644 --- a/src/include/simeng/arch/aarch64/Instruction.hh +++ b/src/include/simeng/arch/aarch64/Instruction.hh @@ -247,7 +247,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. */ @@ -270,6 +270,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; @@ -322,6 +324,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/ExceptionHandler.hh b/src/include/simeng/arch/riscv/ExceptionHandler.hh index f28e6f3929..19157dba73 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 85bb4c3cf4..b019aedbec 100644 --- a/src/include/simeng/arch/riscv/Instruction.hh +++ b/src/include/simeng/arch/riscv/Instruction.hh @@ -74,7 +74,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. */ @@ -97,6 +97,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; @@ -155,6 +157,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/include/simeng/models/emulation/Core.hh b/src/include/simeng/models/emulation/Core.hh index 9f1d4c2c1d..ba71b39b5f 100644 --- a/src/include/simeng/models/emulation/Core.hh +++ b/src/include/simeng/models/emulation/Core.hh @@ -39,6 +39,10 @@ class Core : public simeng::Core { /** Retrieve a map of statistics to report. */ std::map getStats() const override; + protected: + /** Apply changes to the process state. */ + void applyStateChange(const arch::ProcessStateChange& change) override; + private: /** Execute an instruction. */ void execute(std::shared_ptr& uop); @@ -71,6 +75,8 @@ class Core : public simeng::Core { /** The length of the available instruction memory. */ uint64_t programByteLength_ = 0; + std::shared_ptr exceptionGeneratingInstruction_; + /** Is the core waiting on a data read? */ uint64_t pendingReads_ = 0; diff --git a/src/include/simeng/models/inorder/Core.hh b/src/include/simeng/models/inorder/Core.hh index 7b4b74f713..1c0d80aa39 100644 --- a/src/include/simeng/models/inorder/Core.hh +++ b/src/include/simeng/models/inorder/Core.hh @@ -43,6 +43,10 @@ class Core : public simeng::Core { /** Generate a map of statistics to report. */ std::map getStats() const override; + protected: + /** Apply changes to the process state. */ + void applyStateChange(const arch::ProcessStateChange& change) override; + private: /** Raise an exception to the core, providing the generating instruction. */ void raiseException(const std::shared_ptr& instruction); diff --git a/src/include/simeng/models/outoforder/Core.hh b/src/include/simeng/models/outoforder/Core.hh index 2b1b16f8a0..e6698d5204 100644 --- a/src/include/simeng/models/outoforder/Core.hh +++ b/src/include/simeng/models/outoforder/Core.hh @@ -49,6 +49,10 @@ class Core : public simeng::Core { /** Generate a map of statistics to report. */ std::map getStats() const override; + protected: + /** Apply changes to the process state. */ + void applyStateChange(const arch::ProcessStateChange& change) override; + private: /** Raise an exception to the core, providing the generating instruction. */ void raiseException(const std::shared_ptr& instruction); diff --git a/src/include/simeng/pipeline/ReorderBuffer.hh b/src/include/simeng/pipeline/ReorderBuffer.hh index b67075af2d..8c27e97e71 100644 --- a/src/include/simeng/pipeline/ReorderBuffer.hh +++ b/src/include/simeng/pipeline/ReorderBuffer.hh @@ -56,11 +56,16 @@ 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(uint64_t maxCommitSize); /** 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/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.cc b/src/lib/arch/aarch64/Instruction.cc index 0c77f1413b..c76603ba5b 100644 --- a/src/lib/arch/aarch64/Instruction.cc +++ b/src/lib/arch/aarch64/Instruction.cc @@ -42,6 +42,9 @@ const span Instruction::getSourceOperands() const { return {const_cast(sourceValues_.data()), sourceValues_.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 @@ -51,7 +54,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(sourceValues_[index]); } diff --git a/src/lib/arch/aarch64/Instruction_execute.cc b/src/lib/arch/aarch64/Instruction_execute.cc index 98a6cc4c53..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. @@ -5902,6 +5903,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 4082e70572..5479aa6ad1 100644 --- a/src/lib/arch/riscv/ExceptionHandler.cc +++ b/src/lib/arch/riscv/ExceptionHandler.cc @@ -694,9 +694,17 @@ bool ExceptionHandler::init() { // Only update if registers should be written to if (destinationRegs.size() > 0) { - // Dummy logic to allow progression. Set Rd to 0 - stateChange = { - ChangeType::REPLACEMENT, {destinationRegs[0]}, {result}}; + std::cerr << "handler opcode = " + << 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, {}, {}}; } break; default: diff --git a/src/lib/arch/riscv/Instruction.cc b/src/lib/arch/riscv/Instruction.cc index 62ecd57eab..7aa7b6ccdb 100644 --- a/src/lib/arch/riscv/Instruction.cc +++ b/src/lib/arch/riscv/Instruction.cc @@ -43,7 +43,8 @@ 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(sourceValues_[index]); } @@ -94,6 +95,16 @@ const span Instruction::getResults() const { 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) { + results_[n] = result; + n++; + } +} + bool Instruction::isStoreAddress() const { return isStore_; } bool Instruction::isStoreData() const { return isStore_; } bool Instruction::isLoad() const { return isLoad_; } @@ -107,6 +118,9 @@ void Instruction::setMemoryAddresses( memoryAddresses_ = addresses; dataPending_ = addresses.size(); } +void Instruction::printInstructionInfo() { + std::cerr << metadata_.mnemonic << " " << metadata_.operandStr << std::endl; +} span Instruction::getGeneratedAddresses() const { diff --git a/src/lib/models/emulation/Core.cc b/src/lib/models/emulation/Core.cc index 274b8bf7c8..4a52a479ad 100644 --- a/src/lib/models/emulation/Core.cc +++ b/src/lib/models/emulation/Core.cc @@ -104,7 +104,7 @@ void Core::tick() { 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)); } } @@ -217,6 +217,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(); } @@ -253,6 +254,59 @@ void Core::processExceptionHandler() { instructionMemory_.requestRead({pc_, FETCH_SIZE}); microOps_.pop(); } +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( + change.modifiedRegisters[i], + registerFileSet_.get(change.modifiedRegisters[i]).get() + + change.modifiedRegisterValues[i].get()); + } + break; + } + case arch::ChangeType::DECREMENT: { + for (size_t i = 0; i < change.modifiedRegisters.size(); i++) { + registerFileSet_.set( + change.modifiedRegisters[i], + registerFileSet_.get(change.modifiedRegisters[i]).get() - + change.modifiedRegisterValues[i].get()); + } + break; + } + default: { // arch::ChangeType::REPLACEMENT + // If type is ChangeType::REPLACEMENT, set new values + for (size_t i = 0; i < change.modifiedRegisters.size(); i++) { + registerFileSet_.set(change.modifiedRegisters[i], + change.modifiedRegisterValues[i]); + } + break; + } + } + + // Update memory + // TODO: Analyse if ChangeType::INCREMENT or ChangeType::DECREMENT case is + // required for memory changes + for (size_t i = 0; i < change.memoryAddresses.size(); i++) { + dataMemory_.requestWrite(change.memoryAddresses[i], + change.memoryAddressValues[i]); + } +} } // namespace emulation } // namespace models diff --git a/src/lib/models/inorder/Core.cc b/src/lib/models/inorder/Core.cc index ce4339eff0..d0e7eebe9e 100644 --- a/src/lib/models/inorder/Core.cc +++ b/src/lib/models/inorder/Core.cc @@ -173,18 +173,18 @@ void Core::raiseException(const std::shared_ptr& instruction) { } void Core::handleException() { + // Flush pipeline + fetchToDecodeBuffer_.fill({}); + decodeToExecuteBuffer_.fill(nullptr); + decodeUnit_.purgeFlushed(); + completionSlots_[0].fill(nullptr); + exceptionGenerated_ = false; exceptionHandler_ = isa_.handleException(exceptionGeneratingInstruction_, *this, dataMemory_); processExceptionHandler(); - - // Flush pipeline - fetchToDecodeBuffer_.fill({}); - decodeToExecuteBuffer_.fill(nullptr); - decodeUnit_.purgeFlushed(); - completionSlots_[0].fill(nullptr); } void Core::processExceptionHandler() { @@ -286,7 +286,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]); } @@ -309,11 +309,60 @@ 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)); } } } +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()); + + completionSlots_[0].getTailSlots()[0] = + std::move(exceptionGeneratingInstruction_); + + break; + } + case arch::ChangeType::INCREMENT: { + for (size_t i = 0; i < change.modifiedRegisters.size(); i++) { + registerFileSet_.set( + change.modifiedRegisters[i], + registerFileSet_.get(change.modifiedRegisters[i]).get() + + change.modifiedRegisterValues[i].get()); + } + break; + } + case arch::ChangeType::DECREMENT: { + for (size_t i = 0; i < change.modifiedRegisters.size(); i++) { + registerFileSet_.set( + change.modifiedRegisters[i], + registerFileSet_.get(change.modifiedRegisters[i]).get() - + change.modifiedRegisterValues[i].get()); + } + break; + } + default: { // arch::ChangeType::REPLACEMENT + // If type is ChangeType::REPLACEMENT, set new values + for (size_t i = 0; i < change.modifiedRegisters.size(); i++) { + registerFileSet_.set(change.modifiedRegisters[i], + change.modifiedRegisterValues[i]); + } + break; + } + } + + // Update memory + // TODO: Analyse if ChangeType::INCREMENT or ChangeType::DECREMENT case is + // required for memory changes + for (size_t i = 0; i < change.memoryAddresses.size(); i++) { + dataMemory_.requestWrite(change.memoryAddresses[i], + change.memoryAddressValues[i]); + } +} } // namespace inorder } // namespace models diff --git a/src/lib/models/outoforder/Core.cc b/src/lib/models/outoforder/Core.cc index 41fe3fa38c..f24226aa7a 100644 --- a/src/lib/models/outoforder/Core.cc +++ b/src/lib/models/outoforder/Core.cc @@ -6,6 +6,8 @@ #include #include +#include "simeng/Core.hh" + namespace simeng { namespace models { namespace outoforder { @@ -256,8 +258,8 @@ std::map Core::getStats() const { {"lsq.loadViolations", std::to_string(reorderBuffer_.getViolatingLoadsCount())}}; } - void Core::raiseException(const std::shared_ptr& instruction) { + assert(instruction && "Raised exception on null instruction"); exceptionGenerated_ = true; exceptionGeneratingInstruction_ = instruction; } @@ -275,6 +277,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(); @@ -318,6 +322,71 @@ void Core::processExceptionHandler() { exceptionHandler_ = nullptr; } +void Core::applyStateChange(const arch::ProcessStateChange& change) { + if (change.type != arch::ChangeType::WRITEBACK && + exceptionGeneratingInstruction_) { + // Flush instruction from ROB + reorderBuffer_.flushIncluding( + exceptionGeneratingInstruction_->getInstructionId()); + } + + // 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"); + + // 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( + change.modifiedRegisters[i], + mappedRegisterFileSet_.get(change.modifiedRegisters[i]) + .get() + + change.modifiedRegisterValues[i].get()); + } + break; + } + case arch::ChangeType::DECREMENT: { + for (size_t i = 0; i < change.modifiedRegisters.size(); i++) { + mappedRegisterFileSet_.set( + change.modifiedRegisters[i], + mappedRegisterFileSet_.get(change.modifiedRegisters[i]) + .get() - + change.modifiedRegisterValues[i].get()); + } + break; + } + default: { // arch::ChangeType::REPLACEMENT + // If type is ChangeType::REPLACEMENT, set new values + for (size_t i = 0; i < change.modifiedRegisters.size(); i++) { + mappedRegisterFileSet_.set(change.modifiedRegisters[i], + change.modifiedRegisterValues[i]); + } + break; + } + } + + // Update memory + // TODO: Analyse if ChangeType::INCREMENT or ChangeType::DECREMENT case is + // required for memory changes + for (size_t i = 0; i < change.memoryAddresses.size(); i++) { + dataMemory_.requestWrite(change.memoryAddresses[i], + change.memoryAddressValues[i]); + } +} + void Core::flushIfNeeded() { // Check for flush bool euFlush = false; diff --git a/src/lib/pipeline/DispatchIssueUnit.cc b/src/lib/pipeline/DispatchIssueUnit.cc index afd7390215..c362de8205 100644 --- a/src/lib/pipeline/DispatchIssueUnit.cc +++ b/src/lib/pipeline/DispatchIssueUnit.cc @@ -101,7 +101,7 @@ void DispatchIssueUnit::tick() { for (uint16_t i = 0; i < sourceRegisters.size(); i++) { const auto& reg = sourceRegisters[i]; - if (!uop->isOperandReady(i)) { + if (!uop->isSourceOperandReady(i)) { // 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 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/RegisterAliasTable.cc b/src/lib/pipeline/RegisterAliasTable.cc index 23bcac3980..fb40c8d9b4 100644 --- a/src/lib/pipeline/RegisterAliasTable.cc +++ b/src/lib/pipeline/RegisterAliasTable.cc @@ -91,6 +91,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]; + freeQueues_[physical.type].push(oldTag); } diff --git a/src/lib/pipeline/RenameUnit.cc b/src/lib/pipeline/RenameUnit.cc index 6cbf0add4a..d8a33697b5 100644 --- a/src/lib/pipeline/RenameUnit.cc +++ b/src/lib/pipeline/RenameUnit.cc @@ -35,6 +35,7 @@ void RenameUnit::tick() { if (uop == nullptr) { continue; } + if (reorderBuffer_.getFreeSpace() == 0) { input_.stall(true); robStalls_++; @@ -99,7 +100,7 @@ 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)) { + if (!uop->isSourceOperandReady(i)) { uop->renameSource(i, rat_.getMapping(reg)); } } diff --git a/src/lib/pipeline/ReorderBuffer.cc b/src/lib/pipeline/ReorderBuffer.cc index 2a3e7dd1ff..b74183e3b4 100644 --- a/src/lib/pipeline/ReorderBuffer.cc +++ b/src/lib/pipeline/ReorderBuffer.cc @@ -85,9 +85,13 @@ unsigned int ReorderBuffer::commit(uint64_t maxCommitSize) { if (uop->isLastMicroOp()) instructionsCommitted_++; if (uop->exceptionEncountered()) { + // Don't remove from ROB immediately as may need to send through writeback + // and commit successfully later raiseException_(uop); - buffer_.pop_front(); - return n + 1; + uop->setExceptionEncounteredFalse(); + uop->setNotCommitReady(); + + return n; } const auto& destinations = uop->getDestinationRegisters(); @@ -155,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` diff --git a/src/lib/pipeline/WritebackUnit.cc b/src/lib/pipeline/WritebackUnit.cc index 1176793fcd..adafe35193 100644 --- a/src/lib/pipeline/WritebackUnit.cc +++ b/src/lib/pipeline/WritebackUnit.cc @@ -22,6 +22,7 @@ void WritebackUnit::tick() { } auto& results = uop->getResults(); + 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..cbd48daf7b --- /dev/null +++ b/test/regression/riscv/instructions/csr.cc @@ -0,0 +1,25 @@ +#include "RISCVRegressionTest.hh" + +namespace { + +using InstCSR = RISCVRegressionTest; + +TEST_P(InstCSR, basicCsr) { + 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(INORDER, "{}"), + std::make_tuple(OUTOFORDER, "{}")), + paramToString); + +} // namespace \ No newline at end of file diff --git a/test/unit/MockCore.hh b/test/unit/MockCore.hh index c76f8ea808..bbd695a6d9 100644 --- a/test/unit/MockCore.hh +++ b/test/unit/MockCore.hh @@ -12,6 +12,7 @@ class MockCore : public Core { const std::vector& regFileStructure) : Core(dataMemory, isa, regFileStructure) {} MOCK_METHOD0(tick, void()); + MOCK_METHOD1(applyStateChange, void(const arch::ProcessStateChange& change)); MOCK_CONST_METHOD0(hasHalted, bool()); MOCK_CONST_METHOD0(getArchitecturalRegisterFileSet, const ArchitecturalRegisterFileSet&()); diff --git a/test/unit/MockInstruction.hh b/test/unit/MockInstruction.hh index 839f42bd34..c4bb1dc0a9 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 1613262588..80fda16f30 100644 --- a/test/unit/aarch64/InstructionTest.cc +++ b/test/unit/aarch64/InstructionTest.cc @@ -135,7 +135,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); @@ -199,7 +199,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); @@ -265,7 +265,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); @@ -335,9 +335,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}; @@ -349,9 +349,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); @@ -395,10 +395,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); @@ -439,10 +439,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/pipeline/DispatchIssueUnitTest.cc b/test/unit/pipeline/DispatchIssueUnitTest.cc index 9bd953f567..07a9e9a016 100644 --- a/test/unit/pipeline/DispatchIssueUnitTest.cc +++ b/test/unit/pipeline/DispatchIssueUnitTest.cc @@ -129,9 +129,9 @@ TEST_F(PipelineDispatchIssueUnitTest, singleInstr) { uop->setExceptionEncountered(false); EXPECT_CALL(*uop, getSourceRegisters()) .WillOnce(Return(span(srcRegs))); - EXPECT_CALL(*uop, isOperandReady(0)).WillOnce(Return(false)); + EXPECT_CALL(*uop, isSourceOperandReady(0)).WillOnce(Return(false)); EXPECT_CALL(*uop, supplyOperand(0, RegisterValue(0, 8))); - EXPECT_CALL(*uop, isOperandReady(1)).WillOnce(Return(false)); + EXPECT_CALL(*uop, isSourceOperandReady(1)).WillOnce(Return(false)); EXPECT_CALL(*uop, supplyOperand(1, RegisterValue(0, 8))); EXPECT_CALL(*uop, getDestinationRegisters()) .WillOnce(Return(span(destRegs))); @@ -372,7 +372,7 @@ TEST_F(PipelineDispatchIssueUnitTest, createdependency_raw) { uop->setExceptionEncountered(false); EXPECT_CALL(*uop, getSourceRegisters()) .WillOnce(Return(span(srcRegs_1))); - EXPECT_CALL(*uop, isOperandReady(0)).WillOnce(Return(false)); + EXPECT_CALL(*uop, isSourceOperandReady(0)).WillOnce(Return(false)); EXPECT_CALL(*uop, supplyOperand(0, RegisterValue(0, 8))); EXPECT_CALL(*uop, getDestinationRegisters()) .WillOnce(Return(span(destRegs_1))); @@ -392,7 +392,7 @@ TEST_F(PipelineDispatchIssueUnitTest, createdependency_raw) { uop->setExceptionEncountered(false); EXPECT_CALL(*uop2, getSourceRegisters()) .WillOnce(Return(span(srcRegs_2))); - EXPECT_CALL(*uop2, isOperandReady(0)).WillOnce(Return(false)); + EXPECT_CALL(*uop2, isSourceOperandReady(0)).WillOnce(Return(false)); EXPECT_CALL(*uop2, getDestinationRegisters()) .WillOnce(Return(span(destRegs_2))); // Expected call to port allocator during tick() @@ -466,7 +466,7 @@ TEST_F(PipelineDispatchIssueUnitTest, purgeFlushed) { uop->setExceptionEncountered(false); EXPECT_CALL(*uop, getSourceRegisters()) .WillOnce(Return(span(srcRegs_1))); - EXPECT_CALL(*uop, isOperandReady(0)).WillOnce(Return(false)); + EXPECT_CALL(*uop, isSourceOperandReady(0)).WillOnce(Return(false)); EXPECT_CALL(*uop, supplyOperand(0, RegisterValue(0, 8))); EXPECT_CALL(*uop, getDestinationRegisters()) .WillOnce(Return(span(destRegs_1))); @@ -483,7 +483,7 @@ TEST_F(PipelineDispatchIssueUnitTest, purgeFlushed) { uop->setExceptionEncountered(false); EXPECT_CALL(*uop2, getSourceRegisters()) .WillOnce(Return(span(srcRegs_2))); - EXPECT_CALL(*uop2, isOperandReady(0)).WillOnce(Return(false)); + EXPECT_CALL(*uop2, isSourceOperandReady(0)).WillOnce(Return(false)); EXPECT_CALL(*uop2, getDestinationRegisters()) .WillOnce(Return(span(destRegs_2))); // Expected call to port allocator during tick() diff --git a/test/unit/pipeline/RenameUnitTest.cc b/test/unit/pipeline/RenameUnitTest.cc index 23a1e3dd71..ed4c35b09f 100644 --- a/test/unit/pipeline/RenameUnitTest.cc +++ b/test/unit/pipeline/RenameUnitTest.cc @@ -95,7 +95,7 @@ TEST_F(RenameUnitTest, tick) { .WillByDefault(Return(span(destRegs))); ON_CALL(*uop, getSourceRegisters()) .WillByDefault(Return(span(srcRegs))); - ON_CALL(*uop, isOperandReady(_)).WillByDefault(Return(false)); + ON_CALL(*uop, isSourceOperandReady(_)).WillByDefault(Return(false)); ON_CALL(*uop, isLoad()).WillByDefault(Return(false)); ON_CALL(*uop, isStoreAddress()).WillByDefault(Return(false)); @@ -104,7 +104,7 @@ TEST_F(RenameUnitTest, tick) { EXPECT_CALL(*uop, isStoreAddress()).Times(1); EXPECT_CALL(*uop, getDestinationRegisters()).Times(1); EXPECT_CALL(*uop, getSourceRegisters()).Times(1); - EXPECT_CALL(*uop, isOperandReady(_)).Times(2); + EXPECT_CALL(*uop, isSourceOperandReady(_)).Times(2); EXPECT_CALL(*uop, renameSource(_, _)).Times(2); EXPECT_CALL(*uop, renameDestination(0, _)).Times(1); renameUnit.tick(); @@ -169,7 +169,7 @@ TEST_F(RenameUnitTest, noFreeRegs) { std::array destRegs = {r0}; ON_CALL(*uop, getDestinationRegisters()) .WillByDefault(Return(span(destRegs))); - ON_CALL(*uop, isOperandReady(_)).WillByDefault(Return(false)); + ON_CALL(*uop, isSourceOperandReady(_)).WillByDefault(Return(false)); ON_CALL(*uop, isLoad()).WillByDefault(Return(false)); ON_CALL(*uop, isStoreAddress()).WillByDefault(Return(false)); @@ -228,7 +228,7 @@ TEST_F(RenameUnitTest, loadUop) { .WillByDefault(Return(span(destRegs))); ON_CALL(*uop, getSourceRegisters()) .WillByDefault(Return(span(srcRegs))); - ON_CALL(*uop, isOperandReady(_)).WillByDefault(Return(false)); + ON_CALL(*uop, isSourceOperandReady(_)).WillByDefault(Return(false)); ON_CALL(*uop, isLoad()).WillByDefault(Return(true)); ON_CALL(*uop, isStoreAddress()).WillByDefault(Return(false)); @@ -237,7 +237,7 @@ TEST_F(RenameUnitTest, loadUop) { EXPECT_CALL(*uop, isStoreAddress()).Times(1); EXPECT_CALL(*uop, getDestinationRegisters()).Times(1); EXPECT_CALL(*uop, getSourceRegisters()).Times(1); - EXPECT_CALL(*uop, isOperandReady(_)).Times(2); + EXPECT_CALL(*uop, isSourceOperandReady(_)).Times(2); EXPECT_CALL(*uop, renameSource(_, _)).Times(2); EXPECT_CALL(*uop, renameDestination(0, _)).Times(1); renameUnit.tick(); @@ -277,7 +277,7 @@ TEST_F(RenameUnitTest, loadUopQueueFull) { .WillByDefault(Return(span(destRegs))); ON_CALL(*uop, getSourceRegisters()) .WillByDefault(Return(span(srcRegs))); - ON_CALL(*uop, isOperandReady(_)).WillByDefault(Return(false)); + ON_CALL(*uop, isSourceOperandReady(_)).WillByDefault(Return(false)); ON_CALL(*uop, isLoad()).WillByDefault(Return(true)); ON_CALL(*uop, isStoreAddress()).WillByDefault(Return(false)); @@ -314,7 +314,7 @@ TEST_F(RenameUnitTest, storeUop) { .WillByDefault(Return(span(destRegs))); ON_CALL(*uop, getSourceRegisters()) .WillByDefault(Return(span(srcRegs))); - ON_CALL(*uop, isOperandReady(_)).WillByDefault(Return(false)); + ON_CALL(*uop, isSourceOperandReady(_)).WillByDefault(Return(false)); ON_CALL(*uop, isLoad()).WillByDefault(Return(false)); ON_CALL(*uop, isStoreAddress()).WillByDefault(Return(true)); @@ -323,7 +323,7 @@ TEST_F(RenameUnitTest, storeUop) { EXPECT_CALL(*uop, isStoreAddress()).Times(1); EXPECT_CALL(*uop, getDestinationRegisters()).Times(1); EXPECT_CALL(*uop, getSourceRegisters()).Times(1); - EXPECT_CALL(*uop, isOperandReady(_)).Times(2); + EXPECT_CALL(*uop, isSourceOperandReady(_)).Times(2); EXPECT_CALL(*uop, renameSource(_, _)).Times(2); EXPECT_CALL(*uop, renameDestination(0, _)).Times(1); renameUnit.tick(); @@ -363,7 +363,7 @@ TEST_F(RenameUnitTest, storeUopQueueFull) { .WillByDefault(Return(span(destRegs))); ON_CALL(*uop, getSourceRegisters()) .WillByDefault(Return(span(srcRegs))); - ON_CALL(*uop, isOperandReady(_)).WillByDefault(Return(false)); + ON_CALL(*uop, isSourceOperandReady(_)).WillByDefault(Return(false)); ON_CALL(*uop, isLoad()).WillByDefault(Return(false)); ON_CALL(*uop, isStoreAddress()).WillByDefault(Return(true)); @@ -406,7 +406,7 @@ TEST_F(RenameUnitTest, serializedDest) { .WillByDefault(Return(span(destRegs))); ON_CALL(*uop, getSourceRegisters()) .WillByDefault(Return(span(srcRegs))); - ON_CALL(*uop, isOperandReady(_)).WillByDefault(Return(false)); + ON_CALL(*uop, isSourceOperandReady(_)).WillByDefault(Return(false)); ON_CALL(*uop, isLoad()).WillByDefault(Return(false)); ON_CALL(*uop, isStoreAddress()).WillByDefault(Return(false)); @@ -436,7 +436,7 @@ TEST_F(RenameUnitTest, serializedDest) { EXPECT_CALL(*uop, isStoreAddress()).Times(1); EXPECT_CALL(*uop, getDestinationRegisters()).Times(1); EXPECT_CALL(*uop, getSourceRegisters()).Times(1); - EXPECT_CALL(*uop, isOperandReady(_)).Times(2); + EXPECT_CALL(*uop, isSourceOperandReady(_)).Times(2); EXPECT_CALL(*uop, renameSource(_, _)).Times(2); renameUnit.tick(); diff --git a/test/unit/riscv/InstructionTest.cc b/test/unit/riscv/InstructionTest.cc index baf8073402..73810735b5 100644 --- a/test/unit/riscv/InstructionTest.cc +++ b/test/unit/riscv/InstructionTest.cc @@ -131,7 +131,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); @@ -195,7 +195,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); @@ -261,7 +261,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); @@ -330,8 +330,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}; @@ -340,8 +340,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); @@ -382,10 +382,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); @@ -421,10 +421,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);