perilus

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

commit b2e69ab264d590e195cbcb2044e37bbc03122987
parent 4083d01412cd28a59e85c0544abd420eafb3a880
Author: Bradley Gannon <bradley@bradleygannon.com>
Date:   Sat, 29 Nov 2025 15:21:05 -0500

Implement ExtendUnit

Diffstat:
Mshell.nix | 1+
Msrc/main/scala/extendUnit.scala | 24+++++++++++++++++++++---
Dsrc/test/scala/.gitkeep | 0
Asrc/test/scala/perilus/extendUnit.scala | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 83 insertions(+), 3 deletions(-)

diff --git a/shell.nix b/shell.nix @@ -9,5 +9,6 @@ pkgs.mkShellNoCC { metals sbt scalafmt + verilator ]; } diff --git a/src/main/scala/extendUnit.scala b/src/main/scala/extendUnit.scala @@ -1,15 +1,33 @@ package com.rinthyAi.perilus.extendUnit import chisel3._ +import chisel3.util._ class ExtendUnit extends Module { val io = IO(new Bundle { - val input = Input(UInt(21.W)) + val input = Input(UInt(25.W)) val immSrc = Input(UInt(2.W)) val immExt = Output(UInt(32.W)) }) - // TODO implement - io.immExt := 0.U + // Table 7.1 (page 406) + when(io.immSrc === "b00".U) { + // I-type instruction + io.immExt := Cat(Fill(20, io.input(24)), io.input(24, 13)) + }.elsewhen(io.immSrc === "b01".U) { + // S-type instruction + io.immExt := Cat(Fill(20, io.input(24)), io.input(24, 18), io.input(4, 0)) + }.elsewhen(io.immSrc === "b10".U) { + // B-type instruction + io.immExt := Cat( + Fill(20, io.input(24)), + io.input(0), + io.input(23, 18), + io.input(4, 1), + 0.U(1.W) + ) + }.otherwise { + io.immExt := 0.U + } } diff --git a/src/test/scala/.gitkeep b/src/test/scala/.gitkeep diff --git a/src/test/scala/perilus/extendUnit.scala b/src/test/scala/perilus/extendUnit.scala @@ -0,0 +1,61 @@ +import chisel3._ +import chisel3.simulator.scalatest.ChiselSim +import org.scalatest.funspec.AnyFunSpec +import com.rinthyAi.perilus.extendUnit._ + +class ExtendUnitTests extends AnyFunSpec with ChiselSim { + describe("ExtendUnit") { + it("correctly extends I-type immediates") { + simulate(new ExtendUnit) { extendUnit => + { + extendUnit.io.immSrc.poke("b00".U) + + extendUnit.io.input.poke("hdc4691".U) // immediate value is 0xe9b + extendUnit.io.immExt.expect("h6e2".U) + + extendUnit.io.input.poke("h1ff8946".U) // immediate value is 0xffc + extendUnit.io.immExt.expect("hfffffffc".U) + } + } + } + it("correctly extends S-type immediates") { + simulate(new ExtendUnit) { extendUnit => + { + extendUnit.io.immSrc.poke("b01".U) + + extendUnit.io.input.poke("h65b22a".U) // immediate value is 0x32a + extendUnit.io.immExt.expect("h32a".U) + + extendUnit.io.input.poke("h1de532a".U) // immediate value is 0xeea + extendUnit.io.immExt.expect("hfffffeea".U) + } + } + } + it("correctly extends B-type immediates") { + simulate(new ExtendUnit) { extendUnit => + { + extendUnit.io.immSrc.poke("b10".U) + + extendUnit.io.input.poke("hcbee9".U) // immediate value is 0x868 + extendUnit.io.immExt.expect("h868".U) + + extendUnit.io.input.poke("h144ae93".U) // immediate value is 0x1a32 + extendUnit.io.immExt.expect("hfffffa32".U) + } + } + } + it("outputs zero when immSrc is invalid") { + simulate(new ExtendUnit) { extendUnit => + { + extendUnit.io.immSrc.poke("b11".U) + + extendUnit.io.input.poke("hb2a945".U) + extendUnit.io.immExt.expect(0.U) + + extendUnit.io.input.poke("h1f800d2".U) + extendUnit.io.immExt.expect(0.U) + } + } + } + } +}