aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main/antlr4/FIRRTL.g42
-rw-r--r--src/main/scala/firrtl/Emitter.scala7
-rw-r--r--src/main/scala/firrtl/Utils.scala3
-rw-r--r--src/main/scala/firrtl/Visitor.scala38
-rw-r--r--src/main/scala/firrtl/ir/IR.scala6
-rw-r--r--src/main/scala/firrtl/passes/CheckWidths.scala2
-rw-r--r--src/test/scala/firrtlTests/UnitTests.scala52
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)
+ }
+ }
}