RV5S/RV5SWOF: Refactor finish condition
Ditch the finishing counter. Instead, execution has finished once all stages
contains invalid instructions.
MODIFY
src/processors/RISC-V/riscv.h
src/processors/RISC-V/riscv.h
@@ -68,49 +68,4 @@ private:
decode_functor m_decodeBInstr;
};
-/**
- * @brief The FinishingCounter struct
- * May be used to control how many cycles are allowed to be performed once a processor has been designated to begin its
- * finishing sequence. Increment/decrement operators may be used in conjunction with clocking/reversing the circuit.
- */
-struct FinishingCounter {
- void start(int _target) {
- if (finishing || finished)
- return; // Already running
- target = _target;
- finishing = true;
- count = 0;
- finished = false;
- }
- void reset() {
- finishing = false;
- finished = false;
- }
-
- bool finishing = false;
- int count;
- int target;
- bool finished = false;
- void operator++(int) {
- if (!finishing || finished)
- return;
- count++;
- if (count == target) {
- finishing = false;
- finished = true;
- }
- }
- void operator--(int) {
- if (finished) {
- finished = false;
- finishing = true;
- }
- if (!finishing)
- return;
- count--;
- if (count == 0)
- finishing = false;
- }
-};
-
} // namespace Ripes

MODIFY
src/processors/RISC-V/rv5s/rv5s.h
src/processors/RISC-V/rv5s/rv5s.h
@@ -376,16 +376,18 @@ public:
m_syscallExitCycle = m_cycleCount;
}
ecallChecker->setSysCallExiting(ecallChecker->isSysCallExiting() || fr.exitSyscall);
- if (ecallChecker->isSysCallExiting()) {
- // Ecall is handled in the EX stage. Hence, only stages > EX should be cleared. All stages < EX are invalid.
- m_fcntr.start(STAGECOUNT - ID);
- } else if (fr.any()) {
- m_fcntr.start(STAGECOUNT);
- } else {
- m_fcntr.reset();
}
+
+ bool finished() const override {
+ // The processor is finished when there are no more valid instructions in the pipeline
+ bool allStagesInvalid = true;
+ for (int stage = IF; stage < STAGECOUNT; stage++) {
+ allStagesInvalid &= !stageInfo(stage).pc_valid;
+ if (!allStagesInvalid)
+ break;
+ }
+ return allStagesInvalid;
}
- bool finished() const override { return m_fcntr.finished; }
void setRegister(unsigned i, uint32_t v) override { setSynchronousValue(registerFile->_wr_mem, i, v); }
@@ -397,38 +399,28 @@ public:
}
RipesProcessor::clock();
- if (!hzunit->stallEcallHandling.uValue()) {
- m_fcntr++;
- }
}
void reverse() override {
if (m_syscallExitCycle != -1 && (m_cycleCount - 1) == m_syscallExitCycle) {
- // We are about to undo an exit syscall instruction. In this case, the syscall exiting sequence should be
- // terminate
+ // We are about to undo an exit syscall instruction. In this case, the syscall exiting sequence should
+ // be terminate
ecallChecker->setSysCallExiting(false);
m_syscallExitCycle = -1;
- finalize(FinalizeReason());
}
RipesProcessor::reverse();
if (memwb_reg->valid_out.uValue() != 0 && isExecutableAddress(memwb_reg->pc_out.uValue())) {
m_instructionsRetired--;
}
- if (!hzunit->stallEcallHandling.uValue()) {
- m_fcntr--;
- }
}
void reset() override {
ecallChecker->setSysCallExiting(false);
RipesProcessor::reset();
- m_fcntr.reset();
m_syscallExitCycle = -1;
}
private:
- FinishingCounter m_fcntr;
-
/**
* @brief m_syscallExitCycle
* The variable will contain the cycle of which an exit system call was executed. From this, we may determine

MODIFY
src/processors/RISC-V/rv5swof/rv5swof.h
src/processors/RISC-V/rv5swof/rv5swof.h
@@ -292,8 +292,8 @@ public:
default: case IF: stageValid &= isExecutableAddress(pc_reg->out.uValue()); break;
}
- // Are we currently clearing the pipeline due to a syscall exit? if such, the first stage (IF) is never valid
- if(stage == IF){
+ // Are we currently clearing the pipeline due to a syscall exit? if such, all stages before the EX stage are invalid
+ if(stage < EX){
stageValid &= !ecallChecker->isSysCallExiting();
}
@@ -316,14 +316,18 @@ public:
m_syscallExitCycle = m_cycleCount;
}
ecallChecker->setSysCallExiting(ecallChecker->isSysCallExiting() || fr.exitSyscall);
- if (ecallChecker->isSysCallExiting() || fr.any()) {
- m_fcntr.start(STAGECOUNT);
- } else {
- m_fcntr.reset();
}
- }
- bool finished() const override { return m_fcntr.finished; }
+ bool finished() const override {
+ // The processor is finished when there are no more valid instructions in the pipeline
+ bool allStagesInvalid = true;
+ for (int stage = IF; stage < STAGECOUNT; stage++) {
+ allStagesInvalid &= !stageInfo(stage).pc_valid;
+ if (!allStagesInvalid)
+ break;
+ }
+ return allStagesInvalid;
+ }
void setRegister(unsigned i, uint32_t v) override { setSynchronousValue(registerFile->_wr_mem, i, v); }
void clock() override {
@@ -334,7 +338,6 @@ public:
}
RipesProcessor::clock();
- m_fcntr++;
}
void reverse() override {
@@ -343,26 +346,20 @@ public:
// terminate
ecallChecker->setSysCallExiting(false);
m_syscallExitCycle = -1;
- finalize(FinalizeReason());
}
RipesProcessor::reverse();
if (memwb_reg->valid_out.uValue() != 0 && isExecutableAddress(memwb_reg->pc_out.uValue())) {
m_instructionsRetired--;
}
-
- m_fcntr--;
}
void reset() override {
RipesProcessor::reset();
- m_fcntr.reset();
ecallChecker->setSysCallExiting(false);
m_syscallExitCycle = -1;
}
private:
- FinishingCounter m_fcntr;
-
/**
* @brief m_syscallExitCycle
* The variable will contain the cycle of which an exit system call was executed. From this, we may determine when

RV5S/RV5SWOF: Refactor finish condition

Ditch the finishing counter. Instead, execution has finished once all stages
contains invalid instructions.