diff options
| author | Jack Koenig | 2021-03-19 13:59:52 -0700 |
|---|---|---|
| committer | GitHub | 2021-03-19 13:59:52 -0700 |
| commit | 49b823244732e8d3a4b0fe91d0f10625fea34eec (patch) | |
| tree | f47edb75d158b9654b5ea60c8aa95176caf7dd70 /src/main | |
| parent | b274b319d4a4014c154f06bfc174beba461d6fce (diff) | |
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).
Diffstat (limited to 'src/main')
| -rw-r--r-- | src/main/scala/firrtl/passes/Legalize.scala | 18 |
1 files changed, 16 insertions, 2 deletions
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 |
