Register all Registers through constructor, and manage them (clock all) through RegBase
MODIFY
src/pipeline.cpp
src/pipeline.cpp
@@ -35,11 +35,6 @@ Pipeline::Pipeline() {
mux_memToReg.setInput(1, r_readData_MEMWB.getOutput());
}
-void Pipeline::registerRegs() {
- // Registers all registers in m_regs
- m_regs.push_back(&r_instr_IFID);
-}
-
void Pipeline::immGen() {
// Generates an immediate value on the basis of an instruction opcode
// Opcode bits 5 and 6 can define the required fields for generating the immediate

MODIFY
src/pipeline.h
src/pipeline.h
@@ -19,7 +19,6 @@ public:
private:
// Simulator functions
- void registerRegs();
void immGen();
void aluCtrl();
void clock();

MODIFY
src/pipelineobjects.h
src/pipelineobjects.h
@@ -68,17 +68,30 @@ private:
std::string m_name;
};
+// The Reg class is used for sequential signal assignment. Has a single input/output of a given signal size.
+// Upon construction, new registers are added to "registers", which is used when clocking the pipeline
class RegBase {
public:
+ static std::vector<RegBase*> registers;
+ static void clockAll() {
+ // Each registers input value is save before clocking it, to ensure that register -> register connections are
+ // clocked properly
+ std::for_each(registers.begin(), registers.end(), [](auto reg) { reg->save(); });
+ std::for_each(registers.begin(), registers.end(), [](auto reg) { reg->clock(); });
+ }
+
+protected:
virtual void clock() = 0;
+ virtual void save() = 0;
};
-// The Reg class is used for sequential signal assignment. Has a single input/output of a given signal size.
template <int n>
class Reg : public RegBase {
public:
- Reg() { ASSERT_SIZE }
- void clock() override { m_current = *m_next; }
+ Reg() {
+ ASSERT_SIZE
+ RegBase::registers.push_back(this);
+ }
// Signal connection
void connect(Reg<n>& r) { setInput(&r.m_current); }
@@ -90,8 +103,13 @@ public:
explicit operator bool() const { return (bool)m_current; }
void setInput(const Signal<n>* in) { m_next = in; }
+protected:
+ void clock() override { m_current = m_nextSaved; }
+ void save() override { m_nextSaved = *m_next; }
+
private:
Signal<n> m_current;
+ Signal<n> m_nextSaved;
const Signal<n>* m_next;
};

Register all Registers through constructor, and manage them (clock all) through RegBase