diff options
| -rw-r--r-- | src/main/scala/firrtl/AddDescriptionNodes.scala | 4 | ||||
| -rw-r--r-- | src/main/scala/firrtl/Emitter.scala | 2 | ||||
| -rw-r--r-- | src/main/scala/firrtl/Utils.scala | 1 | ||||
| -rw-r--r-- | src/main/scala/firrtl/WIR.scala | 13 | ||||
| -rw-r--r-- | src/main/scala/firrtl/ir/IR.scala | 129 | ||||
| -rw-r--r-- | src/main/scala/firrtl/ir/Serializer.scala | 58 | ||||
| -rw-r--r-- | src/main/scala/firrtl/passes/memlib/MemIR.scala | 2 | ||||
| -rw-r--r-- | src/test/scala/firrtlTests/fixed/FixedSerializationSpec.scala | 27 |
8 files changed, 88 insertions, 148 deletions
diff --git a/src/main/scala/firrtl/AddDescriptionNodes.scala b/src/main/scala/firrtl/AddDescriptionNodes.scala index 0d804e63..5ff07314 100644 --- a/src/main/scala/firrtl/AddDescriptionNodes.scala +++ b/src/main/scala/firrtl/AddDescriptionNodes.scala @@ -79,7 +79,7 @@ case class Attribute(string: StringLit) extends Description { * @param stmt the encapsulated statement */ private case class DescribedStmt(descriptions: Seq[Description], stmt: Statement) extends Statement with HasDescription { - def serialize: String = s"${descriptions.map(_.serialize).mkString("\n")}\n${stmt.serialize}" + override def serialize: String = s"${descriptions.map(_.serialize).mkString("\n")}\n${stmt.serialize}" def mapStmt(f: Statement => Statement): Statement = f(stmt) def mapExpr(f: Expression => Expression): Statement = this.copy(stmt = stmt.mapExpr(f)) def mapType(f: Type => Type): Statement = this.copy(stmt = stmt.mapType(f)) @@ -104,7 +104,7 @@ private case class DescribedMod(descriptions: Seq[Description], val info = mod.info val name = mod.name val ports = mod.ports - def serialize: String = s"${descriptions.map(_.serialize).mkString("\n")}\n${mod.serialize}" + override def serialize: String = s"${descriptions.map(_.serialize).mkString("\n")}\n${mod.serialize}" def mapStmt(f: Statement => Statement): DefModule = this.copy(mod = mod.mapStmt(f)) def mapPort(f: Port => Port): DefModule = this.copy(mod = mod.mapPort(f)) def mapString(f: String => String): DefModule = this.copy(mod = mod.mapString(f)) diff --git a/src/main/scala/firrtl/Emitter.scala b/src/main/scala/firrtl/Emitter.scala index b6162692..b8d26103 100644 --- a/src/main/scala/firrtl/Emitter.scala +++ b/src/main/scala/firrtl/Emitter.scala @@ -167,7 +167,7 @@ case class VRandom(width: BigInt) extends Expression { def tpe = UIntType(IntWidth(width)) def nWords = (width + 31) / 32 def realWidth = nWords * 32 - def serialize: String = "RANDOM" + override def serialize: String = "RANDOM" def mapExpr(f: Expression => Expression): Expression = this def mapType(f: Type => Type): Expression = this def mapWidth(f: Width => Width): Expression = this diff --git a/src/main/scala/firrtl/Utils.scala b/src/main/scala/firrtl/Utils.scala index a807b39f..71a4d3ef 100644 --- a/src/main/scala/firrtl/Utils.scala +++ b/src/main/scala/firrtl/Utils.scala @@ -234,6 +234,7 @@ object Utils extends LazyLogging { def isTemp(str: String): Boolean = str.head == '_' /** Indent the results of [[ir.FirrtlNode.serialize]] */ + @deprecated("Use ther new firrt.ir.Serializer instead.", "FIRRTL 1.4") def indent(str: String) = str replaceAllLiterally ("\n", "\n ") implicit def toWrappedExpression (x:Expression): WrappedExpression = new WrappedExpression(x) diff --git a/src/main/scala/firrtl/WIR.scala b/src/main/scala/firrtl/WIR.scala index aeb4f4c2..184ce665 100644 --- a/src/main/scala/firrtl/WIR.scala +++ b/src/main/scala/firrtl/WIR.scala @@ -65,7 +65,6 @@ object WSubAccess { case object WVoid extends Expression { def tpe = UnknownType - def serialize: String = "VOID" def mapExpr(f: Expression => Expression): Expression = this def mapType(f: Type => Type): Expression = this def mapWidth(f: Width => Width): Expression = this @@ -75,7 +74,6 @@ case object WVoid extends Expression { } case object WInvalid extends Expression { def tpe = UnknownType - def serialize: String = "INVALID" def mapExpr(f: Expression => Expression): Expression = this def mapType(f: Type => Type): Expression = this def mapWidth(f: Width => Width): Expression = this @@ -86,7 +84,6 @@ case object WInvalid extends Expression { // Useful for splitting then remerging references case object EmptyExpression extends Expression { def tpe = UnknownType - def serialize: String = "EMPTY" def mapExpr(f: Expression => Expression): Expression = this def mapType(f: Type => Type): Expression = this def mapWidth(f: Width => Width): Expression = this @@ -109,8 +106,6 @@ case class WDefInstanceConnector( module: String, tpe: Type, portCons: Seq[(Expression, Expression)]) extends Statement with IsDeclaration { - def serialize: String = s"inst $name of $module with ${tpe.serialize} connected to " + - portCons.map(_._2.serialize).mkString("(", ", ", ")") + info.serialize def mapExpr(f: Expression => Expression): Statement = this.copy(portCons = portCons map { case (e1, e2) => (f(e1), f(e2)) }) def mapStmt(f: Statement => Statement): Statement = this @@ -186,7 +181,7 @@ private[firrtl] case class InfoExpr(info: Info, expr: Expression) extends Expres def tpe: Type = expr.tpe // Members declared in firrtl.ir.FirrtlNode - def serialize: String = s"(${expr.serialize}: ${info.serialize})" + override def serialize: String = s"(${expr.serialize}: ${info.serialize})" } private[firrtl] object InfoExpr { @@ -331,8 +326,6 @@ case class CDefMemory( size: BigInt, seq: Boolean, readUnderWrite: ReadUnderWrite.Value = ReadUnderWrite.Undefined) extends Statement with HasInfo { - def serialize: String = (if (seq) "smem" else "cmem") + - s" $name : ${tpe.serialize} [$size]" + info.serialize def mapExpr(f: Expression => Expression): Statement = this def mapStmt(f: Statement => Statement): Statement = this def mapType(f: Type => Type): Statement = this.copy(tpe = f(tpe)) @@ -350,10 +343,6 @@ case class CDefMPort(info: Info, mem: String, exps: Seq[Expression], direction: MPortDir) extends Statement with HasInfo { - def serialize: String = { - val dir = direction.serialize - s"$dir mport $name = $mem[${exps.head.serialize}], ${exps(1).serialize}" + info.serialize - } def mapExpr(f: Expression => Expression): Statement = this.copy(exps = exps map f) def mapStmt(f: Statement => Statement): Statement = this def mapType(f: Type => Type): Statement = this.copy(tpe = f(tpe)) diff --git a/src/main/scala/firrtl/ir/IR.scala b/src/main/scala/firrtl/ir/IR.scala index 33083c10..6441a3b2 100644 --- a/src/main/scala/firrtl/ir/IR.scala +++ b/src/main/scala/firrtl/ir/IR.scala @@ -3,7 +3,7 @@ package firrtl package ir -import Utils.{dec2string, indent, trim} +import Utils.{dec2string, trim} import firrtl.constraint.{Constraint, IsKnown, IsVar} import org.apache.commons.text.translate.{AggregateTranslator, JavaUnicodeEscaper, LookupTranslator} @@ -17,7 +17,7 @@ abstract class FirrtlNode { abstract class Info extends FirrtlNode { // default implementation - def serialize: String = this.toString + def serialize: String = Serializer.serialize(this) def ++(that: Info): Info } case object NoInfo extends Info { @@ -194,6 +194,7 @@ abstract class PrimOp extends FirrtlNode { } abstract class Expression extends FirrtlNode { + def serialize: String = Serializer.serialize(this) def tpe: Type def mapExpr(f: Expression => Expression): Expression def mapType(f: Type => Type): Expression @@ -220,7 +221,6 @@ object Reference { case class Reference(name: String, tpe: Type = UnknownType, kind: Kind = UnknownKind, flow: Flow = UnknownFlow) extends Expression with HasName { - def serialize: String = name def mapExpr(f: Expression => Expression): Expression = this def mapType(f: Type => Type): Expression = this.copy(tpe = f(tpe)) def mapWidth(f: Width => Width): Expression = this @@ -231,7 +231,6 @@ case class Reference(name: String, tpe: Type = UnknownType, kind: Kind = Unknown case class SubField(expr: Expression, name: String, tpe: Type = UnknownType, flow: Flow = UnknownFlow) extends Expression with HasName { - def serialize: String = s"${expr.serialize}.$name" def mapExpr(f: Expression => Expression): Expression = this.copy(expr = f(expr)) def mapType(f: Type => Type): Expression = this.copy(tpe = f(tpe)) def mapWidth(f: Width => Width): Expression = this @@ -242,7 +241,6 @@ case class SubField(expr: Expression, name: String, tpe: Type = UnknownType, flo case class SubIndex(expr: Expression, value: Int, tpe: Type, flow: Flow = UnknownFlow) extends Expression { - def serialize: String = s"${expr.serialize}[$value]" def mapExpr(f: Expression => Expression): Expression = this.copy(expr = f(expr)) def mapType(f: Type => Type): Expression = this.copy(tpe = f(tpe)) def mapWidth(f: Width => Width): Expression = this @@ -253,7 +251,6 @@ case class SubIndex(expr: Expression, value: Int, tpe: Type, flow: Flow = Unknow case class SubAccess(expr: Expression, index: Expression, tpe: Type, flow: Flow = UnknownFlow) extends Expression { - def serialize: String = s"${expr.serialize}[${index.serialize}]" def mapExpr(f: Expression => Expression): Expression = this.copy(expr = f(expr), index = f(index)) def mapType(f: Type => Type): Expression = this.copy(tpe = f(tpe)) def mapWidth(f: Width => Width): Expression = this @@ -263,7 +260,6 @@ case class SubAccess(expr: Expression, index: Expression, tpe: Type, flow: Flow } case class Mux(cond: Expression, tval: Expression, fval: Expression, tpe: Type = UnknownType) extends Expression { - def serialize: String = s"mux(${cond.serialize}, ${tval.serialize}, ${fval.serialize})" def mapExpr(f: Expression => Expression): Expression = Mux(f(cond), f(tval), f(fval), tpe) def mapType(f: Type => Type): Expression = this.copy(tpe = f(tpe)) def mapWidth(f: Width => Width): Expression = this @@ -272,7 +268,6 @@ case class Mux(cond: Expression, tval: Expression, fval: Expression, tpe: Type = def foreachWidth(f: Width => Unit): Unit = () } case class ValidIf(cond: Expression, value: Expression, tpe: Type) extends Expression { - def serialize: String = s"validif(${cond.serialize}, ${value.serialize})" def mapExpr(f: Expression => Expression): Expression = ValidIf(f(cond), f(value), tpe) def mapType(f: Type => Type): Expression = this.copy(tpe = f(tpe)) def mapWidth(f: Width => Width): Expression = this @@ -286,7 +281,6 @@ abstract class Literal extends Expression { } case class UIntLiteral(value: BigInt, width: Width) extends Literal { def tpe = UIntType(width) - 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)) @@ -309,7 +303,6 @@ object UIntLiteral { } case class SIntLiteral(value: BigInt, width: Width) extends Literal { def tpe = SIntType(width) - 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)) @@ -323,10 +316,6 @@ object SIntLiteral { } case class FixedLiteral(value: BigInt, width: Width, point: Width) extends Literal { def tpe = FixedType(width, point) - def serialize = { - val pstring = if(point == UnknownWidth) "" else s"<${point.serialize}>" - s"""Fixed${width.serialize}$pstring("h${value.toString(16)}")""" - } def mapExpr(f: Expression => Expression): Expression = this def mapType(f: Type => Type): Expression = this def mapWidth(f: Width => Width): Expression = FixedLiteral(value, f(width), f(point)) @@ -335,8 +324,6 @@ case class FixedLiteral(value: BigInt, width: Width, point: Width) extends Liter def foreachWidth(f: Width => Unit): Unit = { f(width); f(point) } } case class DoPrim(op: PrimOp, args: Seq[Expression], consts: Seq[BigInt], tpe: Type) extends Expression { - def serialize: String = op.serialize + "(" + - (args.map(_.serialize) ++ consts.map(_.toString)).mkString(", ") + ")" def mapExpr(f: Expression => Expression): Expression = this.copy(args = args map f) def mapType(f: Type => Type): Expression = this.copy(tpe = f(tpe)) def mapWidth(f: Width => Width): Expression = this @@ -346,6 +333,7 @@ case class DoPrim(op: PrimOp, args: Seq[Expression], consts: Seq[BigInt], tpe: T } abstract class Statement extends FirrtlNode { + def serialize: String = Serializer.serialize(this) def mapStmt(f: Statement => Statement): Statement def mapExpr(f: Expression => Expression): Statement def mapType(f: Type => Type): Statement @@ -358,7 +346,6 @@ abstract class Statement extends FirrtlNode { def foreachInfo(f: Info => Unit): Unit } case class DefWire(info: Info, name: String, tpe: Type) extends Statement with IsDeclaration { - def serialize: String = s"wire $name : ${tpe.serialize}" + info.serialize def mapStmt(f: Statement => Statement): Statement = this def mapExpr(f: Expression => Expression): Statement = this def mapType(f: Type => Type): Statement = DefWire(info, name, f(tpe)) @@ -377,9 +364,6 @@ case class DefRegister( clock: Expression, reset: Expression, init: Expression) extends Statement with IsDeclaration { - def serialize: String = - s"reg $name : ${tpe.serialize}, ${clock.serialize} with :" + - indent("\n" + s"reset => (${reset.serialize}, ${init.serialize})" + info.serialize) def mapStmt(f: Statement => Statement): Statement = this def mapExpr(f: Expression => Expression): Statement = DefRegister(info, name, tpe, f(clock), f(reset), f(init)) @@ -399,7 +383,6 @@ object DefInstance { case class DefInstance(info: Info, name: String, module: String, tpe: Type = UnknownType) extends Statement with IsDeclaration { - def serialize: String = s"inst $name of $module" + info.serialize def mapExpr(f: Expression => Expression): Statement = this def mapStmt(f: Statement => Statement): Statement = this def mapType(f: Type => Type): Statement = this.copy(tpe = f(tpe)) @@ -430,17 +413,6 @@ case class DefMemory( readwriters: Seq[String], // TODO: handle read-under-write readUnderWrite: ReadUnderWrite.Value = ReadUnderWrite.Undefined) extends Statement with IsDeclaration { - def serialize: String = - s"mem $name :" + info.serialize + - indent( - (Seq("\ndata-type => " + dataType.serialize, - "depth => " + depth, - "read-latency => " + readLatency, - "write-latency => " + writeLatency) ++ - (readers map ("reader => " + _)) ++ - (writers map ("writer => " + _)) ++ - (readwriters map ("readwriter => " + _)) ++ - Seq(s"read-under-write => ${readUnderWrite}")) mkString "\n") def mapStmt(f: Statement => Statement): Statement = this def mapExpr(f: Expression => Expression): Statement = this def mapType(f: Type => Type): Statement = this.copy(dataType = f(dataType)) @@ -453,7 +425,6 @@ case class DefMemory( def foreachInfo(f: Info => Unit): Unit = f(info) } case class DefNode(info: Info, name: String, value: Expression) extends Statement with IsDeclaration { - def serialize: String = s"node $name = ${value.serialize}" + info.serialize def mapStmt(f: Statement => Statement): Statement = this def mapExpr(f: Expression => Expression): Statement = DefNode(info, name, f(value)) def mapType(f: Type => Type): Statement = this @@ -470,11 +441,6 @@ case class Conditionally( pred: Expression, conseq: Statement, alt: Statement) extends Statement with HasInfo { - def serialize: String = - s"when ${pred.serialize} :" + info.serialize + - indent("\n" + conseq.serialize) + - (if (alt == EmptyStmt) "" - else "\nelse :" + indent("\n" + alt.serialize)) def mapStmt(f: Statement => Statement): Statement = Conditionally(info, pred, f(conseq), f(alt)) def mapExpr(f: Expression => Expression): Statement = Conditionally(info, f(pred), conseq, alt) def mapType(f: Type => Type): Statement = this @@ -492,10 +458,6 @@ object Block { } case class Block(stmts: Seq[Statement]) extends Statement { - def serialize: String = { - val res = stmts.view.map(_.serialize).mkString("\n") - if (res.nonEmpty) res else EmptyStmt.serialize - } def mapStmt(f: Statement => Statement): Statement = { val res = new scala.collection.mutable.ArrayBuffer[Statement]() var its = stmts.iterator :: Nil @@ -526,7 +488,6 @@ case class Block(stmts: Seq[Statement]) extends Statement { def foreachInfo(f: Info => Unit): Unit = () } case class PartialConnect(info: Info, loc: Expression, expr: Expression) extends Statement with HasInfo { - def serialize: String = s"${loc.serialize} <- ${expr.serialize}" + info.serialize def mapStmt(f: Statement => Statement): Statement = this def mapExpr(f: Expression => Expression): Statement = PartialConnect(info, f(loc), f(expr)) def mapType(f: Type => Type): Statement = this @@ -539,7 +500,6 @@ case class PartialConnect(info: Info, loc: Expression, expr: Expression) extends def foreachInfo(f: Info => Unit): Unit = f(info) } case class Connect(info: Info, loc: Expression, expr: Expression) extends Statement with HasInfo { - def serialize: String = s"${loc.serialize} <= ${expr.serialize}" + info.serialize def mapStmt(f: Statement => Statement): Statement = this def mapExpr(f: Expression => Expression): Statement = Connect(info, f(loc), f(expr)) def mapType(f: Type => Type): Statement = this @@ -552,7 +512,6 @@ case class Connect(info: Info, loc: Expression, expr: Expression) extends Statem def foreachInfo(f: Info => Unit): Unit = f(info) } case class IsInvalid(info: Info, expr: Expression) extends Statement with HasInfo { - def serialize: String = s"${expr.serialize} is invalid" + info.serialize def mapStmt(f: Statement => Statement): Statement = this def mapExpr(f: Expression => Expression): Statement = IsInvalid(info, f(expr)) def mapType(f: Type => Type): Statement = this @@ -565,7 +524,6 @@ case class IsInvalid(info: Info, expr: Expression) extends Statement with HasInf def foreachInfo(f: Info => Unit): Unit = f(info) } case class Attach(info: Info, exprs: Seq[Expression]) extends Statement with HasInfo { - def serialize: String = "attach " + exprs.map(_.serialize).mkString("(", ", ", ")") def mapStmt(f: Statement => Statement): Statement = this def mapExpr(f: Expression => Expression): Statement = Attach(info, exprs map f) def mapType(f: Type => Type): Statement = this @@ -578,7 +536,6 @@ case class Attach(info: Info, exprs: Seq[Expression]) extends Statement with Has def foreachInfo(f: Info => Unit): Unit = f(info) } case class Stop(info: Info, ret: Int, clk: Expression, en: Expression) extends Statement with HasInfo { - def serialize: String = s"stop(${clk.serialize}, ${en.serialize}, $ret)" + info.serialize def mapStmt(f: Statement => Statement): Statement = this def mapExpr(f: Expression => Expression): Statement = Stop(info, ret, f(clk), f(en)) def mapType(f: Type => Type): Statement = this @@ -596,11 +553,6 @@ case class Print( args: Seq[Expression], clk: Expression, en: Expression) extends Statement with HasInfo { - def serialize: String = { - val strs = Seq(clk.serialize, en.serialize, string.escape) ++ - (args map (_.serialize)) - "printf(" + (strs mkString ", ") + ")" + info.serialize - } def mapStmt(f: Statement => Statement): Statement = this def mapExpr(f: Expression => Expression): Statement = Print(info, string, args map f, f(clk), f(en)) def mapType(f: Type => Type): Statement = this @@ -628,8 +580,6 @@ case class Verification( en: Expression, msg: StringLit ) extends Statement with HasInfo { - def serialize: String = op + "(" + Seq(clk, pred, en).map(_.serialize) - .mkString(", ") + ", \"" + msg.serialize + "\")" + info.serialize def mapStmt(f: Statement => Statement): Statement = this def mapExpr(f: Expression => Expression): Statement = copy(clk = f(clk), pred = f(pred), en = f(en)) @@ -645,7 +595,6 @@ case class Verification( // end formal case object EmptyStmt extends Statement { - def serialize: String = "skip" def mapStmt(f: Statement => Statement): Statement = this def mapExpr(f: Expression => Expression): Statement = this def mapType(f: Type => Type): Statement = this @@ -659,6 +608,7 @@ case object EmptyStmt extends Statement { } abstract class Width extends FirrtlNode { + def serialize: String = Serializer.serialize(this) def +(x: Width): Width = (this, x) match { case (a: IntWidth, b: IntWidth) => IntWidth(a.width + b.width) case _ => UnknownWidth @@ -695,7 +645,6 @@ object IntWidth { def unapply(w: IntWidth): Option[BigInt] = Some(w.width) } class IntWidth(val width: BigInt) extends Width with Product { - def serialize: String = s"<$width>" override def equals(that: Any) = that match { case w: IntWidth => width == w.width case _ => false @@ -711,14 +660,12 @@ class IntWidth(val width: BigInt) extends Width with Product { case _ => throw new IndexOutOfBoundsException } } -case object UnknownWidth extends Width { - def serialize: String = "" -} -case class CalcWidth(arg: Constraint) extends Width { - def serialize: String = s"calcw(${arg.serialize})" -} +case object UnknownWidth extends Width + +case class CalcWidth(arg: Constraint) extends Width + case class VarWidth(name: String) extends Width with IsVar { - override def serialize: String = s"<$name>" + override def serialize: String = name } /** Orientation of [[Field]] */ @@ -732,28 +679,28 @@ case object Flip extends Orientation { /** Field of [[BundleType]] */ case class Field(name: String, flip: Orientation, tpe: Type) extends FirrtlNode with HasName { - def serialize: String = flip.serialize + name + " : " + tpe.serialize + def serialize: String = Serializer.serialize(this) } /** Bounds of [[IntervalType]] */ trait Bound extends Constraint { - def serialize: String + def serialize: String = Serializer.serialize(this) } case object UnknownBound extends Bound { - def serialize: String = "?" def map(f: Constraint=>Constraint): Constraint = this override def reduce(): Constraint = this val children = Vector() } case class CalcBound(arg: Constraint) extends Bound { - def serialize: String = s"calcb(${arg.serialize})" def map(f: Constraint=>Constraint): Constraint = f(arg) override def reduce(): Constraint = arg val children = Vector(arg) } -case class VarBound(name: String) extends IsVar with Bound +case class VarBound(name: String) extends IsVar with Bound { + override def serialize: String = Serializer.serialize(this) +} object KnownBound { def unapply(b: Constraint): Option[BigDecimal] = b match { case k: IsKnown => Some(k.value) @@ -765,7 +712,6 @@ object KnownBound { } } case class Open(value: BigDecimal) extends IsKnown with Bound { - def serialize = s"o($value)" def +(that: IsKnown): IsKnown = Open(value + that.value) def *(that: IsKnown): IsKnown = that match { case Closed(x) if x == 0 => Closed(x) @@ -778,7 +724,6 @@ case class Open(value: BigDecimal) extends IsKnown with Bound { def pow: IsKnown = if(value.isBinaryDouble) Open(BigDecimal(BigInt(1) << value.toInt)) else sys.error("Shouldn't be here") } case class Closed(value: BigDecimal) extends IsKnown with Bound { - def serialize = s"c($value)" def +(that: IsKnown): IsKnown = that match { case Open(x) => Open(value + x) case Closed(x) => Closed(value + x) @@ -797,6 +742,7 @@ case class Closed(value: BigDecimal) extends IsKnown with Bound { /** Types of [[FirrtlNode]] */ abstract class Type extends FirrtlNode { + def serialize: String = Serializer.serialize(this) def mapType(f: Type => Type): Type def mapWidth(f: Width => Width): Type def foreachType(f: Type => Unit): Unit @@ -815,20 +761,14 @@ abstract class AggregateType extends Type { def foreachWidth(f: Width => Unit): Unit = () } case class UIntType(width: Width) extends GroundType { - def serialize: String = "UInt" + width.serialize def mapWidth(f: Width => Width): Type = UIntType(f(width)) def foreachWidth(f: Width => Unit): Unit = f(width) } case class SIntType(width: Width) extends GroundType { - def serialize: String = "SInt" + width.serialize def mapWidth(f: Width => Width): Type = SIntType(f(width)) def foreachWidth(f: Width => Unit): Unit = f(width) } case class FixedType(width: Width, point: Width) extends GroundType { - override def serialize: String = { - val pstring = if(point == UnknownWidth) "" else s"<${point.serialize}>" - s"Fixed${width.serialize}$pstring" - } def mapWidth(f: Width => Width): Type = FixedType(f(width), f(point)) def foreachWidth(f: Width => Unit): Unit = { f(width); f(point) } } @@ -911,42 +851,35 @@ case class IntervalType(lower: Bound, upper: Bound, point: Width) extends Ground } case class BundleType(fields: Seq[Field]) extends AggregateType { - def serialize: String = "{ " + (fields map (_.serialize) mkString ", ") + "}" def mapType(f: Type => Type): Type = BundleType(fields map (x => x.copy(tpe = f(x.tpe)))) def foreachType(f: Type => Unit): Unit = fields.foreach{ x => f(x.tpe) } } case class VectorType(tpe: Type, size: Int) extends AggregateType { - def serialize: String = tpe.serialize + s"[$size]" def mapType(f: Type => Type): Type = this.copy(tpe = f(tpe)) def foreachType(f: Type => Unit): Unit = f(tpe) } case object ClockType extends GroundType { val width = IntWidth(1) - def serialize: String = "Clock" def mapWidth(f: Width => Width): Type = this def foreachWidth(f: Width => Unit): Unit = () } /* Abstract reset, will be inferred to UInt<1> or AsyncReset */ case object ResetType extends GroundType { val width = IntWidth(1) - def serialize: String = "Reset" def mapWidth(f: Width => Width): Type = this def foreachWidth(f: Width => Unit): Unit = () } case object AsyncResetType extends GroundType { val width = IntWidth(1) - def serialize: String = "AsyncReset" def mapWidth(f: Width => Width): Type = this def foreachWidth(f: Width => Unit): Unit = () } case class AnalogType(width: Width) extends GroundType { - def serialize: String = "Analog" + width.serialize def mapWidth(f: Width => Width): Type = AnalogType(f(width)) def foreachWidth(f: Width => Unit): Unit = f(width) } case object UnknownType extends Type { - def serialize: String = "?" def mapType(f: Type => Type): Type = this def mapWidth(f: Width => Width): Type = this def foreachType(f: Type => Unit): Unit = () @@ -968,7 +901,7 @@ case class Port( name: String, direction: Direction, tpe: Type) extends FirrtlNode with IsDeclaration { - def serialize: String = s"${direction.serialize} $name : ${tpe.serialize}" + info.serialize + def serialize: String = Serializer.serialize(this) def mapType(f: Type => Type): Port = Port(info, name, direction, f(tpe)) def mapString(f: String => String): Port = Port(info, f(name), direction, tpe) } @@ -976,35 +909,26 @@ case class Port( /** Parameters for external modules */ sealed abstract class Param extends FirrtlNode { def name: String - def serialize: String = s"parameter $name = " + def serialize: String = Serializer.serialize(this) } /** Integer (of any width) Parameter */ -case class IntParam(name: String, value: BigInt) extends Param { - override def serialize: String = super.serialize + value -} +case class IntParam(name: String, value: BigInt) extends Param /** IEEE Double Precision Parameter (for Verilog real) */ -case class DoubleParam(name: String, value: Double) extends Param { - override def serialize: String = super.serialize + value -} +case class DoubleParam(name: String, value: Double) extends Param /** String Parameter */ -case class StringParam(name: String, value: StringLit) extends Param { - override def serialize: String = super.serialize + value.escape -} +case class StringParam(name: String, value: StringLit) extends Param /** Raw String Parameter * Useful for Verilog type parameters * @note Firrtl doesn't guarantee anything about this String being legal in any backend */ -case class RawStringParam(name: String, value: String) extends Param { - override def serialize: String = super.serialize + s"'${value.replace("'", "\\'")}'" -} +case class RawStringParam(name: String, value: String) extends Param /** Base class for modules */ abstract class DefModule extends FirrtlNode with IsDeclaration { val info : Info val name : String val ports : Seq[Port] - protected def serializeHeader(tpe: String): String = - s"$tpe $name :${info.serialize}${indent(ports.map("\n" + _.serialize).mkString)}\n" + def serialize: String = Serializer.serialize(this) def mapStmt(f: Statement => Statement): DefModule def mapPort(f: Port => Port): DefModule def mapString(f: String => String): DefModule @@ -1019,7 +943,6 @@ abstract class DefModule extends FirrtlNode with IsDeclaration { * An instantiable hardware block */ case class Module(info: Info, name: String, ports: Seq[Port], body: Statement) extends DefModule { - def serialize: String = serializeHeader("module") + indent("\n" + body.serialize) def mapStmt(f: Statement => Statement): DefModule = this.copy(body = f(body)) def mapPort(f: Port => Port): DefModule = this.copy(ports = ports map f) def mapString(f: String => String): DefModule = this.copy(name = f(name)) @@ -1040,8 +963,6 @@ case class ExtModule( ports: Seq[Port], defname: String, params: Seq[Param]) extends DefModule { - def serialize: String = serializeHeader("extmodule") + - indent(s"\ndefname = $defname\n" + params.map(_.serialize).mkString("\n")) def mapStmt(f: Statement => Statement): DefModule = this def mapPort(f: Port => Port): DefModule = this.copy(ports = ports map f) def mapString(f: String => String): DefModule = this.copy(name = f(name)) @@ -1053,9 +974,7 @@ case class ExtModule( } case class Circuit(info: Info, modules: Seq[DefModule], main: String) extends FirrtlNode with HasInfo { - def serialize: String = - s"circuit $main :" + info.serialize + - (modules map ("\n" + _.serialize) map indent mkString "\n") + "\n" + def serialize: String = Serializer.serialize(this) def mapModule(f: DefModule => DefModule): Circuit = this.copy(modules = modules map f) def mapString(f: String => String): Circuit = this.copy(main = f(main)) def mapInfo(f: Info => Info): Circuit = this.copy(f(info)) diff --git a/src/main/scala/firrtl/ir/Serializer.scala b/src/main/scala/firrtl/ir/Serializer.scala index 8ab4fc6e..ea304cf3 100644 --- a/src/main/scala/firrtl/ir/Serializer.scala +++ b/src/main/scala/firrtl/ir/Serializer.scala @@ -46,9 +46,14 @@ object Serializer { private def s(node: Info)(implicit b: StringBuilder, indent: Int): Unit = node match { case f : FileInfo => b ++= " @[" ; b ++= f.escaped ; b ++= "]" case NoInfo => // empty string - case MultiInfo(infos) => - val ii = flattenInfo(infos) - b ++= " @[" ; sInfo(ii, ", ") ; b ++= "]" + case m : MultiInfo => + val infos = m.flatten + if(infos.nonEmpty) { + val lastId = infos.length - 1 + b ++= " @[" + infos.zipWithIndex.foreach { case (f, i) => b ++= f.escaped; if (i < lastId) b += ' ' } + b += ']' + } } private def s(str: StringLit)(implicit b: StringBuilder, indent: Int): Unit = b ++= str.serialize @@ -68,9 +73,8 @@ object Serializer { case SIntLiteral(value, width) => b ++= "SInt" ; s(width) ; b ++= "(\"h" ; b ++= value.toString(16) ; b ++= "\")" case FixedLiteral(value, width, point) => - b ++= "Fixed" - if(width != UnknownWidth) { b += '<' ; s(width) ; b += '>' } - s(point) ; b ++= "(\"h" ; b ++= value.toString(16) ; b ++= "\")" + b ++= "Fixed" ; s(width) ; sPoint(point) + b ++= "(\"h" ; b ++= value.toString(16) ; b ++= "\")" // WIR case firrtl.WVoid => b ++= "VOID" case firrtl.WInvalid => b ++= "INVALID" @@ -88,6 +92,7 @@ object Serializer { newLineAndIndent(1) ; s(alt)(b, indent + 1) } case EmptyStmt => b ++= "skip" + case Block(Seq()) => b ++= "skip" case Block(stmts) => val it = stmts.iterator while(it.hasNext) { @@ -131,6 +136,9 @@ object Serializer { case firrtl.CDefMPort(info, name, _, mem, exps, direction) => b ++= direction.serialize ; b ++= " mport " ; b ++= name ; b ++= " = " ; b ++= mem b += '[' ; s(exps.head) ; b ++= "], " ; s(exps(1)) ; s(info) + case firrtl.WDefInstanceConnector(info, name, module, tpe, portCons) => + b ++= "inst " ; b ++= name ; b ++= " of " ; b ++= module ; b ++= " with " ; s(tpe) ; b ++= " connected to (" + s(portCons.map(_._2), ", ") ; b += ')' ; s(info) } private def s(node: Width)(implicit b: StringBuilder, indent: Int): Unit = node match { @@ -140,6 +148,13 @@ object Serializer { case VarWidth(name) => b += '<'; b ++= name; b += '>' } + private def sPoint(node: Width)(implicit b: StringBuilder, indent: Int): Unit = node match { + case IntWidth(width) => b ++= "<<"; b ++= width.toString(); b ++= ">>" + case UnknownWidth => // empty string + case CalcWidth(arg) => b ++= "calcw("; s(arg); b += ')' + case VarWidth(name) => b ++= "<<"; b ++= name; b ++= ">>" + } + private def s(node: Orientation)(implicit b: StringBuilder, indent: Int): Unit = node match { case Default => // empty string case Flip => b ++= "flip " @@ -153,7 +168,7 @@ object Serializer { // Types case UIntType(width: Width) => b ++= "UInt"; s(width) case SIntType(width: Width) => b ++= "SInt"; s(width) - case FixedType(width, point) => b ++= "Fixed"; s(width); s(point) + case FixedType(width, point) => b ++= "Fixed"; s(width); sPoint(point) case BundleType(fields) => b ++= "{ "; sField(fields, ", "); b += '}' case VectorType(tpe, size) => s(tpe); b += '['; b ++= size.toString; b += ']' case ClockType => b ++= "Clock" @@ -188,11 +203,8 @@ object Serializer { case Module(info, name, ports, body) => b ++= "module " ; b ++= name ; b ++= " :" ; s(info) ports.foreach{ p => newLineAndIndent(1) ; s(p) } - val isEmpty = body == EmptyStmt || body == Block(Seq()) - if(!isEmpty) { - newLineNoIndent() // add a new line between port declaration and body - newLineAndIndent(1) ; s(body)(b, indent + 1) - } + newLineNoIndent() // add a new line between port declaration and body + newLineAndIndent(1) ; s(body)(b, indent + 1) case ExtModule(info, name, ports, defname, params) => b ++= "extmodule " ; b ++= name ; b ++= " :" ; s(info) ports.foreach{ p => newLineAndIndent(1) ; s(p) } @@ -214,7 +226,10 @@ object Serializer { // Bounds case UnknownBound => b += '?' case CalcBound(arg) => b ++= "calcb(" ; s(arg) ; b += ')' - case other => b ++= other.serialize + case VarBound(name) => b ++= name + case Open(value) => b ++ "o(" ; b ++= value.toString ; b += ')' + case Closed(value) => b ++ "c(" ; b ++= value.toString ; b += ')' + case other => other.serialize } /** create a new line with the appropriate indent */ @@ -230,7 +245,7 @@ object Serializer { } /** serialize firrtl Expression nodes with a custom separator and the option to include the separator at the end */ - private def s(nodes: Seq[Expression], sep: String, noFinalSep: Boolean = true) + private def s(nodes: Iterable[Expression], sep: String, noFinalSep: Boolean = true) (implicit b: StringBuilder, indent: Int): Unit = { val it = nodes.iterator while(it.hasNext) { @@ -239,20 +254,9 @@ object Serializer { } } - /** serialize firrtl Info nodes with a custom separator and the option to include the separator at the end */ - @inline - private def sInfo(nodes: Seq[Info], sep: String) - (implicit b: StringBuilder, indent: Int): Unit = { - val it = nodes.iterator - while(it.hasNext) { - s(it.next()) - if(it.hasNext) b ++= sep - } - } - /** serialize firrtl Field nodes with a custom separator and the option to include the separator at the end */ @inline - private def sField(nodes: Seq[Field], sep: String) + private def sField(nodes: Iterable[Field], sep: String) (implicit b: StringBuilder, indent: Int): Unit = { val it = nodes.iterator while(it.hasNext) { @@ -262,7 +266,7 @@ object Serializer { } /** serialize BigInts with a custom separator */ - private def s(consts: Seq[BigInt], sep: String)(implicit b: StringBuilder): Unit = { + private def s(consts: Iterable[BigInt], sep: String)(implicit b: StringBuilder): Unit = { val it = consts.iterator while(it.hasNext) { b ++= it.next().toString() diff --git a/src/main/scala/firrtl/passes/memlib/MemIR.scala b/src/main/scala/firrtl/passes/memlib/MemIR.scala index 2781f1e2..3731ea86 100644 --- a/src/main/scala/firrtl/passes/memlib/MemIR.scala +++ b/src/main/scala/firrtl/passes/memlib/MemIR.scala @@ -39,7 +39,7 @@ case class DefAnnotatedMemory( memRef: Option[(String, String)] /* (Module, Mem) */ //pins: Seq[Pin], ) extends Statement with IsDeclaration { - def serialize: String = this.toMem.serialize + override def serialize: String = this.toMem.serialize def mapStmt(f: Statement => Statement): Statement = this def mapExpr(f: Expression => Expression): Statement = this def mapType(f: Type => Type): Statement = this.copy(dataType = f(dataType)) diff --git a/src/test/scala/firrtlTests/fixed/FixedSerializationSpec.scala b/src/test/scala/firrtlTests/fixed/FixedSerializationSpec.scala new file mode 100644 index 00000000..db107cb3 --- /dev/null +++ b/src/test/scala/firrtlTests/fixed/FixedSerializationSpec.scala @@ -0,0 +1,27 @@ +// See LICENSE for license details. + +package firrtlTests +package fixed + +import firrtl.ir +import org.scalatest.flatspec.AnyFlatSpec + +class FixedSerializationSpec extends AnyFlatSpec { + behavior of "FixedType" + + it should "serialize correctly" in { + assert(ir.FixedType(ir.IntWidth(3), ir.IntWidth(2)).serialize == "Fixed<3><<2>>") + assert(ir.FixedType(ir.IntWidth(10), ir.UnknownWidth).serialize == "Fixed<10>") + assert(ir.FixedType(ir.UnknownWidth, ir.IntWidth(-4)).serialize == "Fixed<<-4>>") + assert(ir.FixedType(ir.UnknownWidth, ir.UnknownWidth).serialize == "Fixed") + } + + behavior of "FixedLiteral" + + it should "serialize correctly" in { + assert(ir.FixedLiteral(1, ir.IntWidth(3), ir.IntWidth(2)).serialize == "Fixed<3><<2>>(\"h1\")") + assert(ir.FixedLiteral(1, ir.IntWidth(10), ir.UnknownWidth).serialize == "Fixed<10>(\"h1\")") + assert(ir.FixedLiteral(1, ir.UnknownWidth, ir.IntWidth(-4)).serialize == "Fixed<<-4>>(\"h1\")") + assert(ir.FixedLiteral(1, ir.UnknownWidth, ir.UnknownWidth).serialize == "Fixed(\"h1\")") + } +} |
