summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Lin2019-01-21 21:31:06 -0800
committerGitHub2019-01-21 21:31:06 -0800
commit99bb15f13491637f1c7ce58edb5ba494efc810dc (patch)
treeb257572551776759c29876fff68aa9f079498eb1
parent9e992816e570284193e121cd9c24503fd8cb4427 (diff)
Support DontCare in Mux and cloneSupertype (#995)
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Data.scala19
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Mux.scala16
-rw-r--r--src/test/scala/chiselTests/MuxSpec.scala25
-rw-r--r--src/test/scala/chiselTests/Vec.scala9
4 files changed, 60 insertions, 9 deletions
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Data.scala b/chiselFrontend/src/main/scala/chisel3/core/Data.scala
index e56412e6..cf6dabdd 100644
--- a/chiselFrontend/src/main/scala/chisel3/core/Data.scala
+++ b/chiselFrontend/src/main/scala/chisel3/core/Data.scala
@@ -113,8 +113,11 @@ private[core] object cloneSupertype {
compileOptions: CompileOptions): T = {
require(!elts.isEmpty, s"can't create $createdType with no inputs")
- if (elts.head.isInstanceOf[Bits]) {
- val model: T = elts reduce { (elt1: T, elt2: T) => ((elt1, elt2) match {
+ val filteredElts = elts.filter(_ != DontCare)
+ require(!filteredElts.isEmpty, s"can't create $createdType with only DontCare inputs")
+
+ if (filteredElts.head.isInstanceOf[Bits]) {
+ val model: T = filteredElts reduce { (elt1: T, elt2: T) => ((elt1, elt2) match {
case (elt1: Bool, elt2: Bool) => elt1
case (elt1: Bool, elt2: UInt) => elt2 // TODO: what happens with zero width UInts?
case (elt1: UInt, elt2: Bool) => elt1 // TODO: what happens with zero width UInts?
@@ -140,13 +143,13 @@ private[core] object cloneSupertype {
model.cloneTypeFull
}
else {
- for (elt <- elts.tail) {
- require(elt.getClass == elts.head.getClass,
- s"can't create $createdType with heterogeneous types ${elts.head.getClass} and ${elt.getClass}")
- require(elt typeEquivalent elts.head,
- s"can't create $createdType with non-equivalent types ${elts.head} and ${elt}")
+ for (elt <- filteredElts.tail) {
+ require(elt.getClass == filteredElts.head.getClass,
+ s"can't create $createdType with heterogeneous types ${filteredElts.head.getClass} and ${elt.getClass}")
+ require(elt typeEquivalent filteredElts.head,
+ s"can't create $createdType with non-equivalent types ${filteredElts.head} and ${elt}")
}
- elts.head.cloneTypeFull
+ filteredElts.head.cloneTypeFull
}
}
}
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Mux.scala b/chiselFrontend/src/main/scala/chisel3/core/Mux.scala
index 56c145b5..7dd1b98b 100644
--- a/chiselFrontend/src/main/scala/chisel3/core/Mux.scala
+++ b/chiselFrontend/src/main/scala/chisel3/core/Mux.scala
@@ -32,6 +32,20 @@ object Mux extends SourceInfoDoc {
requireIsHardware(con, "mux true value")
requireIsHardware(alt, "mux false value")
val d = cloneSupertype(Seq(con, alt), "Mux")
- pushOp(DefPrim(sourceInfo, d, MultiplexOp, cond.ref, con.ref, alt.ref))
+ val conRef = con match { // this matches chisel semantics (DontCare as object) to firrtl semantics (invalidate)
+ case DontCare =>
+ val dcWire = Wire(d)
+ dcWire := DontCare
+ dcWire.ref
+ case _ => con.ref
+ }
+ val altRef = alt match {
+ case DontCare =>
+ val dcWire = Wire(d)
+ dcWire := DontCare
+ dcWire.ref
+ case _ => alt.ref
+ }
+ pushOp(DefPrim(sourceInfo, d, MultiplexOp, cond.ref, conRef, altRef))
}
}
diff --git a/src/test/scala/chiselTests/MuxSpec.scala b/src/test/scala/chiselTests/MuxSpec.scala
new file mode 100644
index 00000000..d06c00af
--- /dev/null
+++ b/src/test/scala/chiselTests/MuxSpec.scala
@@ -0,0 +1,25 @@
+package chiselTests
+
+import chisel3._
+import chisel3.testers.BasicTester
+
+class MuxTester extends BasicTester {
+ assert(Mux(0.B, 1.U, 2.U) === 2.U)
+ assert(Mux(1.B, 1.U, 2.U) === 1.U)
+ val dontCareMux1 = Wire(UInt())
+ dontCareMux1 := Mux(0.B, DontCare, 4.U) // note: Mux output of type Element
+ assert(dontCareMux1 === 4.U)
+
+ val dontCareMux2 = Wire(UInt())
+ dontCareMux2 := Mux(1.B, 3.U, DontCare) // note: Mux output of type Element
+ assert(dontCareMux2 === 3.U)
+
+ Mux(0.B, 3.U, DontCare) // just to make sure nothing crashes, any result is valid
+ stop()
+}
+
+class MuxSpec extends ChiselFlatSpec {
+ "Mux" should "pass basic checks" in {
+ assertTesterPasses { new MuxTester }
+ }
+} \ No newline at end of file
diff --git a/src/test/scala/chiselTests/Vec.scala b/src/test/scala/chiselTests/Vec.scala
index 395624f7..d8e3be10 100644
--- a/src/test/scala/chiselTests/Vec.scala
+++ b/src/test/scala/chiselTests/Vec.scala
@@ -265,4 +265,13 @@ class VecSpec extends ChiselPropSpec {
})
}
}
+
+ property("It should be possible to initialize a Vec with DontCare") {
+ elaborate(new Module {
+ val io = IO(new Bundle {
+ val out = Output(Vec(4, UInt(8.W)))
+ })
+ io.out := VecInit(Seq(4.U, 5.U, DontCare, 2.U))
+ })
+ }
}