diff options
| author | Adam Izraelevitz | 2016-04-27 13:30:14 -0700 |
|---|---|---|
| committer | jackkoenig | 2016-05-10 14:44:52 -0700 |
| commit | 4e784786622496a4447513f1b17dd2ed13fa3e01 (patch) | |
| tree | 4427ce0dbadb79a763073347e3df39a85f7378ed /src | |
| parent | 72e6e928d3596ce04cecfff22c17ce606730fc26 (diff) | |
Added pad widths to eliminate all implicit width extending
Diffstat (limited to 'src')
| -rw-r--r-- | src/main/scala/firrtl/Emitter.scala | 2 | ||||
| -rw-r--r-- | src/main/scala/firrtl/WIR.scala | 9 | ||||
| -rw-r--r-- | src/main/scala/firrtl/passes/PadWidths.scala | 80 |
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) +} |
