perilus

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

commit 9b22240b1911a643a2e893fde4be9f4bb85302c9
parent 5924ed9e5dfac5942dc3ffc05ca4b45acc3faa65
Author: Bradley Gannon <bradley@bradleygannon.com>
Date:   Tue, 30 Dec 2025 21:34:02 -0500

Factor out AluDecoder and InstructionDecoder and add tests for both

Diffstat:
Msrc/main/scala/controlUnit.scala | 41++++++++++++++++++++++++++++++++++++-----
Msrc/test/scala/perilus/controlUnit.scala | 52+++++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 87 insertions(+), 6 deletions(-)

diff --git a/src/main/scala/controlUnit.scala b/src/main/scala/controlUnit.scala @@ -25,6 +25,9 @@ class ControlUnit(withDebug: Boolean = false) extends Module { else None }) + val aluDecoder = Module(new AluDecoder()) + val instrDecoder = Module(new InstructionDecoder()) + val state = RegInit(ControlUnitState.fetch) io.debug.foreach(d => { @@ -35,10 +38,8 @@ class ControlUnit(withDebug: Boolean = false) extends Module { val branch, pcUpdate = WireDefault(false.B) io.adrSrc := DontCare - io.aluControl := DontCare io.aluSrcA := DontCare io.aluSrcB := DontCare - io.immSrc := DontCare io.irWrite := DontCare io.memWrite := DontCare io.regWrite := DontCare @@ -138,8 +139,29 @@ class ControlUnit(withDebug: Boolean = false) extends Module { io.pcWrite := (io.zero && branch) || pcUpdate - // ALU Decoder (Table 7.3, page 409) - switch(aluOp) { + aluDecoder.io.aluOp := aluOp + aluDecoder.io.funct3 := io.funct3 + aluDecoder.io.funct7_5 := io.funct7_5 + aluDecoder.io.op := io.op + io.aluControl := aluDecoder.io.aluControl + + instrDecoder.io.op := io.op + io.immSrc := instrDecoder.io.immSrc +} + +// ALU Decoder (Table 7.3, page 409) +class AluDecoder extends Module { + val io = IO(new Bundle { + val aluOp = Input(AluOp()) + val funct3 = Input(UInt(3.W)) + val funct7_5 = Input(Bool()) + val op = Input(Opcode()) + val aluControl = Output(AluControl()) + }) + + io.aluControl := DontCare + + switch(io.aluOp) { is(AluOp.memory) { io.aluControl := AluControl.add } @@ -164,8 +186,17 @@ class ControlUnit(withDebug: Boolean = false) extends Module { } } } +} + +// Instruction Decoder (Table 7.6, page 413) +class InstructionDecoder extends Module { + val io = IO(new Bundle { + val op = Input(Opcode()) + val immSrc = Output(ImmSrc()) + }) + + io.immSrc := DontCare - // Instruction Decoder (Table 7.6, page 413) switch(io.op) { is(Opcode.load) { io.immSrc := ImmSrc.iType diff --git a/src/test/scala/perilus/controlUnit.scala b/src/test/scala/perilus/controlUnit.scala @@ -2,9 +2,11 @@ import chisel3._ import chisel3.simulator.scalatest.ChiselSim import org.scalatest.funspec.AnyFunSpec +import com.rinthyAi.perilus.alu._ import com.rinthyAi.perilus.controlUnit._ +import com.rinthyAi.perilus.extendUnit._ -class ControlUnitFsmTests extends AnyFunSpec with ChiselSim { +class ControlUnitTests extends AnyFunSpec with ChiselSim { def checkFsmStates(dut: ControlUnit, states: List[ControlUnitState.Type]) = { val debug = dut.io.debug.get debug.state.expect(states.head) @@ -15,6 +17,36 @@ class ControlUnitFsmTests extends AnyFunSpec with ChiselSim { dut.clock.step(1) debug.state.expect(states.head) } + describe("AluDecoder") { + it("decodes correctly") { + simulate(new AluDecoder) { aluDecoder => + { + aluDecoder.io.funct3.poke(0.U) + aluDecoder.io.funct7_5.poke(false.B) + aluDecoder.io.op.poke(Opcode.rType) + + aluDecoder.io.aluOp.poke(AluOp.memory) + aluDecoder.io.aluControl.expect(AluControl.add) + + aluDecoder.io.aluOp.poke(AluOp.branch) + aluDecoder.io.aluControl.expect(AluControl.sub) + + aluDecoder.io.aluOp.poke(AluOp.arithmetic) + aluDecoder.io.op.poke(Opcode.immediate) + aluDecoder.io.aluControl.expect(AluControl.add) + aluDecoder.io.op.poke(Opcode.rType) + aluDecoder.io.funct7_5.poke(true.B) + aluDecoder.io.aluControl.expect(AluControl.sub) + aluDecoder.io.funct3.poke("b010".U) + aluDecoder.io.aluControl.expect(AluControl.slt) + aluDecoder.io.funct3.poke("b110".U) + aluDecoder.io.aluControl.expect(AluControl.or) + aluDecoder.io.funct3.poke("b111".U) + aluDecoder.io.aluControl.expect(AluControl.and) + } + } + } + } describe("ControlUnit") { it("controls the beq instruction") { simulate(new ControlUnit(withDebug = true)) { controlUnit => @@ -131,4 +163,22 @@ class ControlUnitFsmTests extends AnyFunSpec with ChiselSim { } } } + describe("InstructionDecoder") { + it("decodes correctly") { + simulate(new InstructionDecoder) { instrDecoder => + { + instrDecoder.io.op.poke(Opcode.load) + instrDecoder.io.immSrc.expect(ImmSrc.iType) + instrDecoder.io.op.poke(Opcode.store) + instrDecoder.io.immSrc.expect(ImmSrc.sType) + instrDecoder.io.op.poke(Opcode.branch) + instrDecoder.io.immSrc.expect(ImmSrc.bType) + instrDecoder.io.op.poke(Opcode.immediate) + instrDecoder.io.immSrc.expect(ImmSrc.iType) + instrDecoder.io.op.poke(Opcode.jal) + instrDecoder.io.immSrc.expect(ImmSrc.jType) + } + } + } + } }