aboutsummaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
authorJack Koenig2021-03-19 13:59:52 -0700
committerGitHub2021-03-19 13:59:52 -0700
commit49b823244732e8d3a4b0fe91d0f10625fea34eec (patch)
treef47edb75d158b9654b5ea60c8aa95176caf7dd70 /src/main
parentb274b319d4a4014c154f06bfc174beba461d6fce (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.scala18
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