commit 1d79656fbee5a3f89cdef2bf54200038de6280e1
parent fe59fd001fad39f32451291684008c4331e40720
Author: Bradley Gannon <bradley@bradleygannon.com>
Date: Mon, 30 Mar 2026 22:01:20 -0400
Add support for jalr
Diffstat:
2 files changed, 36 insertions(+), 5 deletions(-)
diff --git a/src/main/scala/controlUnit.scala b/src/main/scala/controlUnit.scala
@@ -83,6 +83,8 @@ class ControlUnit(withDebug: Boolean = false) extends Module {
state := ControlUnitState.executeI
}.elsewhen(io.op === Opcode.jal) {
state := ControlUnitState.jal
+ }.elsewhen(io.op === Opcode.jalr) {
+ state := ControlUnitState.jalrLink
}.elsewhen(io.op === Opcode.branch) {
state := ControlUnitState.branch
}.elsewhen(io.op === Opcode.env || io.op === Opcode.fence) {
@@ -143,6 +145,22 @@ class ControlUnit(withDebug: Boolean = false) extends Module {
pcUpdate := true.B
state := ControlUnitState.aluWb
}
+ is(ControlUnitState.jalrLink) {
+ io.aluSrcA := AluSrcA.oldPc
+ io.aluSrcB := AluSrcB.four
+ io.resultSrc := ResultSrc.aluResult
+ io.regWrite := true.B
+ aluOp := AluOp.arithmetic
+ state := ControlUnitState.jalrJump
+ }
+ is(ControlUnitState.jalrJump) {
+ io.aluSrcA := AluSrcA.rd1
+ io.aluSrcB := AluSrcB.immExt
+ io.resultSrc := ResultSrc.aluResult
+ aluOp := AluOp.arithmetic
+ pcUpdate := true.B
+ state := ControlUnitState.fetch
+ }
is(ControlUnitState.branch) {
io.aluSrcA := AluSrcA.rd1
io.aluSrcB := AluSrcB.rd2
@@ -251,7 +269,8 @@ class InstructionDecoder extends Module {
}
object ControlUnitState extends ChiselEnum {
- val fetch, decode, memAdr, memRead, memWb, memWrite, executeR, aluWb, executeI, jal, branch =
+ val fetch, decode, memAdr, memRead, memWb, memWrite, executeR, aluWb, executeI, jal, jalrLink,
+ jalrJump, branch =
Value
}
diff --git a/src/test/scala/perilus/main.scala b/src/test/scala/perilus/main.scala
@@ -37,12 +37,14 @@ class PerilusTests extends AnyFunSpec with ChiselSim {
rs1: Int,
rs1Value: Int,
imm: Int,
- operation: (Int, Int) => Int
+ operation: (Int, Int) => Int,
+ pc: Int = 4,
+ opcode: Int = 19
): Unit = {
var registerFile = ArrayBuffer.fill(32)(0x00000000)
registerFile(rs1) = rs1Value
val memory = ArrayBuffer.fill(64)(0x00000000)
- val instr = assembleIType(funct3, funct7_5, rd, rs1, rs1Value, imm, 19)
+ val instr = assembleIType(funct3, funct7_5, rd, rs1, rs1Value, imm, opcode)
memory(0) = instr
val expected = operation(rs1Value, imm)
@@ -65,7 +67,7 @@ class PerilusTests extends AnyFunSpec with ChiselSim {
perilusDebug.regData.expect(if (rs1 == rd) toULong(rs1Value) else 0)
perilus.clock.step(4)
- perilus.io.pc.expect(4)
+ perilus.io.pc.expect(toULong(pc))
perilusDebug.memAddr.poke(0)
perilusDebug.memData.expect(toULong(instr))
@@ -273,7 +275,17 @@ class PerilusTests extends AnyFunSpec with ChiselSim {
)
}
it("jalr") {
- cancel("Not yet implemented")
+ testIType(
+ funct3 = 0,
+ funct7_5 = false,
+ rd = 3,
+ rs1 = 8,
+ rs1Value = 32,
+ imm = 10,
+ operation = (_rs1, _imm) => 4,
+ pc = 42,
+ opcode = 103
+ )
}
}
describe("executes U-type RV32I instructions") {