commit e1885a909491dfcaebfbacdf2bc3b1b0095b3431
parent 2a60eae4eae580443792e072aa31c1df80c5d388
Author: Bradley Gannon <bradley@bradleygannon.com>
Date: Thu, 2 Apr 2026 20:26:23 -0400
Add support for lui and auipc
Diffstat:
5 files changed, 81 insertions(+), 7 deletions(-)
diff --git a/src/main/scala/alu.scala b/src/main/scala/alu.scala
@@ -72,9 +72,9 @@ object AluSrcB extends ChiselEnum {
}
object AluOp extends ChiselEnum {
- val memory, branch, arithmetic = Value
+ val memory, branch, arithmetic, auipc = Value
}
object ResultSrc extends ChiselEnum {
- val aluOutBuf, readDataBuf, aluResult = Value
+ val aluOutBuf, readDataBuf, aluResult, immExt = Value
}
diff --git a/src/main/scala/controlUnit.scala b/src/main/scala/controlUnit.scala
@@ -87,6 +87,10 @@ class ControlUnit(withDebug: Boolean = false) extends Module {
state := ControlUnitState.jalrLink
}.elsewhen(io.op === Opcode.branch) {
state := ControlUnitState.branch
+ }.elsewhen(io.op === Opcode.lui) {
+ state := ControlUnitState.lui
+ }.elsewhen(io.op === Opcode.auipc) {
+ state := ControlUnitState.auipc
}.elsewhen(io.op === Opcode.env || io.op === Opcode.fence) {
state := ControlUnitState.fetch
}
@@ -169,13 +173,26 @@ class ControlUnit(withDebug: Boolean = false) extends Module {
branch := true.B
state := ControlUnitState.fetch
}
+ is(ControlUnitState.lui) {
+ io.resultSrc := ResultSrc.immExt
+ io.regWrite := true.B
+ state := ControlUnitState.fetch
+ }
+ is(ControlUnitState.auipc) {
+ io.resultSrc := ResultSrc.aluResult
+ io.aluSrcA := AluSrcA.oldPc
+ io.aluSrcB := AluSrcB.immExt
+ aluOp := AluOp.auipc
+ io.regWrite := true.B
+ state := ControlUnitState.fetch
+ }
}
io.pcWrite := ((branch && ((io.funct3 === 0.U && io.zero)
|| (io.funct3 === 1.U && !io.zero)
|| ((io.funct3 === 4.U || io.funct3 === 6.U) && io.lessThan)
|| ((io.funct3 === 5.U || io.funct3 === 7.U) && !io.lessThan)))
- || pcUpdate)
+ || pcUpdate)
aluDecoder.io.aluOp := aluOp
aluDecoder.io.funct3 := io.funct3
@@ -201,6 +218,9 @@ class AluDecoder extends Module {
io.aluControl := AluControl.add
switch(io.aluOp) {
+ is(AluOp.auipc) {
+ io.aluControl := AluControl.add
+ }
is(AluOp.memory) {
io.aluControl := AluControl.add
}
@@ -277,12 +297,18 @@ class InstructionDecoder extends Module {
is(Opcode.jal) {
io.immSrc := ImmSrc.jType
}
+ is(Opcode.lui) {
+ io.immSrc := ImmSrc.uType
+ }
+ is(Opcode.auipc) {
+ io.immSrc := ImmSrc.uType
+ }
}
}
object ControlUnitState extends ChiselEnum {
val fetch, decode, memAdr, memRead, memWb, memWrite, executeR, aluWb, executeI, jal, jalrLink,
- jalrJump, branch =
+ jalrJump, branch, lui, auipc =
Value
}
diff --git a/src/main/scala/extendUnit.scala b/src/main/scala/extendUnit.scala
@@ -41,9 +41,12 @@ class ExtendUnit extends Module {
0.U(1.W)
)
}
+ is(ImmSrc.uType) {
+ io.immExt := Cat(io.input(24, 5), Fill(12, 0.U))
+ }
}
}
object ImmSrc extends ChiselEnum {
- val iTypeSigned, iTypeUnsigned, sType, bType, jType = Value
+ val iTypeSigned, iTypeUnsigned, sType, bType, jType, uType = Value
}
diff --git a/src/main/scala/main.scala b/src/main/scala/main.scala
@@ -109,6 +109,9 @@ class Perilus(
is(ResultSrc.aluResult) {
result := alu.io.aluResult
}
+ is(ResultSrc.immExt) {
+ result := extendUnit.io.immExt
+ }
}
alu.io.aluControl := controlUnit.io.aluControl
diff --git a/src/test/scala/perilus/main.scala b/src/test/scala/perilus/main.scala
@@ -289,11 +289,53 @@ class PerilusTests extends AnyFunSpec with ChiselSim {
}
}
describe("executes U-type RV32I instructions") {
+ def testUType(
+ imm: Int,
+ rd: Int,
+ op: Int
+ ) = {
+ val immMasked = (imm & 0xfffff000)
+ val rdShifted = (rd & 0x1f) << 7
+ val instr = immMasked | rdShifted | op
+
+ var registerFile = ArrayBuffer.fill(32)(0x00000000)
+ var memory = ArrayBuffer.fill(64)(0x00000000)
+ val test_pc = 48
+ memory(0) = 0x02000863 // beq x0, x0, 48
+ memory(test_pc / 4) = instr
+ val expected = if (op == 0x17) { immMasked + test_pc }
+ else { immMasked }
+
+ simulate(
+ new Perilus(
+ initRegs = initMemFile(registerFile),
+ initMem = initMemFile(memory),
+ withDebug = true
+ )
+ ) { perilus =>
+ {
+ val perilusDebug = perilus.io.debug.get
+ perilusDebug.memAddr.poke(test_pc)
+ perilusDebug.memData.expect(toULong(instr))
+ perilus.clock.step(6)
+ perilusDebug.reg.poke(rd)
+ perilusDebug.regData.expect(toULong(expected))
+ }
+ }
+ }
it("auipc") {
- cancel("Not yet implemented")
+ testUType(
+ imm = 0xf5540000,
+ rd = 29,
+ op = 0x17
+ )
}
it("lui") {
- cancel("Not yet implemented")
+ testUType(
+ imm = 0xc6fed000,
+ rd = 21,
+ op = 0x37
+ )
}
}
describe("executes S-type RV32I instructions") {