From 49b823244732e8d3a4b0fe91d0f10625fea34eec Mon Sep 17 00:00:00 2001 From: Jack Koenig Date: Fri, 19 Mar 2021 13:59:52 -0700 Subject: Legalize neg: -x becomes 0 - x (#2128) This fixes an error with negating a negative SInt literal and a [debatable] lint warning in Verilator when negating any value. This behavior matches that of Chisel (which directly emits the 0 - x already).--- src/main/scala/firrtl/passes/Legalize.scala | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'src/main') diff --git a/src/main/scala/firrtl/passes/Legalize.scala b/src/main/scala/firrtl/passes/Legalize.scala index ef0e1706..e1a39fbe 100644 --- a/src/main/scala/firrtl/passes/Legalize.scala +++ b/src/main/scala/firrtl/passes/Legalize.scala @@ -3,11 +3,11 @@ package firrtl.passes import firrtl.PrimOps._ -import firrtl.Utils.{error, zero, BoolType} +import firrtl.Utils.{error, getGroundZero, zero, BoolType} import firrtl.ir._ import firrtl.options.Dependency import firrtl.transforms.ConstantPropagation -import firrtl.{bitWidth, Transform} +import firrtl.{bitWidth, getWidth, Transform} import firrtl.Mappers._ // Replace shr by amount >= arg width with 0 for UInts and MSB for SInts @@ -56,6 +56,19 @@ object Legalize extends Pass { SIntLiteral(value, IntWidth(expr.consts.head)) case _ => expr } + // Convert `-x` to `0 - x` + private def legalizeNeg(expr: DoPrim): Expression = { + val arg = expr.args.head + arg.tpe match { + case tpe: SIntType => + val zero = getGroundZero(tpe) + DoPrim(Sub, Seq(zero, arg), Nil, expr.tpe) + case tpe: UIntType => + val zero = getGroundZero(tpe) + val sub = DoPrim(Sub, Seq(zero, arg), Nil, UIntType(tpe.width + IntWidth(1))) + DoPrim(AsSInt, Seq(sub), Nil, expr.tpe) + } + } private def legalizeConnect(c: Connect): Statement = { val t = c.loc.tpe val w = bitWidth(t) @@ -78,6 +91,7 @@ object Legalize extends Pass { case Shr => legalizeShiftRight(prim) case Pad => legalizePad(prim) case Bits | Head | Tail => legalizeBitExtract(prim) + case Neg => legalizeNeg(prim) case _ => prim } case e => e // respect pre-order traversal -- cgit v1.2.3