Implement support for JAL, JALR & AUIPC instructions
MODIFY
src/pipeline.cpp
src/pipeline.cpp
@@ -14,7 +14,7 @@ Pipeline::Pipeline() {
r_PC_IF.setInput(mux_PCSrc.getOutput());
r_PC_IF.setEnable(&s_PCWrite);
r_instr_IFID.setInput(&s_instr_IF);
- r_instr_IFID.setReset(&s_branchTaken);
+ r_instr_IFID.setReset(&s_IFID_reset);
r_instr_IFID.setEnable(&s_IFID_write);
mux_PCSrc.setControl(&s_PCSrc);
mux_PCSrc.setInput(0, alu_pc4.getOutput());
@@ -24,10 +24,11 @@ Pipeline::Pipeline() {
mux_PCSrc.setInput(3, alu_mainALU.getOutput());
r_PC_IFID.setInput(r_PC_IF.getOutput());
- r_PC_IFID.setReset(&s_branchTaken);
+ r_PC_IFID.setReset(&s_IFID_reset);
r_PC_IFID.setEnable(&s_IFID_write);
r_invalidPC_IFID.setInput(&s_invalidPC);
r_PC4_IFID.setInput(alu_pc4.getOutput());
+ r_PC4_IFID.setReset(&s_IFID_reset);
// ------ ID ---------
m_reg.setInputs(&s_readRegister1, &s_readRegister2, r_writeReg_MEMWB.getOutput(), mux_memToReg.getOutput(),
@@ -59,12 +60,12 @@ Pipeline::Pipeline() {
mux_forwardA_ID.setControl(&s_forwardA_ID);
mux_forwardA_ID.setInput(Forwarding::NONE, m_reg.getOutput(1));
- mux_forwardA_ID.setInput(Forwarding::EXMEM, r_alures_EXMEM.getOutput());
+ mux_forwardA_ID.setInput(Forwarding::EXMEM, mux_alures_PC4_MEM.getOutput());
mux_forwardA_ID.setInput(Forwarding::MEMWB, mux_memToReg.getOutput());
mux_forwardB_ID.setControl(&s_forwardB_ID);
mux_forwardB_ID.setInput(Forwarding::NONE, m_reg.getOutput(2));
- mux_forwardB_ID.setInput(Forwarding::EXMEM, r_alures_EXMEM.getOutput());
+ mux_forwardB_ID.setInput(Forwarding::EXMEM, mux_alures_PC4_MEM.getOutput());
mux_forwardB_ID.setInput(Forwarding::MEMWB, mux_memToReg.getOutput());
alu_pc_target.setControl(&s_alu_const_add);
@@ -73,18 +74,25 @@ Pipeline::Pipeline() {
// Control signals
r_regWrite_IDEX.setInput(&s_RegWrite);
r_ALUOP_IDEX.setInput(&s_ALUOP);
- r_ALUSrc_IDEX.setInput(&s_ALUSrc);
+ r_ALUSrc1_IDEX.setInput(&s_ALUSrc1);
+ r_ALUSrc2_IDEX.setInput(&s_ALUSrc2);
r_MemWrite_IDEX.setInput(&s_MemWrite);
r_MemRead_IDEX.setInput(&s_MemRead);
r_memToReg_IDEX.setInput(&s_memToReg);
+ r_jal_IDEX.setInput(&s_jal);
+ r_jalr_IDEX.setInput(&s_jalr);
// ------ EX ---------
- alu_mainALU.setInputs(mux_forwardA_EX.getOutput(), mux_ALUSrc.getOutput());
+ alu_mainALU.setInputs(mux_ALUSrc1.getOutput(), mux_ALUSrc2.getOutput());
alu_mainALU.setControl(r_ALUOP_IDEX.getOutput());
- mux_ALUSrc.setInput(0, mux_forwardB_EX.getOutput());
- mux_ALUSrc.setInput(1, r_imm_IDEX.getOutput());
- mux_ALUSrc.setControl(r_ALUSrc_IDEX.getOutput());
+ mux_ALUSrc1.setInput(0, mux_forwardA_EX.getOutput());
+ mux_ALUSrc1.setInput(1, r_PC_IDEX.getOutput());
+ mux_ALUSrc1.setControl(r_ALUSrc1_IDEX.getOutput());
+
+ mux_ALUSrc2.setInput(0, mux_forwardB_EX.getOutput());
+ mux_ALUSrc2.setInput(1, r_imm_IDEX.getOutput());
+ mux_ALUSrc2.setControl(r_ALUSrc2_IDEX.getOutput());
r_alures_EXMEM.setInput(alu_mainALU.getOutput());
r_writeData_EXMEM.setInput(mux_forwardB_EX.getOutput());
r_writeReg_EXMEM.setInput(r_writeReg_IDEX.getOutput());
@@ -93,14 +101,17 @@ Pipeline::Pipeline() {
r_invalidPC_EXMEM.setInput(r_invalidPC_IDEX.getOutput());
r_PC4_EXMEM.setInput(r_PC4_IDEX.getOutput());
+ r_jal_EXMEM.setInput(r_jal_IDEX.getOutput());
+ r_jalr_EXMEM.setInput(r_jalr_IDEX.getOutput());
+
mux_forwardA_EX.setControl(&s_forwardA_EX);
mux_forwardA_EX.setInput(Forwarding::NONE, r_rd1_IDEX.getOutput());
- mux_forwardA_EX.setInput(Forwarding::EXMEM, r_alures_EXMEM.getOutput());
+ mux_forwardA_EX.setInput(Forwarding::EXMEM, mux_alures_PC4_MEM.getOutput());
mux_forwardA_EX.setInput(Forwarding::MEMWB, mux_memToReg.getOutput());
mux_forwardB_EX.setControl(&s_forwardB_EX);
mux_forwardB_EX.setInput(Forwarding::NONE, r_rd2_IDEX.getOutput());
- mux_forwardB_EX.setInput(Forwarding::EXMEM, r_alures_EXMEM.getOutput());
+ mux_forwardB_EX.setInput(Forwarding::EXMEM, mux_alures_PC4_MEM.getOutput());
mux_forwardB_EX.setInput(Forwarding::MEMWB, mux_memToReg.getOutput());
// Control signals
@@ -110,6 +121,10 @@ Pipeline::Pipeline() {
r_memToReg_EXMEM.setInput(r_memToReg_IDEX.getOutput());
// ------ MEM --------
+ mux_alures_PC4_MEM.setInput(0, r_alures_EXMEM.getOutput());
+ mux_alures_PC4_MEM.setInput(1, r_PC4_EXMEM.getOutput());
+ mux_alures_PC4_MEM.setControl(&s_alures_PC4_MEM);
+
r_readData_MEMWB.setInput(&readData_MEM);
r_alures_MEMWB.setInput(r_alures_EXMEM.getOutput());
r_writeReg_MEMWB.setInput(r_writeReg_EXMEM.getOutput());
@@ -128,13 +143,17 @@ Pipeline::Pipeline() {
}
void Pipeline::immGen() {
- if (((uint32_t)r_instr_IFID & 0b1111111) == 0b0110111) {
- // LUI
+ uint32_t opcode = (uint32_t)r_instr_IFID & 0b1111111;
+ if (opcode == 0b0110111 || opcode == 0b0010111) {
+ // LUI & AUIPC
s_imm_ID = Signal<32>((uint32_t)r_instr_IFID & 0xfffff000);
- } else if (((uint32_t)r_instr_IFID & 0b1111111) == 0b1101111) {
+ } else if (opcode == 0b1101111) {
// JAL
auto fields = Parser::getParser()->decodeJInstr((uint32_t)r_instr_IFID);
s_imm_ID = signextend<int32_t, 21>(fields[0] << 20 | fields[1] << 1 | fields[2] << 11 | fields[3] << 12);
+ } else if (opcode == 0b1100111) {
+ // JALR
+ s_imm_ID = Signal<32>(signextend<int32_t, 12>(((uint32_t)r_instr_IFID >> 20)));
} else {
// 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
@@ -164,7 +183,8 @@ void Pipeline::immGen() {
void Pipeline::controlGen() {
// Deassert all control lines
s_ALUOP = 0;
- s_ALUSrc = 0;
+ s_ALUSrc1 = 0;
+ s_ALUSrc2 = 0;
s_memToReg = MemToReg::ALURES;
s_RegWrite = 0;
s_MemRead = 0;
@@ -178,8 +198,16 @@ void Pipeline::controlGen() {
switch ((uint32_t)r_instr_IFID & 0b1111111) {
case 0b0110111: {
// LUI
- s_ALUOP = ALUDefs::LUI;
- s_ALUSrc = 1;
+ s_ALUOP = ALUOps::LUI;
+ s_ALUSrc2 = 1;
+ s_RegWrite = 1;
+ break;
+ }
+ case 0b0010111: {
+ // AUIPC
+ s_ALUSrc1 = 1;
+ s_ALUOP = ALUOps::ADD;
+ s_ALUSrc2 = 1;
s_RegWrite = 1;
break;
}
@@ -189,56 +217,56 @@ void Pipeline::controlGen() {
switch (fields[2]) {
case 0b000: {
// ADDI
- s_ALUOP = ALUDefs::ADD;
+ s_ALUOP = ALUOps::ADD;
break;
}
case 0b010: {
// SLTI
- s_ALUOP = ALUDefs::LT;
+ s_ALUOP = ALUOps::LT;
break;
}
case 0b011: {
// SLTIU
- s_ALUOP = ALUDefs::LTU;
+ s_ALUOP = ALUOps::LTU;
break;
}
case 0b100: {
// XORI
- s_ALUOP = ALUDefs::XOR;
+ s_ALUOP = ALUOps::XOR;
break;
}
case 0b110: {
// ORI
- s_ALUOP = ALUDefs::OR;
+ s_ALUOP = ALUOps::OR;
break;
}
case 0b111: {
// ANDI
- s_ALUOP = ALUDefs::AND;
+ s_ALUOP = ALUOps::AND;
break;
}
case 0b001: {
// SLLI
- s_ALUOP = ALUDefs::SL;
+ s_ALUOP = ALUOps::SL;
break;
}
case 0b101: {
switch ((uint32_t)r_instr_IFID >> 25) {
case 0b0: {
// SRLI
- s_ALUOP = ALUDefs::SRL;
+ s_ALUOP = ALUOps::SRL;
break;
}
case 0b0100000: {
// SRAI
- s_ALUOP = ALUDefs::SRA;
+ s_ALUOP = ALUOps::SRA;
break;
}
}
break;
}
}
- s_ALUSrc = 1;
+ s_ALUSrc2 = 1;
s_RegWrite = 1;
break;
}
@@ -250,12 +278,12 @@ void Pipeline::controlGen() {
switch (fields[0]) {
case 0b0000000: {
// ADD
- s_ALUOP = ALUDefs::ADD;
+ s_ALUOP = ALUOps::ADD;
break;
}
- case 0100000: {
+ case 0b0100000: {
// SUB
- s_ALUOP = ALUDefs::SUB;
+ s_ALUOP = ALUOps::SUB;
break;
}
}
@@ -263,34 +291,34 @@ void Pipeline::controlGen() {
}
case 0b001: {
// SLL
- s_ALUOP = ALUDefs::SL;
+ s_ALUOP = ALUOps::SL;
break;
}
case 0b010: {
// SLT
- s_ALUOP = ALUDefs::LT;
+ s_ALUOP = ALUOps::LT;
break;
}
case 0b011: {
// SLTU
- s_ALUOP = ALUDefs::LTU;
+ s_ALUOP = ALUOps::LTU;
break;
}
case 0b100: {
// XOR
- s_ALUOP = ALUDefs::XOR;
+ s_ALUOP = ALUOps::XOR;
break;
}
case 0b101: {
switch (fields[0]) {
case 0b0000000: {
// SRL
- s_ALUOP = ALUDefs::SRL;
+ s_ALUOP = ALUOps::SRL;
break;
}
case 0b0100000: {
// SRA
- s_ALUOP = ALUDefs::SRA;
+ s_ALUOP = ALUOps::SRA;
break;
}
}
@@ -298,12 +326,12 @@ void Pipeline::controlGen() {
}
case 0b110: {
// OR
- s_ALUOP = ALUDefs::OR;
+ s_ALUOP = ALUOps::OR;
break;
}
case 0b111: {
// AND
- s_ALUOP = ALUDefs::AND;
+ s_ALUOP = ALUOps::AND;
break;
}
}
@@ -340,7 +368,7 @@ void Pipeline::controlGen() {
break;
}
}
- s_ALUSrc = 1;
+ s_ALUSrc2 = 1;
s_memToReg = MemToReg::MEMREAD;
s_RegWrite = 1;
break;
@@ -365,7 +393,7 @@ void Pipeline::controlGen() {
break;
}
}
- s_ALUSrc = 1;
+ s_ALUSrc2 = 1;
break;
}
case 0b1100011: {
@@ -415,7 +443,8 @@ void Pipeline::controlGen() {
}
case 0b1100111: {
// JALR
- s_ALUSrc = 1;
+ s_ALUOP = ALUOps::ADD;
+ s_ALUSrc2 = 1;
s_memToReg = MemToReg::PC4;
s_RegWrite = 1;
s_jalr = 1;
@@ -494,19 +523,22 @@ void Pipeline::hazardControlGen() {
// Load Use hazard: Loaded variable is needed in execute stage
bool loadUseHazard = (r1 == (uint32_t)r_writeReg_IDEX || r2 == (uint32_t)r_writeReg_IDEX) && (bool)r_MemRead_IDEX;
- // Jump target must be computed before JALR jump can be performed
- bool jalrHazard = ((uint32_t)r_instr_IFID & 0b1111111) == 0b1100111;
-
- if (branchHazard || loadUseHazard || jalrHazard) { // Require branch instruction
+ if (branchHazard || loadUseHazard) {
// Stall until hazard is resolved - keep IFID and PC vaues, and reset IDEX registers
s_PCWrite = 0;
s_IFID_write = 0;
s_IDEX_reset = 1;
+
} else {
s_PCWrite = 1;
s_IFID_write = 1;
s_IDEX_reset = 0;
}
+
+ // JALR hazard - IFID register is reset for s_jal & r_jal_idex but IDEX needs to be reset aswell for JALR
+ if (r_jalr_IDEX) {
+ s_IDEX_reset = 1;
+ };
}
void Pipeline::propagateCombinational() {
@@ -526,6 +558,8 @@ void Pipeline::propagateCombinational() {
mux_memToReg.update();
// ----- MEM -----
+ s_alures_PC4_MEM = (uint32_t)(r_jalr_EXMEM || r_jal_EXMEM);
+ mux_alures_PC4_MEM.update();
if (r_MemRead_EXMEM) {
switch ((uint32_t)r_MemRead_EXMEM) {
case LB: {
@@ -553,8 +587,9 @@ void Pipeline::propagateCombinational() {
// ----- EX -----
mux_forwardB_EX.update();
- mux_ALUSrc.update();
+ mux_ALUSrc2.update();
mux_forwardA_EX.update();
+ mux_ALUSrc1.update();
alu_mainALU.update();
// ----- ID -----
@@ -595,9 +630,12 @@ void Pipeline::propagateCombinational() {
default: { s_branchTaken = 0; }
}
- // b1=true for s_PCSrc will unconditionally take s_jalr PC target. Else, take branch outcome calculation if
+ // b1=true for s_PCSrc will unconditionally take r_jal_IDEX PC target. Else, take branch outcome calculation if
// s_branchTaken or s_jal. if deasserted, PC+4 is selected
- s_PCSrc = ((uint32_t)s_jalr << 1) + (uint32_t)(s_branchTaken || s_jal);
+ s_PCSrc = ((uint32_t)r_jalr_IDEX << 1) + (uint32_t)(s_branchTaken || s_jal);
+
+ // IFID should be reset when branch is taken and when jumping
+ s_IFID_reset = s_branchTaken || r_jalr_IDEX || s_jal;
// ----- IF -----
alu_pc4.update();
@@ -610,6 +648,41 @@ void Pipeline::propagateCombinational() {
// For GUI - set invalidPC (branch taken indicator) if PCSrc both PCSrc and s_IFID_write is asserted - in this
// case, a new program counter value is starting to propagate, indicating an invalid ID branch
s_invalidPC = (bool)s_branchTaken && (bool)s_IFID_write;
+
+ // handle ECALL I/O. If a0 = 10 for an ECALL, this sets m_finishing and increments finishing counter
+ // if m_finishing is set, we disable PC writing
+ handleEcall();
+ s_PCWrite = m_finishing ? 0 : s_PCWrite;
+ s_IFID_reset = m_finishing ? 1 : s_IFID_reset;
+}
+
+void Pipeline::handleEcall() {
+ if (((uint32_t)r_instr_IFID & 0b1111111) == 0b1110011) {
+ // ECALL
+ uint32_t a0_val = m_reg.a0();
+
+ // Since a0 is not expressed in the ECALL function (and thus not triggering the usual forwarding logic), we have
+ // to do manual forwarding
+ if ((uint32_t)r_writeReg_MEMWB == 10) {
+ // Forward a0 value from MEMWB
+ a0_val = (uint32_t)*mux_memToReg.getOutput();
+ }
+ if ((uint32_t)r_writeReg_EXMEM == 10) {
+ // Forward a0 value from EXMEM
+ a0_val = (uint32_t)*mux_alures_PC4_MEM.getOutput();
+ }
+ if ((uint32_t)r_writeReg_IDEX == 10) {
+ // Forward a0 value from EX stage
+ a0_val = (uint32_t)*alu_mainALU.getOutput();
+ }
+ if (a0_val == 10) {
+ // Start finishing sequence
+ m_finishing = true;
+ }
+ }
+ if (m_finishing) {
+ m_finishingCnt++;
+ }
}
int Pipeline::step() {
@@ -644,8 +717,9 @@ int Pipeline::step() {
// Set stage program counters
setStagePCS();
- // Check for finished execution and breakpoints
- if (m_pcs.WB.pc > m_textSize) {
+ // Check for finished execution(either end of file or m_finishingCnt > 4 (if ecall 10 has been called)) and
+ // breakpoints
+ if ((m_pcs.WB.pc > m_textSize) || (m_finishingCnt > 4)) {
m_finished = true;
return 1;
} else if (m_breakpoints.find((uint32_t)r_PC_IF) != m_breakpoints.end()) {
@@ -701,6 +775,8 @@ void Pipeline::restart() {
m_pcs.reset();
m_pcsPre.reset();
m_finished = false;
+ m_finishing = false;
+ m_finishingCnt = 0;
// Reset all registers to 0 and propagate signals through combinational logic
RegBase::resetAll();

MODIFY
src/pipeline.h
src/pipeline.h
@@ -38,6 +38,7 @@ private:
void immGen();
void controlGen();
void forwardingControlGen();
+ void handleEcall();
void hazardControlGen();
void aluCtrl();
void clock();
@@ -47,7 +48,10 @@ private:
void setStagePCS();
StagePCS m_pcs;
StagePCS m_pcsPre;
+ bool m_finishing =
+ false; // Set when ecall 10 is detected, and the pipeline is running its remaining instructions through
bool m_finished = false;
+ int m_finishingCnt = 0;
// Memory
Registers m_reg;
@@ -62,9 +66,9 @@ private:
ALU<32> alu_pc_target = ALU<32>("ALU PC target"); // ALU for PC target computation
ALU<32> alu_mainALU = ALU<32>("Main ALU"); // Arithmetic ALU
- Mux<2, 32> mux_ALUSrc;
+ Mux<2, 32> mux_ALUSrc1;
+ Mux<2, 32> mux_ALUSrc2;
Mux<3, 32> mux_memToReg;
-
Signal<32> s_imm_ID = Signal<32>("Immediate");
Signal<32> s_instr_IF = Signal<32>("Instruction");
Signal<32> readData_MEM;
@@ -73,44 +77,52 @@ private:
Mux<3, 32> mux_forwardA_EX, mux_forwardB_EX, mux_forwardA_ID,
mux_forwardB_ID; // Forwarding mux'es for execute stage and ID stage (branch comparison operation)
- Signal<2> s_forwardA_EX, s_forwardB_EX, s_forwardA_ID, s_forwardB_ID;
Signal<1> s_invalidPC;
+ Mux<2, 32> mux_alures_PC4_MEM;
+
// Registers
Reg<5> r_readRegister1_IDEX, r_readRegister2_IDEX;
- std::vector<RegBase*> m_regs;
Reg<32> r_instr_IFID, r_rd1_IDEX, r_rd2_IDEX, r_imm_IDEX, r_alures_EXMEM, r_writeData_EXMEM, r_readData_MEMWB,
r_alures_MEMWB;
Reg<32> r_PC_IF, r_PC_IFID, r_PC_IDEX, r_PC_EXMEM, r_PC_MEMWB;
Reg<32> r_PC4_IFID, r_PC4_IDEX, r_PC4_EXMEM, r_PC4_MEMWB;
Reg<1> r_invalidPC_IFID, r_invalidPC_IDEX, r_invalidPC_EXMEM, r_invalidPC_MEMWB;
+ Reg<1> r_jal_IDEX, r_jal_EXMEM, r_jalr_IDEX, r_jalr_EXMEM;
+
Signal<5> writeReg;
Reg<5> r_writeReg_IDEX, r_writeReg_EXMEM, r_writeReg_MEMWB; // Write register (# of register to write to)
RegBank bank_IDEX;
// Control propagation registers
Reg<1> r_regWrite_IDEX, r_regWrite_EXMEM, r_regWrite_MEMWB; // Register write signal
- Reg<ALUDefs::CTRL_SIZE> r_ALUOP_IDEX;
- Reg<1> r_ALUSrc_IDEX; // Multiplexor control signals
+ Reg<ALUOps::CTRL_SIZE> r_ALUOP_IDEX;
+ Reg<1> r_ALUSrc1_IDEX, r_ALUSrc2_IDEX; // Multiplexor control signals
Reg<3> r_MemRead_IDEX, r_MemRead_EXMEM; // Write/read from memory signals. Funct3 value for instruction determines
// signal value (ie. byte width and signed/unsigned load)
Reg<2> r_MemWrite_IDEX, r_MemWrite_EXMEM, r_memToReg_IDEX, r_memToReg_EXMEM, r_memToReg_MEMWB;
// Control signals
- Signal<ALUDefs::CTRL_SIZE> s_alu_const_add = Signal<ALUDefs::CTRL_SIZE>(
- (uint32_t)ALUDefs::OPCODE::ADD); // A constant "ADD" control signal, to turn an ALU into an adder
+ Signal<ALUOps::CTRL_SIZE> s_alu_const_add = Signal<ALUOps::CTRL_SIZE>(
+ (uint32_t)ALUOps::OPCODE::ADD); // A constant "ADD" control signal, to turn an ALU into an adder
Signal<3> s_MemRead;
Signal<2> s_MemWrite;
Signal<2> s_memToReg;
- Signal<1> s_RegWrite, s_ALUSrc, s_Branch;
- Signal<ALUDefs::CTRL_SIZE> s_ALUOP;
+ Signal<1> s_RegWrite;
+ Signal<1> s_ALUSrc1, s_ALUSrc2; // Multiplexor control signal for ALU input (2:1)
+ Signal<2> s_forwardA_EX, s_forwardB_EX, s_forwardA_ID,
+ s_forwardB_ID; // Multiplexor control signal for ALU and ID register forwarding (3:1)
+ Signal<1> s_Branch;
+ Signal<ALUOps::CTRL_SIZE> s_ALUOP;
Signal<3> s_CompOp;
Signal<1> s_validPC; // used for GUI to determine whether a PC = 0 is a nop (register flush) or valid
Signal<1> s_PCWrite; // Used when a branch instruction requires a pipeline stall
- Signal<1> s_IFID_write; // Used when a branch instruction requires a pipeline stall
+ Signal<1> s_IFID_write, s_IFID_reset; // Used when clearing IFID after branching or jumping
Signal<1> s_IDEX_reset; // Used when a branch instruction requires a pipeline stall
Signal<2> s_PCSrc;
Signal<1> s_jal, s_jalr;
+ Signal<1> s_auipc; // used for controlling input 1 to main alu (registers or PC)
+ Signal<1> s_alures_PC4_MEM; // Control signal for forwarding MUX in MEM stage
// Control signal enums
enum CompOp { BEQ = 1, BNE = 2, BLT = 3, BLTU = 4, BGE = 5, BGEU = 6 };

MODIFY
src/pipelineobjects.h
src/pipelineobjects.h
@@ -248,7 +248,7 @@ private:
std::function<bool(bool, const Signal<n>&)> m_op;
};
-namespace ALUDefs {
+namespace ALUOps {
static const int CTRL_SIZE = 5;
enum OPCODE {
ADD = 0,
@@ -266,7 +266,7 @@ enum OPCODE {
LTU = 12,
EQ = 13
};
-} // namespace ALUDefs
+} // namespace ALUOps
template <int n>
class ALU {
@@ -283,7 +283,7 @@ public:
Signal<n>* getOutput() { return &m_output; }
- void setControl(const Signal<ALUDefs::CTRL_SIZE>* sig) { m_control = sig; }
+ void setControl(const Signal<ALUOps::CTRL_SIZE>* sig) { m_control = sig; }
private:
bool initialized() {
@@ -297,51 +297,51 @@ private:
Signal<n> m_output;
const Signal<n>* m_op1;
const Signal<n>* m_op2;
- const Signal<ALUDefs::CTRL_SIZE>* m_control;
+ const Signal<ALUOps::CTRL_SIZE>* m_control;
};
template <int n>
void ALU<n>::update() {
if (!initialized())
throw std::runtime_error("Mux not initialized");
- switch ((ALUDefs::OPCODE)(int)*m_control) {
- case ALUDefs::ADD:
+ switch ((ALUOps::OPCODE)(int)*m_control) {
+ case ALUOps::ADD:
m_output = (uint32_t)*m_op1 + (uint32_t)*m_op2;
break;
- case ALUDefs::SUB:
+ case ALUOps::SUB:
m_output = (uint32_t)*m_op1 - (uint32_t)*m_op2;
break;
- case ALUDefs::MUL:
+ case ALUOps::MUL:
m_output = (uint32_t)*m_op1 * (uint32_t)*m_op2;
break;
- case ALUDefs::DIV:
+ case ALUOps::DIV:
m_output = (uint32_t)*m_op1 / (uint32_t)*m_op2;
break;
- case ALUDefs::AND:
+ case ALUOps::AND:
m_output = (uint32_t)*m_op1 & (uint32_t)*m_op2;
break;
- case ALUDefs::OR:
+ case ALUOps::OR:
m_output = (uint32_t)*m_op1 | (uint32_t)*m_op2;
break;
- case ALUDefs::XOR:
+ case ALUOps::XOR:
m_output = (uint32_t)*m_op1 ^ (uint32_t)*m_op2;
break;
- case ALUDefs::SL:
+ case ALUOps::SL:
m_output = (uint32_t)*m_op1 << (uint32_t)*m_op2;
break;
- case ALUDefs::SRA:
+ case ALUOps::SRA:
m_output = (int32_t)*m_op1 >> (uint32_t)*m_op2;
break;
- case ALUDefs::SRL:
+ case ALUOps::SRL:
m_output = (uint32_t)*m_op1 >> (uint32_t)*m_op2;
break;
- case ALUDefs::LUI:
+ case ALUOps::LUI:
m_output = (uint32_t)*m_op2;
break;
- case ALUDefs::LT:
+ case ALUOps::LT:
m_output = (int)*m_op1 < (int)*m_op2 ? 1 : 0;
break;
- case ALUDefs::LTU:
+ case ALUOps::LTU:
m_output = (uint32_t)*m_op1 < (uint32_t)*m_op2 ? 1 : 0;
break;
default:
@@ -367,6 +367,8 @@ public:
Signal<1>* regWrite);
Signal<32>* getOutput(int n = 1) { return n == 2 ? &m_readData2 : &m_readData1; }
+ uint32_t a0() { return m_reg[10]; } // Direct accessor for a0 register (ECALL functionality)
+
private:
// ReadRegister 1/2 is deduced from the input instruction signal
const Signal<1>* m_regWrite;

MODIFY
src/processortab.ui
src/processortab.ui
<x>0</x>
<y>0</y>
<width>1152</width>
- <height>411</height>
+ <height>563</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
- <layout class="QGridLayout" name="gridLayout">
- <item row="0" column="0">
- <layout class="QVBoxLayout" name="verticalLayout_4">
+ <layout class="QVBoxLayout" name="verticalLayout_2" stretch="0,1">
<item>
<widget class="QGroupBox" name="groupBox_2">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
<property name="title">
<string>Simulation settings</string>
</property>
<layout class="QGridLayout" name="gridLayout_7">
<item row="0" column="0">
- <layout class="QHBoxLayout" name="horizontalLayout_5">
+ <layout class="QHBoxLayout" name="horizontalLayout_5" stretch="0,0,0,0,0,0,0,0,0,0,0,0">
<item>
<widget class="QPushButton" name="run">
<property name="toolTip">
<string>Run until encountering a breakpoint or to the end of the program</string>
</property>
<property name="text">
- <string>Run</string>
+ <string>Run (F4)</string>
+ </property>
+ <property name="shortcut">
+ <string>F4</string>
</property>
</widget>
</item>
</widget>
</item>
<item>
- <layout class="QHBoxLayout" name="horizontalLayout_2">
- <item>
+ <widget class="QSplitter" name="splitter">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="childrenCollapsible">
+ <bool>false</bool>
+ </property>
<widget class="PipelineWidget" name="pipelineWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
</sizepolicy>
</property>
</widget>
- </item>
- <item>
- <layout class="QVBoxLayout" name="verticalLayout">
+ <widget class="QWidget" name="layoutWidget">
+ <layout class="QVBoxLayout" name="verticalLayout" stretch="0,0">
<item>
<widget class="RegisterContainerWidget" name="registerContainer" native="true">
<property name="minimumSize">
</widget>
</item>
</layout>
- </item>
- </layout>
- </item>
- </layout>
+ </widget>
+ </widget>
</item>
</layout>
</widget>

Implement support for JAL, JALR & AUIPC instructions