commit b2e69ab264d590e195cbcb2044e37bbc03122987
parent 4083d01412cd28a59e85c0544abd420eafb3a880
Author: Bradley Gannon <bradley@bradleygannon.com>
Date: Sat, 29 Nov 2025 15:21:05 -0500
Implement ExtendUnit
Diffstat:
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)
+ }
+ }
+ }
+ }
+}