diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/main/antlr4/FIRRTL.g4 | 2 | ||||
| -rw-r--r-- | src/main/scala/firrtl/Emitter.scala | 7 | ||||
| -rw-r--r-- | src/main/scala/firrtl/Utils.scala | 3 | ||||
| -rw-r--r-- | src/main/scala/firrtl/Visitor.scala | 38 | ||||
| -rw-r--r-- | src/main/scala/firrtl/ir/IR.scala | 6 | ||||
| -rw-r--r-- | src/main/scala/firrtl/passes/CheckWidths.scala | 2 | ||||
| -rw-r--r-- | src/test/scala/firrtlTests/UnitTests.scala | 52 |
7 files changed, 80 insertions, 30 deletions
diff --git a/src/main/antlr4/FIRRTL.g4 b/src/main/antlr4/FIRRTL.g4 index cdec7260..e26aca2e 100644 --- a/src/main/antlr4/FIRRTL.g4 +++ b/src/main/antlr4/FIRRTL.g4 @@ -297,7 +297,7 @@ PosInt ; HexLit - : '"' 'h' ( HexDigit )+ '"' + : '"' 'h' ( '+' | '-' )? ( HexDigit )+ '"' ; DoubleLit diff --git a/src/main/scala/firrtl/Emitter.scala b/src/main/scala/firrtl/Emitter.scala index b1c318fa..1153b1e6 100644 --- a/src/main/scala/firrtl/Emitter.scala +++ b/src/main/scala/firrtl/Emitter.scala @@ -248,8 +248,11 @@ class VerilogEmitter extends Transform with PassBased with Emitter { case UIntLiteral(value, IntWidth(width)) => w write s"$width'h${value.toString(16)}" case SIntLiteral(value, IntWidth(width)) => - val unsignedValue = value + (if (value < 0) BigInt(1) << width.toInt else 0) - w write s"$width'sh${unsignedValue.toString(16)}" + val stringLiteral = value.toString(16) + w write (stringLiteral.head match { + case '-' => s"-$width'sh${stringLiteral.tail}" + case _ => s"$width'sh${stringLiteral}" + }) } def op_stream(doprim: DoPrim): Seq[Any] = { diff --git a/src/main/scala/firrtl/Utils.scala b/src/main/scala/firrtl/Utils.scala index c13e031e..ec53aa63 100644 --- a/src/main/scala/firrtl/Utils.scala +++ b/src/main/scala/firrtl/Utils.scala @@ -154,9 +154,6 @@ object Utils extends LazyLogging { /** Indent the results of [[ir.FirrtlNode.serialize]] */ def indent(str: String) = str replaceAllLiterally ("\n", "\n ") - def serialize(bi: BigInt): String = - if (bi < BigInt(0)) "\"h" + bi.toString(16).substring(1) + "\"" - else "\"h" + bi.toString(16) + "\"" implicit def toWrappedExpression (x:Expression): WrappedExpression = new WrappedExpression(x) def ceilLog2(x: BigInt): Int = (x-1).bitLength diff --git a/src/main/scala/firrtl/Visitor.scala b/src/main/scala/firrtl/Visitor.scala index 73555a37..222c2792 100644 --- a/src/main/scala/firrtl/Visitor.scala +++ b/src/main/scala/firrtl/Visitor.scala @@ -26,24 +26,16 @@ class Visitor(infoMode: InfoMode) extends FIRRTLBaseVisitor[FirrtlNode] { def visit[FirrtlNode](ctx: FIRRTLParser.CircuitContext): Circuit = visitCircuit(ctx) // These regex have to change if grammar changes + private val HexPattern = """\"*h([+\-]?[a-zA-Z0-9]+)\"*""".r + private val DecPattern = """([+\-]?[1-9]\d*)""".r + private val ZeroPattern = "0".r + private def string2BigInt(s: String): BigInt = { // private define legal patterns - val HexPattern = - """\"*h([a-zA-Z0-9]+)\"*""".r - val DecPattern = """(\+|-)?([1-9]\d*)""".r - val ZeroPattern = "0".r - val NegPattern = "(89AaBbCcDdEeFf)".r s match { case ZeroPattern(_*) => BigInt(0) - case HexPattern(hexdigits) => - hexdigits(0) match { - case NegPattern(_) => - BigInt("-" + hexdigits, 16) - case _ => BigInt(hexdigits, 16) - } - case DecPattern(sign, num) => - if (sign != null) BigInt(sign + num, 10) - else BigInt(num, 10) + case HexPattern(hexdigits) => BigInt(hexdigits, 16) + case DecPattern(num) => BigInt(num, 10) case _ => throw new Exception("Invalid String for conversion to BigInt " + s) } } @@ -310,11 +302,19 @@ class Visitor(infoMode: InfoMode) extends FIRRTLBaseVisitor[FirrtlNode] { UIntLiteral(value, width) case "SInt" => val (width, value) = - if (ctx.getChildCount > 4) - (IntWidth(string2BigInt(ctx.intLit(0).getText)), string2BigInt(ctx.intLit(1).getText)) - else { - val bigint = string2BigInt(ctx.intLit(0).getText) - (IntWidth(BigInt(bigint.bitLength + 1)), bigint) + if (ctx.getChildCount > 4) { + val width = string2BigInt(ctx.intLit(0).getText) + val value = string2BigInt(ctx.intLit(1).getText) + (IntWidth(width), value) + } else { + val str = ctx.intLit(0).getText + val value = string2BigInt(str) + // To calculate bitwidth of negative number, + // 1) negate number and subtract one to get the maximum positive value. + // 2) get bitwidth of max positive number + // 3) add one to account for the signed representation + val width = if (value < 0) (value.abs - BigInt(1)).bitLength + 1 else value.bitLength + 1 + (IntWidth(BigInt(width)), value) } SIntLiteral(value, width) case "validif(" => ValidIf(visitExp(ctx.exp(0)), visitExp(ctx.exp(1)), UnknownType) diff --git a/src/main/scala/firrtl/ir/IR.scala b/src/main/scala/firrtl/ir/IR.scala index 71ad9366..938b5848 100644 --- a/src/main/scala/firrtl/ir/IR.scala +++ b/src/main/scala/firrtl/ir/IR.scala @@ -103,14 +103,14 @@ abstract class Literal extends Expression { } case class UIntLiteral(value: BigInt, width: Width) extends Literal { def tpe = UIntType(width) - def serialize = s"UInt${width.serialize}(" + Utils.serialize(value) + ")" + def serialize = s"""UInt${width.serialize}("h""" + value.toString(16)+ """")""" def mapExpr(f: Expression => Expression): Expression = this def mapType(f: Type => Type): Expression = this def mapWidth(f: Width => Width): Expression = UIntLiteral(value, f(width)) } case class SIntLiteral(value: BigInt, width: Width) extends Literal { def tpe = SIntType(width) - def serialize = s"SInt${width.serialize}(" + Utils.serialize(value) + ")" + def serialize = s"""SInt${width.serialize}("h""" + value.toString(16)+ """")""" def mapExpr(f: Expression => Expression): Expression = this def mapType(f: Type => Type): Expression = this def mapWidth(f: Width => Width): Expression = SIntLiteral(value, f(width)) @@ -119,7 +119,7 @@ case class FixedLiteral(value: BigInt, width: Width, point: Width) extends Liter def tpe = FixedType(width, point) def serialize = { val pstring = if(point == UnknownWidth) "" else s"<${point.serialize}>" - s"Fixed${width.serialize}$pstring(" + Utils.serialize(value) + ")" + s"""Fixed${width.serialize}$pstring("h${value.toString(16)}")""" } def mapExpr(f: Expression => Expression): Expression = this def mapType(f: Type => Type): Expression = this diff --git a/src/main/scala/firrtl/passes/CheckWidths.scala b/src/main/scala/firrtl/passes/CheckWidths.scala index f9166a6f..4b0b1c0d 100644 --- a/src/main/scala/firrtl/passes/CheckWidths.scala +++ b/src/main/scala/firrtl/passes/CheckWidths.scala @@ -16,7 +16,7 @@ object CheckWidths extends Pass { class UninferredWidth (info: Info, mname: String) extends PassException( s"$info : [module $mname] Uninferred width.") class WidthTooSmall(info: Info, mname: String, b: BigInt) extends PassException( - s"$info : [module $mname] Width too small for constant ${serialize(b)}.") + s"$info : [module $mname] Width too small for constant $b.") class WidthTooBig(info: Info, mname: String, b: BigInt) extends PassException( s"$info : [module $mname] Width $b greater than max allowed width of $MaxWidth bits") class DshlTooBig(info: Info, mname: String) extends PassException( diff --git a/src/test/scala/firrtlTests/UnitTests.scala b/src/test/scala/firrtlTests/UnitTests.scala index 3cf25d3a..0d5d098c 100644 --- a/src/test/scala/firrtlTests/UnitTests.scala +++ b/src/test/scala/firrtlTests/UnitTests.scala @@ -304,7 +304,6 @@ class UnitTests extends FirrtlFlatSpec { (c: Circuit, p: Pass) => p.run(c) } } - } "Conditional conection of clocks" should "throw an exception" in { @@ -323,4 +322,55 @@ class UnitTests extends FirrtlFlatSpec { compileToVerilog(input) } } + + "Parsing SInts" should "work" in { + val passes = Seq() + val input = + """circuit Unit : + | module Unit : + | node posSInt = SInt(13) + | node negSInt = SInt(-13) + | node posSIntString = SInt("h0d") + | node posSIntString2 = SInt("h+d") + | node posSIntString3 = SInt("hd") + | node negSIntString = SInt("h-d") + | node negSIntStringWidth = SInt<5>("h-d") + | node neg2 = SInt("h-2") + | node pos2 = SInt("h2") + | node neg1 = SInt("h-1") + |""".stripMargin + val expected = Seq( + """node posSInt = SInt<5>("hd")""", + """node negSInt = SInt<5>("h-d")""", + """node posSIntString = SInt<5>("hd")""", + """node posSIntString2 = SInt<5>("hd")""", + """node posSIntString3 = SInt<5>("hd")""", + """node negSIntString = SInt<5>("h-d")""", + """node negSIntStringWidth = SInt<5>("h-d")""", + """node neg2 = SInt<2>("h-2")""", + """node pos2 = SInt<3>("h2")""", + """node neg1 = SInt<1>("h-1")""" + ) + executeTest(input, expected, passes) + } + "Verilog SInts" should "work" in { + val passes = Seq() + val input = + """circuit Unit : + | module Unit : + | output posSInt : SInt + | output negSInt : SInt + | posSInt <= SInt(13) + | negSInt <= SInt(-13) + |""".stripMargin + val expected = Seq( + """assign posSInt = 5'shd;""", + """assign negSInt = -5'shd;""" + ) + val out = compileToVerilog(input) + val lines = out.split("\n") map normalized + expected foreach { e => + lines should contain(e) + } + } } |
