aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAdam Izraelevitz2016-04-27 13:30:14 -0700
committerjackkoenig2016-05-10 14:44:52 -0700
commit4e784786622496a4447513f1b17dd2ed13fa3e01 (patch)
tree4427ce0dbadb79a763073347e3df39a85f7378ed /src
parent72e6e928d3596ce04cecfff22c17ce606730fc26 (diff)
Added pad widths to eliminate all implicit width extending
Diffstat (limited to 'src')
-rw-r--r--src/main/scala/firrtl/Emitter.scala2
-rw-r--r--src/main/scala/firrtl/WIR.scala9
-rw-r--r--src/main/scala/firrtl/passes/PadWidths.scala80
3 files changed, 90 insertions, 1 deletions
diff --git a/src/main/scala/firrtl/Emitter.scala b/src/main/scala/firrtl/Emitter.scala
index ddd6ca98..5414053a 100644
--- a/src/main/scala/firrtl/Emitter.scala
+++ b/src/main/scala/firrtl/Emitter.scala
@@ -202,6 +202,7 @@ class VerilogEmitter extends Emitter {
case AS_UINT_OP => Seq("$unsigned(",a0(),")")
case AS_SINT_OP => Seq("$signed(",a0(),")")
case AS_CLOCK_OP => Seq("$unsigned(",a0(),")")
+ case DSHLW_OP => Seq(cast(a0())," << ", a1())
case DYN_SHIFT_LEFT_OP => Seq(cast(a0())," << ", a1())
case DYN_SHIFT_RIGHT_OP => {
(doprim.tpe) match {
@@ -209,6 +210,7 @@ class VerilogEmitter extends Emitter {
case (t) => Seq(cast(a0())," >> ",a1())
}
}
+ case SHLW_OP => Seq(cast(a0())," << ", c0())
case SHIFT_LEFT_OP => Seq(cast(a0())," << ",c0())
case SHIFT_RIGHT_OP => {
if (c0 >= long_BANG(tpe(a0)))
diff --git a/src/main/scala/firrtl/WIR.scala b/src/main/scala/firrtl/WIR.scala
index cdac2ca5..bb555112 100644
--- a/src/main/scala/firrtl/WIR.scala
+++ b/src/main/scala/firrtl/WIR.scala
@@ -59,8 +59,15 @@ case class WInvalid() extends Expression { def tpe = UnknownType() }
case object EmptyExpression extends Expression { def tpe = UnknownType() }
case class WDefInstance(info:Info,name:String,module:String,tpe:Type) extends Stmt with IsDeclaration
-case object ADDW_OP extends PrimOp
+// Resultant width is the same as the maximum input width
+case object ADDW_OP extends PrimOp
+// Resultant width is the same as the maximum input width
case object SUBW_OP extends PrimOp
+// Resultant width is the same as input argument width
+case object DSHLW_OP extends PrimOp
+// Resultant width is the same as input argument width
+case object SHLW_OP extends PrimOp
+
object WrappedExpression {
def apply (e:Expression) = new WrappedExpression(e)
diff --git a/src/main/scala/firrtl/passes/PadWidths.scala b/src/main/scala/firrtl/passes/PadWidths.scala
new file mode 100644
index 00000000..049da53b
--- /dev/null
+++ b/src/main/scala/firrtl/passes/PadWidths.scala
@@ -0,0 +1,80 @@
+package firrtl
+package passes
+
+import firrtl.Mappers.{ExpMap, StmtMap}
+import firrtl.Utils.{tpe, long_BANG}
+
+// Makes all implicit width extensions and truncations explicit
+object PadWidths extends Pass {
+ def name = "Pad Widths"
+ private def width(t: Type): Int = long_BANG(t).toInt
+ private def width(e: Expression): Int = width(tpe(e))
+ // Returns an expression with the correct integer width
+ private def fixup(i: Int)(e: Expression) = {
+ def tx = tpe(e) match {
+ case t: UIntType => UIntType(IntWidth(i))
+ case t: SIntType => SIntType(IntWidth(i))
+ // default case should never be reached
+ }
+ if (i > width(e))
+ DoPrim(PAD_OP, Seq(e), Seq(i), tx)
+ else if (i < width(e))
+ DoPrim(BITS_SELECT_OP, Seq(e), Seq(i - 1, 0), tx)
+ else e
+ }
+ // Recursive, updates expression so children exp's have correct widths
+ private def onExp(e: Expression): Expression = {
+ val sensitiveOps = Seq(
+ LESS_OP, LESS_EQ_OP, GREATER_OP, GREATER_EQ_OP, EQUAL_OP,
+ NEQUAL_OP, NOT_OP, AND_OP, OR_OP, XOR_OP, ADD_OP, SUB_OP,
+ MUL_OP, DIV_OP, REM_OP, SHIFT_RIGHT_OP)
+ val x = e map onExp
+ x match {
+ case Mux(cond, tval, fval, tpe) => {
+ val tvalx = fixup(width(tpe))(tval)
+ val fvalx = fixup(width(tpe))(fval)
+ Mux(cond, tvalx, fvalx, tpe)
+ }
+ case DoPrim(op, args, consts, tpe) => op match {
+ case _ if sensitiveOps.contains(op) => {
+ val i = args.map(a => width(a)).foldLeft(0) {(a, b) => math.max(a, b)}
+ x map fixup(i)
+ }
+ case DYN_SHIFT_LEFT_OP => {
+ // special case as args aren't all same width
+ val ax = fixup(width(tpe))(args(0))
+ DoPrim(DSHLW_OP, Seq(ax, args(1)), consts, tpe)
+ }
+ case SHIFT_LEFT_OP => {
+ // special case as arg should be same width as result
+ val ax = fixup(width(tpe))(args(0))
+ DoPrim(SHLW_OP, Seq(ax), consts, tpe)
+ }
+ case _ => x
+ }
+ case ValidIf(cond, value, tpe) => ValidIf(cond, fixup(width(tpe))(value), tpe)
+ case x => x
+ }
+ }
+ // Recursive. Fixes assignments and register initialization widths
+ private def onStmt(s: Stmt): Stmt = {
+ s map onExp match {
+ case s: Connect => {
+ val ex = fixup(width(s.loc))(s.exp)
+ Connect(s.info, s.loc, ex)
+ }
+ case s: DefRegister => {
+ val ex = fixup(width(s.tpe))(s.init)
+ DefRegister(s.info, s.name, s.tpe, s.clock, s.reset, ex)
+ }
+ case s => s map onStmt
+ }
+ }
+ private def onModule(m: Module): Module = {
+ m match {
+ case m:InModule => InModule(m.info, m.name, m.ports, onStmt(m.body))
+ case m:ExModule => m
+ }
+ }
+ def run(c: Circuit): Circuit = Circuit(c.info, c.modules.map(onModule _), c.main)
+}