aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAdam Izraelevitz2017-03-06 16:57:53 -0800
committerGitHub2017-03-06 16:57:53 -0800
commit132d7baa991501e8c07cac7f6f4efc52905a89e7 (patch)
treef69580b93d93fa5c01606aad2ea1e7c305d2e11f /src
parent881ad9a445bb6c949896d875abbb58541382aa96 (diff)
Zero width (#402)
* Added Zero width wires. Semantics: - No change to width inference rules, e.g. a<0> + b<2> = c<3> - Replace zero width wires with UInt<1>(0) or SInt<1>(0) - Performs constant prop. - Redo width/type inference * Remove errant println * Moved ZeroWidth after ConvertFixedToSInt * Added more tests, bugfix match on connect Also replaced constprop with infertypes for correctness * Updated to new emitter and test infrastructure
Diffstat (limited to 'src')
-rw-r--r--src/main/scala/firrtl/LoweringCompilers.scala3
-rw-r--r--src/main/scala/firrtl/passes/ZeroWidth.scala65
-rw-r--r--src/test/scala/firrtlTests/ZeroWidthTests.scala128
3 files changed, 195 insertions, 1 deletions
diff --git a/src/main/scala/firrtl/LoweringCompilers.scala b/src/main/scala/firrtl/LoweringCompilers.scala
index ab9f6ea4..c2238c2d 100644
--- a/src/main/scala/firrtl/LoweringCompilers.scala
+++ b/src/main/scala/firrtl/LoweringCompilers.scala
@@ -68,7 +68,8 @@ class HighFirrtlToMiddleFirrtl extends CoreTransform {
passes.ResolveGenders,
passes.InferWidths,
passes.CheckWidths,
- passes.ConvertFixedToSInt)
+ passes.ConvertFixedToSInt,
+ passes.ZeroWidth)
}
/** Expands all aggregate types into many ground-typed components. Must
diff --git a/src/main/scala/firrtl/passes/ZeroWidth.scala b/src/main/scala/firrtl/passes/ZeroWidth.scala
new file mode 100644
index 00000000..8638ea68
--- /dev/null
+++ b/src/main/scala/firrtl/passes/ZeroWidth.scala
@@ -0,0 +1,65 @@
+// See LICENSE for license details.
+
+package firrtl.passes
+
+import scala.collection.mutable
+import firrtl.PrimOps._
+import firrtl.ir._
+import firrtl._
+import firrtl.Mappers._
+import firrtl.Utils.throwInternalError
+
+
+object ZeroWidth extends Pass {
+ def name = this.getClass.getName
+ private val ZERO = BigInt(0)
+ private def removeZero(t: Type): Option[Type] = t match {
+ case GroundType(IntWidth(ZERO)) => None
+ case BundleType(fields) =>
+ fields map (f => (f, removeZero(f.tpe))) collect {
+ case (Field(name, flip, _), Some(t)) => Field(name, flip, t)
+ } match {
+ case Nil => None
+ case seq => Some(BundleType(seq))
+ }
+ case VectorType(t, size) => removeZero(t) map (VectorType(_, size))
+ case x => Some(x)
+ }
+ private def onExp(e: Expression): Expression = removeZero(e.tpe) match {
+ case None => e.tpe match {
+ case UIntType(x) => UIntLiteral(ZERO, IntWidth(BigInt(1)))
+ case SIntType(x) => SIntLiteral(ZERO, IntWidth(BigInt(1)))
+ case _ => throwInternalError
+ }
+ case Some(t) =>
+ def replaceType(x: Type): Type = t
+ (e map replaceType) map onExp
+ }
+ private def onStmt(s: Statement): Statement = s match {
+ case sx: IsDeclaration =>
+ var removed = false
+ def applyRemoveZero(t: Type): Type = removeZero(t) match {
+ case None => removed = true; t
+ case Some(tx) => tx
+ }
+ val sxx = (sx map onExp) map applyRemoveZero
+ if(removed) EmptyStmt else sxx
+ case Connect(info, loc, exp) => removeZero(loc.tpe) match {
+ case None => EmptyStmt
+ case Some(t) => Connect(info, loc, onExp(exp))
+ }
+ case sx => sx map onStmt
+ }
+ private def onModule(m: DefModule): DefModule = {
+ val ports = m.ports map (p => (p, removeZero(p.tpe))) collect {
+ case (Port(info, name, dir, _), Some(t)) => Port(info, name, dir, t)
+ }
+ m match {
+ case ext: ExtModule => ext.copy(ports = ports)
+ case in: Module => in.copy(ports = ports, body = onStmt(in.body))
+ }
+ }
+ def run(c: Circuit): Circuit = {
+ InferTypes.run(c.copy(modules = c.modules map onModule))
+ }
+}
diff --git a/src/test/scala/firrtlTests/ZeroWidthTests.scala b/src/test/scala/firrtlTests/ZeroWidthTests.scala
new file mode 100644
index 00000000..53fae73f
--- /dev/null
+++ b/src/test/scala/firrtlTests/ZeroWidthTests.scala
@@ -0,0 +1,128 @@
+// See LICENSE for license details.
+
+package firrtlTests
+
+import org.scalatest.Matchers
+import java.io.{StringWriter,Writer}
+import firrtl.ir.Circuit
+import firrtl._
+import firrtl.Parser.IgnoreInfo
+import firrtl.Parser
+import firrtl.passes._
+
+class ZeroWidthTests extends FirrtlFlatSpec {
+ val passes = Seq(
+ ToWorkingIR,
+ ResolveKinds,
+ InferTypes,
+ ResolveGenders,
+ InferWidths,
+ ZeroWidth)
+ private def exec (input: String) = {
+ passes.foldLeft(parse(input)) {
+ (c: Circuit, p: Pass) => p.run(c)
+ }.serialize
+ }
+ // =============================
+ "Zero width port" should " be deleted" in {
+ val input =
+ """circuit Top :
+ | module Top :
+ | input y : UInt<0>
+ | output x : UInt<1>
+ | x <= y""".stripMargin
+ val check =
+ """circuit Top :
+ | module Top :
+ | output x : UInt<1>
+ | x <= UInt<1>(0)""".stripMargin
+ (parse(exec(input))) should be (parse(check))
+ }
+ "Add of <0> and <2> " should " put in zero" in {
+ val input =
+ """circuit Top :
+ | module Top :
+ | input y : UInt<0>
+ | output x : UInt
+ | x <= add(y, UInt<2>(2))""".stripMargin
+ val check =
+ """circuit Top :
+ | module Top :
+ | output x : UInt<3>
+ | x <= add(UInt<1>(0), UInt<2>(2))""".stripMargin
+ (parse(exec(input)).serialize) should be (parse(check).serialize)
+ }
+ "Mux on <0>" should "put in zero" in {
+ val input =
+ """circuit Top :
+ | module Top :
+ | input y : UInt<0>
+ | output x : UInt
+ | x <= mux(y, UInt<2>(2), UInt<2>(1))""".stripMargin
+ val check =
+ """circuit Top :
+ | module Top :
+ | output x : UInt<2>
+ | x <= mux(UInt<1>(0), UInt<2>(2), UInt<2>(1))""".stripMargin
+ (parse(exec(input)).serialize) should be (parse(check).serialize)
+ }
+ "Bundle with field of <0>" should "get deleted" in {
+ val input =
+ """circuit Top :
+ | module Top :
+ | input y : { a: UInt<0> }
+ | output x : { a: UInt<0>, b: UInt<1>}
+ | x.a <= y.a""".stripMargin
+ val check =
+ """circuit Top :
+ | module Top :
+ | output x : { b: UInt<1> }
+ | skip""".stripMargin
+ (parse(exec(input)).serialize) should be (parse(check).serialize)
+ }
+ "Vector with type of <0>" should "get deleted" in {
+ val input =
+ """circuit Top :
+ | module Top :
+ | input y : UInt<0>[10]
+ | output x : UInt<0>[10]
+ | x <= y""".stripMargin
+ val check =
+ """circuit Top :
+ | module Top :
+ | skip""".stripMargin
+ (parse(exec(input)).serialize) should be (parse(check).serialize)
+ }
+ "Node with <0>" should "be given zero" in {
+ val input =
+ """circuit Top :
+ | module Top :
+ | input y: UInt<0>
+ | node x = y""".stripMargin
+ val check =
+ """circuit Top :
+ | module Top :
+ | node x = UInt(0)""".stripMargin
+ (parse(exec(input)).serialize) should be (parse(check).serialize)
+ }
+}
+
+class ZeroWidthVerilog extends FirrtlFlatSpec {
+ "Circuit" should "accept zero width wires" in {
+ val compiler = new VerilogCompiler
+ val input =
+ """circuit Top :
+ | module Top :
+ | input y: UInt<0>
+ | output x: UInt<3>
+ | x <= y""".stripMargin
+ val check =
+ """module Top(
+ | output [2:0] x
+ |);
+ | assign x = 3'h0;
+ |endmodule
+ |""".stripMargin.split("\n") map normalized
+ executeTest(input, check, compiler)
+ }
+}