Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Writeback Exceptions #393

Draft
wants to merge 6 commits into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 1 addition & 39 deletions src/include/simeng/Core.hh
Original file line number Diff line number Diff line change
Expand Up @@ -55,45 +55,7 @@ class Core {

protected:
/** Apply changes to the process state. */
void applyStateChange(const arch::ProcessStateChange& change) const {
auto& regFile = const_cast<ArchitecturalRegisterFileSet&>(
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<uint64_t>() +
change.modifiedRegisterValues[i].get<uint64_t>());
}
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<uint64_t>() -
change.modifiedRegisterValues[i].get<uint64_t>());
}
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_;
Expand Down
12 changes: 11 additions & 1 deletion src/include/simeng/Instruction.hh
Original file line number Diff line number Diff line change
Expand Up @@ -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<Register> getSourceRegisters() const = 0;

Expand All @@ -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. */
Expand All @@ -76,13 +80,19 @@ 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;

/** Retrieve register results. */
virtual const span<RegisterValue> getResults() const = 0;

/** Set results array */
virtual void setResults(span<RegisterValue> resultsInput) = 0;

/** Generate memory addresses this instruction wishes to access. */
virtual span<const memory::MemoryAccessTarget> generateAddresses() = 0;

Expand Down
2 changes: 1 addition & 1 deletion src/include/simeng/arch/ProcessStateChange.hh
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
5 changes: 4 additions & 1 deletion src/include/simeng/arch/aarch64/Instruction.hh
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ class Instruction : public simeng::Instruction {
const span<Register> 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.
*/
Expand All @@ -270,6 +270,8 @@ class Instruction : public simeng::Instruction {
/** Retrieve register results. */
const span<RegisterValue> getResults() const override;

void setResults(span<RegisterValue> resultsInput) override;

/** Generate memory addresses this instruction wishes to access. */
span<const memory::MemoryAccessTarget> generateAddresses() override;

Expand Down Expand Up @@ -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. */
Expand Down
2 changes: 1 addition & 1 deletion src/include/simeng/arch/riscv/ExceptionHandler.hh
Original file line number Diff line number Diff line change
Expand Up @@ -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_;
Expand Down
5 changes: 4 additions & 1 deletion src/include/simeng/arch/riscv/Instruction.hh
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ class Instruction : public simeng::Instruction {
const span<Register> 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.
*/
Expand All @@ -97,6 +97,8 @@ class Instruction : public simeng::Instruction {
/** Retrieve register results. */
const span<RegisterValue> getResults() const override;

void setResults(span<RegisterValue> resultsInput) override;

/** Generate memory addresses this instruction wishes to access. */
span<const memory::MemoryAccessTarget> generateAddresses() override;

Expand Down Expand Up @@ -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. */
Expand Down
6 changes: 6 additions & 0 deletions src/include/simeng/models/emulation/Core.hh
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ class Core : public simeng::Core {
/** Retrieve a map of statistics to report. */
std::map<std::string, std::string> 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<Instruction>& uop);
Expand Down Expand Up @@ -71,6 +75,8 @@ class Core : public simeng::Core {
/** The length of the available instruction memory. */
uint64_t programByteLength_ = 0;

std::shared_ptr<Instruction> exceptionGeneratingInstruction_;

/** Is the core waiting on a data read? */
uint64_t pendingReads_ = 0;

Expand Down
4 changes: 4 additions & 0 deletions src/include/simeng/models/inorder/Core.hh
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ class Core : public simeng::Core {
/** Generate a map of statistics to report. */
std::map<std::string, std::string> 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>& instruction);
Expand Down
4 changes: 4 additions & 0 deletions src/include/simeng/models/outoforder/Core.hh
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ class Core : public simeng::Core {
/** Generate a map of statistics to report. */
std::map<std::string, std::string> 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>& instruction);
Expand Down
5 changes: 5 additions & 0 deletions src/include/simeng/pipeline/ReorderBuffer.hh
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
7 changes: 7 additions & 0 deletions src/lib/Instruction.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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); }
Expand All @@ -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
5 changes: 4 additions & 1 deletion src/lib/arch/aarch64/Instruction.cc
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ const span<RegisterValue> Instruction::getSourceOperands() const {
return {const_cast<RegisterValue*>(sourceValues_.data()),
sourceValues_.size()};
}
void Instruction::printInstructionInfo() {
std::cerr << metadata_.mnemonic << " " << metadata_.operandStr << std::endl;
}

const span<Register> Instruction::getDestinationRegisters() const {
// The `destinationRegisterCount` is used here as the span count value because
Expand All @@ -51,7 +54,7 @@ const span<Register> Instruction::getDestinationRegisters() const {
return {const_cast<Register*>(destinationRegisters_.data()),
destinationRegisterCount_};
}
bool Instruction::isOperandReady(int index) const {
bool Instruction::isSourceOperandReady(int index) const {
return static_cast<bool>(sourceValues_[index]);
}

Expand Down
4 changes: 4 additions & 0 deletions src/lib/arch/aarch64/Instruction_execute.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -5902,6 +5903,9 @@ void Instruction::execute() {
}
#endif
}
void Instruction::setResults(span<RegisterValue> resultsInput) {
// TODO implement this
}

} // namespace aarch64
} // namespace arch
Expand Down
14 changes: 11 additions & 3 deletions src/lib/arch/riscv/ExceptionHandler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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<RegisterValue> res{r, std::size(r)};
instruction_.setResults(res);
// Send instruction through writeback for resolution of renamed
// registers
stateChange = {ChangeType::WRITEBACK, {}, {}};
}
break;
default:
Expand Down
16 changes: 15 additions & 1 deletion src/lib/arch/riscv/Instruction.cc
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ const span<Register> 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<bool>(sourceValues_[index]);
}

Expand Down Expand Up @@ -94,6 +95,16 @@ const span<RegisterValue> Instruction::getResults() const {
destinationRegisterCount_};
}

void Instruction::setResults(span<RegisterValue> 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_; }
Expand All @@ -107,6 +118,9 @@ void Instruction::setMemoryAddresses(
memoryAddresses_ = addresses;
dataPending_ = addresses.size();
}
void Instruction::printInstructionInfo() {
std::cerr << metadata_.mnemonic << " " << metadata_.operandStr << std::endl;
}

span<const memory::MemoryAccessTarget> Instruction::getGeneratedAddresses()
const {
Expand Down
Loading