Add MakeWireBundle
This allows Bundle (wire) instances to be created and (partially)
connected in one call, and provides some readability improvements:
- avoid repeating the name of the instance
- avoid naming the instance if we're just going to return it
This change applies the trick to common/Library and rvv only.
Change-Id: I56a7f220f6de63920d55227e23e5f7955b2d4b33
diff --git a/hdl/chisel/src/common/Library.scala b/hdl/chisel/src/common/Library.scala
index 4824074..5f1123f 100644
--- a/hdl/chisel/src/common/Library.scala
+++ b/hdl/chisel/src/common/Library.scala
@@ -27,12 +27,36 @@
}
}
+// An easy way to build a Wire(T) and (partially) connect some of its
+// contents.
+// This is essentially somewhere between WireDefault (which does not like
+// bundle members) and bundle literals (which only likes literals)
+// See MakeValid for usage example.
+// TODO: add more examples for advanced usage:
+// - _.member1.member2 on LHS
+// - _.something on RHS (only, or both)
+// - _ (no member) on LHS
+// TODO: add tests
+object MakeWireBundle {
+ def apply[T <: Bundle](gen: T, exp: T => (Data, Data)*): T = {
+ val ret = Wire(gen)
+ exp.foreach { e =>
+ val (x, y) = e(ret)
+ x := y
+ }
+ ret
+ }
+}
+
object MakeValid {
def apply[T <: Data](valid: Bool, bits: T): ValidIO[T] = {
- val result = Wire(Valid(chiselTypeOf(bits)))
- result.valid := valid
- result.bits := bits
- result
+ // Explicitly stating the type here allows the function types to be
+ // inferred.
+ MakeWireBundle[ValidIO[T]](
+ Valid(chiselTypeOf(bits)),
+ _.valid -> valid,
+ _.bits -> bits,
+ )
}
def apply[T <: Data](bits: T): ValidIO[T] = {
@@ -41,23 +65,21 @@
}
object MakeInvalid {
- def apply[T <: Data](gen: T): ValidIO[T] = {
- val result = Wire(Valid(gen))
- result.valid := false.B
- result.bits := 0.U.asTypeOf(gen)
- result
- }
+ def apply[T <: Data](gen: T): ValidIO[T] = MakeWireBundle[ValidIO[T]](
+ Valid(gen),
+ _.valid -> false.B,
+ _.bits -> 0.U.asTypeOf(gen),
+ )
}
// Gate the bits of an interface based on it's validity bit. This prevents
// invalid data from propagating down stream, thus reducing dynamic power
object ForceZero {
- def apply[T <: Data](input: ValidIO[T]): ValidIO[T] = {
- val result = Wire(chiselTypeOf(input))
- result.valid := input.valid
- result.bits := Mux(input.valid, input.bits, 0.U.asTypeOf(input).bits)
- result
- }
+ def apply[T <: Data](input: ValidIO[T]): ValidIO[T] = MakeWireBundle[ValidIO[T]](
+ chiselTypeOf(input),
+ _.valid -> input.valid,
+ _.bits -> Mux(input.valid, input.bits, 0.U.asTypeOf(input).bits),
+ )
}
object Clz {
diff --git a/hdl/chisel/src/kelvin/rvv/RvvDecode.scala b/hdl/chisel/src/kelvin/rvv/RvvDecode.scala
index d42c96b..f557aff 100644
--- a/hdl/chisel/src/kelvin/rvv/RvvDecode.scala
+++ b/hdl/chisel/src/kelvin/rvv/RvvDecode.scala
@@ -16,7 +16,7 @@
import chisel3._
import chisel3.util._
-import common.{ForceZero, MakeInvalid, MakeValid}
+import common.{ForceZero, MakeInvalid, MakeValid, MakeWireBundle}
object RvvCompressedOpcode extends ChiselEnum {
@@ -41,10 +41,14 @@
"b0100111".U -> MakeValid(RvvCompressedOpcode.RVVSTORE),
"b1010111".U -> MakeValid(RvvCompressedOpcode.RVVALU),
))
- val compressed = Wire(new RvvCompressedInstruction)
- compressed.opcode := new_opcode.bits
- compressed.bits := bits
- MakeValid(new_opcode.valid, compressed)
+
+ // Fancy way to MakeValid.
+ MakeWireBundle[ValidIO[RvvCompressedInstruction]](
+ Valid(new RvvCompressedInstruction),
+ _.valid -> new_opcode.valid,
+ _.bits.opcode -> new_opcode.bits,
+ _.bits.bits -> bits,
+ )
}
}
@@ -104,10 +108,11 @@
(f6vm === BitPat("b101111_?")) -> MakeValid(RvvAluOp.VNCLIP),
))
- val d = Wire(new RvvS1DecodedInstruction())
- d.op := op.bits
-
- ForceZero(MakeValid(op.valid, d))
+ ForceZero(MakeWireBundle[ValidIO[RvvS1DecodedInstruction]](
+ Valid(new RvvS1DecodedInstruction),
+ _.valid -> op.valid,
+ _.bits.op -> op.bits,
+ ))
}
private def s1decode_opivx(f6vm: UInt, vs2: UInt, rs1: UInt, vd: UInt): Valid[RvvS1DecodedInstruction] = {
@@ -161,10 +166,11 @@
(f6vm === BitPat("b101111_?")) -> MakeValid(RvvAluOp.VNCLIP),
))
- val d = Wire(new RvvS1DecodedInstruction())
- d.op := op.bits
-
- ForceZero(MakeValid(op.valid, d))
+ ForceZero(MakeWireBundle[ValidIO[RvvS1DecodedInstruction]](
+ Valid(new RvvS1DecodedInstruction),
+ _.valid -> op.valid,
+ _.bits.op -> op.bits,
+ ))
}
private def s1decode_opivi(f6vm: UInt, vs2: UInt, imm5: UInt, vd: UInt): Valid[RvvS1DecodedInstruction] = {
@@ -222,10 +228,11 @@
(f6vm === BitPat("b101111_?")) -> MakeValid(RvvAluOp.VNCLIP),
))
- val d = Wire(new RvvS1DecodedInstruction())
- d.op := op.bits
-
- ForceZero(MakeValid(op.valid, d))
+ ForceZero(MakeWireBundle[ValidIO[RvvS1DecodedInstruction]](
+ Valid(new RvvS1DecodedInstruction),
+ _.valid -> op.valid,
+ _.bits.op -> op.bits,
+ ))
}
protected def s1decode_opv(bits: UInt): Valid[RvvS1DecodedInstruction] = {