perilus

git clone https://git.bradleygannon.com/perilus.git
Log | Files | Refs | Submodules | README

commit 5924ed9e5dfac5942dc3ffc05ca4b45acc3faa65
parent f736439ba08a3a78179e0c41c99482d4edc2b579
Author: Bradley Gannon <bradley@bradleygannon.com>
Date:   Tue, 30 Dec 2025 20:47:56 -0500

Add ControlUnitFsmTests

Diffstat:
Msrc/main/scala/controlUnit.scala | 10+++++++++-
Asrc/test/scala/perilus/controlUnit.scala | 134+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 143 insertions(+), 1 deletion(-)

diff --git a/src/main/scala/controlUnit.scala b/src/main/scala/controlUnit.scala @@ -6,7 +6,7 @@ import chisel3.util._ import com.rinthyAi.perilus.alu._ import com.rinthyAi.perilus.extendUnit._ -class ControlUnit extends Module { +class ControlUnit(withDebug: Boolean = false) extends Module { // Figure 7.28 (page 423) val io = IO(new Bundle { val op = Input(Opcode()) @@ -19,10 +19,18 @@ class ControlUnit extends Module { val resultSrc = Output(ResultSrc()) val immSrc = Output(ImmSrc()) val aluControl = Output(AluControl()) + val debug = if (withDebug) Some(Output(new Bundle { + val state = ControlUnitState() + })) + else None }) val state = RegInit(ControlUnitState.fetch) + io.debug.foreach(d => { + d.state := state + }) + val aluOp = WireDefault(AluOp.memory) val branch, pcUpdate = WireDefault(false.B) diff --git a/src/test/scala/perilus/controlUnit.scala b/src/test/scala/perilus/controlUnit.scala @@ -0,0 +1,134 @@ +import chisel3._ +import chisel3.simulator.scalatest.ChiselSim +import org.scalatest.funspec.AnyFunSpec + +import com.rinthyAi.perilus.controlUnit._ + +class ControlUnitFsmTests extends AnyFunSpec with ChiselSim { + def checkFsmStates(dut: ControlUnit, states: List[ControlUnitState.Type]) = { + val debug = dut.io.debug.get + debug.state.expect(states.head) + states.tail.foreach(state => { + dut.clock.step(1) + debug.state.expect(state) + }) + dut.clock.step(1) + debug.state.expect(states.head) + } + describe("ControlUnit") { + it("controls the beq instruction") { + simulate(new ControlUnit(withDebug = true)) { controlUnit => + { + controlUnit.io.op.poke(Opcode.branch) + controlUnit.io.funct3.poke(0.U) + controlUnit.io.funct7_5.poke(false.B) + controlUnit.io.zero.poke(false.B) + + val states = List( + ControlUnitState.fetch, + ControlUnitState.decode, + ControlUnitState.beq + ) + + checkFsmStates(controlUnit, states) + } + } + } + it("controls the jal instruction") { + simulate(new ControlUnit(withDebug = true)) { controlUnit => + { + controlUnit.io.op.poke(Opcode.jal) + controlUnit.io.funct3.poke(0.U) + controlUnit.io.funct7_5.poke(false.B) + controlUnit.io.zero.poke(false.B) + + val states = List( + ControlUnitState.fetch, + ControlUnitState.decode, + ControlUnitState.jal, + ControlUnitState.aluWb + ) + + checkFsmStates(controlUnit, states) + } + } + } + it("controls the lw instruction") { + simulate(new ControlUnit(withDebug = true)) { controlUnit => + { + controlUnit.io.op.poke(Opcode.load) + controlUnit.io.funct3.poke(2.U) + controlUnit.io.funct7_5.poke(false.B) + controlUnit.io.zero.poke(false.B) + + val states = List( + ControlUnitState.fetch, + ControlUnitState.decode, + ControlUnitState.memAdr, + ControlUnitState.memRead, + ControlUnitState.memWb + ) + + checkFsmStates(controlUnit, states) + } + } + } + it("controls the or instruction") { + simulate(new ControlUnit(withDebug = true)) { controlUnit => + { + controlUnit.io.op.poke(Opcode.rType) + controlUnit.io.funct3.poke(6.U) + controlUnit.io.funct7_5.poke(false.B) + controlUnit.io.zero.poke(false.B) + + val states = List( + ControlUnitState.fetch, + ControlUnitState.decode, + ControlUnitState.executeR, + ControlUnitState.aluWb + ) + + checkFsmStates(controlUnit, states) + } + } + } + it("controls the slti instruction") { + simulate(new ControlUnit(withDebug = true)) { controlUnit => + { + controlUnit.io.op.poke(Opcode.immediate) + controlUnit.io.funct3.poke(2.U) + controlUnit.io.funct7_5.poke(false.B) + controlUnit.io.zero.poke(false.B) + + val states = List( + ControlUnitState.fetch, + ControlUnitState.decode, + ControlUnitState.executeI, + ControlUnitState.aluWb + ) + + checkFsmStates(controlUnit, states) + } + } + } + it("controls the sw instruction") { + simulate(new ControlUnit(withDebug = true)) { controlUnit => + { + controlUnit.io.op.poke(Opcode.store) + controlUnit.io.funct3.poke(2.U) + controlUnit.io.funct7_5.poke(false.B) + controlUnit.io.zero.poke(false.B) + + val states = List( + ControlUnitState.fetch, + ControlUnitState.decode, + ControlUnitState.memAdr, + ControlUnitState.memWrite + ) + + checkFsmStates(controlUnit, states) + } + } + } + } +}