diff options
| author | chick | 2020-08-14 19:47:53 -0700 |
|---|---|---|
| committer | Jack Koenig | 2020-08-14 19:47:53 -0700 |
| commit | 6fc742bfaf5ee508a34189400a1a7dbffe3f1cac (patch) | |
| tree | 2ed103ee80b0fba613c88a66af854ae9952610ce /src/main/scala/firrtl/ir | |
| parent | b516293f703c4de86397862fee1897aded2ae140 (diff) | |
All of src/ formatted with scalafmt
Diffstat (limited to 'src/main/scala/firrtl/ir')
| -rw-r--r-- | src/main/scala/firrtl/ir/IR.scala | 869 | ||||
| -rw-r--r-- | src/main/scala/firrtl/ir/Serializer.scala | 247 | ||||
| -rw-r--r-- | src/main/scala/firrtl/ir/StructuralHash.scala | 291 |
3 files changed, 762 insertions, 645 deletions
diff --git a/src/main/scala/firrtl/ir/IR.scala b/src/main/scala/firrtl/ir/IR.scala index 5263d9c0..2536a77e 100644 --- a/src/main/scala/firrtl/ir/IR.scala +++ b/src/main/scala/firrtl/ir/IR.scala @@ -39,41 +39,50 @@ case class FileInfo(escaped: String) extends Info { object FileInfo { @deprecated("Use FileInfo.fromUnEscaped instead. FileInfo.apply will be removed in FIRRTL 1.5.", "FIRRTL 1.4") - def apply(info: StringLit): FileInfo = new FileInfo(escape(info.string)) - def fromEscaped(s: String): FileInfo = new FileInfo(s) - def fromUnescaped(s: String): FileInfo = new FileInfo(escape(s)) + def apply(info: StringLit): FileInfo = new FileInfo(escape(info.string)) + def fromEscaped(s: String): FileInfo = new FileInfo(s) + def fromUnescaped(s: String): FileInfo = new FileInfo(escape(s)) + /** prepends a `\` to: `\`, `\n`, `\t` and `]` */ def escape(s: String): String = EscapeFirrtl.translate(s) + /** removes the `\` in front of `\`, `\n`, `\t` and `]` */ def unescape(s: String): String = UnescapeFirrtl.translate(s) + /** take an already escaped String and do the additional escaping needed for Verilog comment */ def escapedToVerilog(s: String) = EscapedToVerilog.translate(s) // custom `CharSequenceTranslator` for FIRRTL Info String escaping type CharMap = (CharSequence, CharSequence) - private val EscapeFirrtl = new LookupTranslator(Seq[CharMap]( - "\\" -> "\\\\", - "\n" -> "\\n", - "\t" -> "\\t", - "]" -> "\\]" - ).toMap.asJava) - private val UnescapeFirrtl = new LookupTranslator(Seq[CharMap]( - "\\\\" -> "\\", - "\\n" -> "\n", - "\\t" -> "\t", - "\\]" -> "]" - ).toMap.asJava) + private val EscapeFirrtl = new LookupTranslator( + Seq[CharMap]( + "\\" -> "\\\\", + "\n" -> "\\n", + "\t" -> "\\t", + "]" -> "\\]" + ).toMap.asJava + ) + private val UnescapeFirrtl = new LookupTranslator( + Seq[CharMap]( + "\\\\" -> "\\", + "\\n" -> "\n", + "\\t" -> "\t", + "\\]" -> "]" + ).toMap.asJava + ) // EscapeFirrtl + EscapedToVerilog essentially does the same thing as running StringEscapeUtils.unescapeJava private val EscapedToVerilog = new AggregateTranslator( - new LookupTranslator(Seq[CharMap]( - // ] is the one character that firrtl needs to be escaped that does not need to be escaped in - "\\]" -> "]", - "\"" -> "\\\"", - // \n and \t are already escaped - "\b" -> "\\b", - "\f" -> "\\f", - "\r" -> "\\r" - ).toMap.asJava), + new LookupTranslator( + Seq[CharMap]( + // ] is the one character that firrtl needs to be escaped that does not need to be escaped in + "\\]" -> "]", + "\"" -> "\\\"", + // \n and \t are already escaped + "\b" -> "\\b", + "\f" -> "\\f", + "\r" -> "\\r" + ).toMap.asJava + ), JavaUnicodeEscaper.outsideOf(32, 0x7f) ) @@ -81,9 +90,9 @@ object FileInfo { case class MultiInfo(infos: Seq[Info]) extends Info { private def collectStrings(info: Info): Seq[String] = info match { - case f : FileInfo => Seq(f.escaped) - case MultiInfo(seq) => seq flatMap collectStrings - case NoInfo => Seq.empty + case f: FileInfo => Seq(f.escaped) + case MultiInfo(seq) => seq.flatMap(collectStrings) + case NoInfo => Seq.empty } override def toString: String = { val parts = collectStrings(this) @@ -107,12 +116,12 @@ object MultiInfo { // TODO should this be made into an API? private[firrtl] def demux(info: Info): (Info, Info, Info) = info match { case MultiInfo(infos) if infos.lengthCompare(3) == 0 => (infos(0), infos(1), infos(2)) - case other => (other, NoInfo, NoInfo) // if not exactly 3, we don't know what to do + case other => (other, NoInfo, NoInfo) // if not exactly 3, we don't know what to do } - + private def flattenInfo(infos: Seq[Info]): Seq[FileInfo] = infos.flatMap { case NoInfo => Seq() - case f : FileInfo => Seq(f) + case f: FileInfo => Seq(f) case MultiInfo(infos) => flattenInfo(infos) } } @@ -127,6 +136,7 @@ trait IsDeclaration extends HasName with HasInfo case class StringLit(string: String) extends FirrtlNode { import org.apache.commons.text.StringEscapeUtils + /** Returns an escaped and quoted String */ def escape: String = { "\"" + serialize + "\"" @@ -137,26 +147,28 @@ case class StringLit(string: String) extends FirrtlNode { def verilogFormat: StringLit = { StringLit(string.replaceAll("%x", "%h")) } + /** Returns an escaped and quoted String */ def verilogEscape: String = { // normalize to turn things like รถ into o import java.text.Normalizer val normalized = Normalizer.normalize(string, Normalizer.Form.NFD) - val ascii = normalized flatMap StringLit.toASCII + val ascii = normalized.flatMap(StringLit.toASCII) ascii.mkString("\"", "", "\"") } } object StringLit { import org.apache.commons.text.StringEscapeUtils + /** Maps characters to ASCII for Verilog emission */ private def toASCII(char: Char): List[Char] = char match { case nonASCII if !nonASCII.isValidByte => List('?') - case '"' => List('\\', '"') - case '\\' => List('\\', '\\') - case c if c >= ' ' && c <= '~' => List(c) - case '\n' => List('\\', 'n') - case '\t' => List('\\', 't') - case _ => List('?') + case '"' => List('\\', '"') + case '\\' => List('\\', '\\') + case c if c >= ' ' && c <= '~' => List(c) + case '\n' => List('\\', 'n') + case '\t' => List('\\', 't') + case _ => List('?') } /** Create a StringLit from a raw parsed String */ @@ -175,8 +187,8 @@ abstract class PrimOp extends FirrtlNode { def apply(args: Any*): DoPrim = { val groups = args.groupBy { case x: Expression => "exp" - case x: BigInt => "int" - case x: Int => "int" + case x: BigInt => "int" + case x: Int => "int" case other => "other" } val exprs = groups.getOrElse("exp", Nil).collect { @@ -185,11 +197,11 @@ abstract class PrimOp extends FirrtlNode { val consts = groups.getOrElse("int", Nil).map { _ match { case i: BigInt => i - case i: Int => BigInt(i) + case i: Int => BigInt(i) } } groups.get("other") match { - case None => + case None => case Some(x) => sys.error(s"Shouldn't be here: $x") } DoPrim(this, exprs, consts, UnknownType) @@ -198,12 +210,12 @@ abstract class PrimOp extends FirrtlNode { abstract class Expression extends FirrtlNode { def tpe: Type - def mapExpr(f: Expression => Expression): Expression - def mapType(f: Type => Type): Expression - def mapWidth(f: Width => Width): Expression - def foreachExpr(f: Expression => Unit): Unit - def foreachType(f: Type => Unit): Unit - def foreachWidth(f: Width => Unit): Unit + def mapExpr(f: Expression => Expression): Expression + def mapType(f: Type => Type): Expression + def mapWidth(f: Width => Width): Expression + def foreachExpr(f: Expression => Unit): Unit + def foreachType(f: Type => Unit): Unit + def foreachWidth(f: Width => Unit): Unit } /** Represents reference-like expression nodes: SubField, SubIndex, SubAccess and Reference @@ -215,75 +227,92 @@ abstract class Expression extends FirrtlNode { sealed trait RefLikeExpression extends Expression { def flow: Flow } object Reference { + /** Creates a Reference from a Wire */ def apply(wire: DefWire): Reference = Reference(wire.name, wire.tpe, WireKind, UnknownFlow) + /** Creates a Reference from a Register */ def apply(reg: DefRegister): Reference = Reference(reg.name, reg.tpe, RegKind, UnknownFlow) + /** Creates a Reference from a Node */ def apply(node: DefNode): Reference = Reference(node.name, node.value.tpe, NodeKind, SourceFlow) + /** Creates a Reference from a Port */ def apply(port: Port): Reference = Reference(port.name, port.tpe, PortKind, UnknownFlow) + /** Creates a Reference from a DefInstance */ def apply(i: DefInstance): Reference = Reference(i.name, i.tpe, InstanceKind, UnknownFlow) + /** Creates a Reference from a DefMemory */ def apply(mem: DefMemory): Reference = Reference(mem.name, passes.MemPortUtils.memType(mem), MemKind, UnknownFlow) } case class Reference(name: String, tpe: Type = UnknownType, kind: Kind = UnknownKind, flow: Flow = UnknownFlow) - extends Expression with HasName with UseSerializer with RefLikeExpression { - 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 - def foreachExpr(f: Expression => Unit): Unit = () - def foreachType(f: Type => Unit): Unit = f(tpe) - def foreachWidth(f: Width => Unit): Unit = () + extends Expression + with HasName + with UseSerializer + with RefLikeExpression { + 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 + def foreachExpr(f: Expression => Unit): Unit = () + def foreachType(f: Type => Unit): Unit = f(tpe) + def foreachWidth(f: Width => Unit): Unit = () } case class SubField(expr: Expression, name: String, tpe: Type = UnknownType, flow: Flow = UnknownFlow) - extends Expression with HasName with UseSerializer with RefLikeExpression { - 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 - def foreachExpr(f: Expression => Unit): Unit = f(expr) - def foreachType(f: Type => Unit): Unit = f(tpe) - def foreachWidth(f: Width => Unit): Unit = () + extends Expression + with HasName + with UseSerializer + with RefLikeExpression { + 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 + def foreachExpr(f: Expression => Unit): Unit = f(expr) + def foreachType(f: Type => Unit): Unit = f(tpe) + def foreachWidth(f: Width => Unit): Unit = () } case class SubIndex(expr: Expression, value: Int, tpe: Type, flow: Flow = UnknownFlow) - extends Expression with UseSerializer with RefLikeExpression { - 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 - def foreachExpr(f: Expression => Unit): Unit = f(expr) - def foreachType(f: Type => Unit): Unit = f(tpe) - def foreachWidth(f: Width => Unit): Unit = () + extends Expression + with UseSerializer + with RefLikeExpression { + 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 + def foreachExpr(f: Expression => Unit): Unit = f(expr) + def foreachType(f: Type => Unit): Unit = f(tpe) + def foreachWidth(f: Width => Unit): Unit = () } case class SubAccess(expr: Expression, index: Expression, tpe: Type, flow: Flow = UnknownFlow) - extends Expression with UseSerializer with RefLikeExpression { - 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 + extends Expression + with UseSerializer + with RefLikeExpression { + 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 def foreachExpr(f: Expression => Unit): Unit = { f(expr); f(index) } - def foreachType(f: Type => Unit): Unit = f(tpe) + def foreachType(f: Type => Unit): Unit = f(tpe) def foreachWidth(f: Width => Unit): Unit = () } case class Mux(cond: Expression, tval: Expression, fval: Expression, tpe: Type = UnknownType) - extends Expression with UseSerializer { - 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 + extends Expression + with UseSerializer { + 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 def foreachExpr(f: Expression => Unit): Unit = { f(cond); f(tval); f(fval) } - def foreachType(f: Type => Unit): Unit = f(tpe) + def foreachType(f: Type => Unit): Unit = f(tpe) def foreachWidth(f: Width => Unit): Unit = () } case class ValidIf(cond: Expression, value: Expression, tpe: Type) extends Expression with UseSerializer { - 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 + 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 def foreachExpr(f: Expression => Unit): Unit = { f(cond); f(value) } - def foreachType(f: Type => Unit): Unit = f(tpe) + def foreachType(f: Type => Unit): Unit = f(tpe) def foreachWidth(f: Width => Unit): Unit = () } abstract class Literal extends Expression { @@ -292,16 +321,16 @@ abstract class Literal extends Expression { } case class UIntLiteral(value: BigInt, width: Width) extends Literal with UseSerializer { def tpe = UIntType(width) - def mapExpr(f: Expression => Expression): Expression = this - def mapType(f: Type => Type): Expression = this - def mapWidth(f: Width => Width): Expression = UIntLiteral(value, f(width)) - def foreachExpr(f: Expression => Unit): Unit = () - def foreachType(f: Type => Unit): Unit = () - def foreachWidth(f: Width => Unit): Unit = f(width) + def mapExpr(f: Expression => Expression): Expression = this + def mapType(f: Type => Type): Expression = this + def mapWidth(f: Width => Width): Expression = UIntLiteral(value, f(width)) + def foreachExpr(f: Expression => Unit): Unit = () + def foreachType(f: Type => Unit): Unit = () + def foreachWidth(f: Width => Unit): Unit = f(width) } object UIntLiteral { def minWidth(value: BigInt): Width = IntWidth(math.max(value.bitLength, 1)) - def apply(value: BigInt): UIntLiteral = new UIntLiteral(value, minWidth(value)) + def apply(value: BigInt): UIntLiteral = new UIntLiteral(value, minWidth(value)) /** Utility to construct UIntLiterals masked by the width * @@ -314,78 +343,82 @@ object UIntLiteral { } case class SIntLiteral(value: BigInt, width: Width) extends Literal with UseSerializer { def tpe = SIntType(width) - def mapExpr(f: Expression => Expression): Expression = this - def mapType(f: Type => Type): Expression = this - def mapWidth(f: Width => Width): Expression = SIntLiteral(value, f(width)) - def foreachExpr(f: Expression => Unit): Unit = () - def foreachType(f: Type => Unit): Unit = () - def foreachWidth(f: Width => Unit): Unit = f(width) + def mapExpr(f: Expression => Expression): Expression = this + def mapType(f: Type => Type): Expression = this + def mapWidth(f: Width => Width): Expression = SIntLiteral(value, f(width)) + def foreachExpr(f: Expression => Unit): Unit = () + def foreachType(f: Type => Unit): Unit = () + def foreachWidth(f: Width => Unit): Unit = f(width) } object SIntLiteral { def minWidth(value: BigInt): Width = IntWidth(value.bitLength + 1) - def apply(value: BigInt): SIntLiteral = new SIntLiteral(value, minWidth(value)) + def apply(value: BigInt): SIntLiteral = new SIntLiteral(value, minWidth(value)) } case class FixedLiteral(value: BigInt, width: Width, point: Width) extends Literal with UseSerializer { def tpe = FixedType(width, point) - 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)) - def foreachExpr(f: Expression => Unit): Unit = () - def foreachType(f: Type => Unit): Unit = () + 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)) + def foreachExpr(f: Expression => Unit): Unit = () + def foreachType(f: Type => Unit): Unit = () 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 with UseSerializer { - 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 - def foreachExpr(f: Expression => Unit): Unit = args.foreach(f) - def foreachType(f: Type => Unit): Unit = f(tpe) - def foreachWidth(f: Width => Unit): Unit = () + extends Expression + with UseSerializer { + 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 + def foreachExpr(f: Expression => Unit): Unit = args.foreach(f) + def foreachType(f: Type => Unit): Unit = f(tpe) + def foreachWidth(f: Width => Unit): Unit = () } abstract class Statement extends FirrtlNode { - def mapStmt(f: Statement => Statement): Statement - def mapExpr(f: Expression => Expression): Statement - def mapType(f: Type => Type): Statement - def mapString(f: String => String): Statement - def mapInfo(f: Info => Info): Statement - def foreachStmt(f: Statement => Unit): Unit - def foreachExpr(f: Expression => Unit): Unit - def foreachType(f: Type => Unit): Unit - def foreachString(f: String => Unit): Unit - def foreachInfo(f: Info => Unit): Unit + def mapStmt(f: Statement => Statement): Statement + def mapExpr(f: Expression => Expression): Statement + def mapType(f: Type => Type): Statement + def mapString(f: String => String): Statement + def mapInfo(f: Info => Info): Statement + def foreachStmt(f: Statement => Unit): Unit + def foreachExpr(f: Expression => Unit): Unit + def foreachType(f: Type => Unit): Unit + def foreachString(f: String => Unit): Unit + def foreachInfo(f: Info => Unit): Unit } case class DefWire(info: Info, name: String, tpe: Type) extends Statement with IsDeclaration with UseSerializer { - 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)) - def mapString(f: String => String): Statement = DefWire(info, f(name), tpe) - def mapInfo(f: Info => Info): Statement = this.copy(info = f(info)) - def foreachStmt(f: Statement => Unit): Unit = () - def foreachExpr(f: Expression => Unit): Unit = () - def foreachType(f: Type => Unit): Unit = f(tpe) - def foreachString(f: String => Unit): Unit = f(name) - def foreachInfo(f: Info => Unit): Unit = f(info) + 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)) + def mapString(f: String => String): Statement = DefWire(info, f(name), tpe) + def mapInfo(f: Info => Info): Statement = this.copy(info = f(info)) + def foreachStmt(f: Statement => Unit): Unit = () + def foreachExpr(f: Expression => Unit): Unit = () + def foreachType(f: Type => Unit): Unit = f(tpe) + def foreachString(f: String => Unit): Unit = f(name) + def foreachInfo(f: Info => Unit): Unit = f(info) } case class DefRegister( - info: Info, - name: String, - tpe: Type, - clock: Expression, - reset: Expression, - init: Expression) extends Statement with IsDeclaration with UseSerializer { + info: Info, + name: String, + tpe: Type, + clock: Expression, + reset: Expression, + init: Expression) + extends Statement + with IsDeclaration + with UseSerializer { def mapStmt(f: Statement => Statement): Statement = this def mapExpr(f: Expression => Expression): Statement = DefRegister(info, name, tpe, f(clock), f(reset), f(init)) - def mapType(f: Type => Type): Statement = this.copy(tpe = f(tpe)) - def mapString(f: String => String): Statement = this.copy(name = f(name)) - def mapInfo(f: Info => Info): Statement = this.copy(info = f(info)) + def mapType(f: Type => Type): Statement = this.copy(tpe = f(tpe)) + def mapString(f: String => String): Statement = this.copy(name = f(name)) + def mapInfo(f: Info => Info): Statement = this.copy(info = f(info)) def foreachStmt(f: Statement => Unit): Unit = () def foreachExpr(f: Expression => Unit): Unit = { f(clock); f(reset); f(init) } - def foreachType(f: Type => Unit): Unit = f(tpe) + def foreachType(f: Type => Unit): Unit = f(tpe) def foreachString(f: String => Unit): Unit = f(name) - def foreachInfo(f: Info => Unit): Unit = f(info) + def foreachInfo(f: Info => Unit): Unit = f(info) } object DefInstance { @@ -393,17 +426,19 @@ object DefInstance { } case class DefInstance(info: Info, name: String, module: String, tpe: Type = UnknownType) - extends Statement with IsDeclaration with UseSerializer { - 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)) - def mapString(f: String => String): Statement = this.copy(name = f(name)) - def mapInfo(f: Info => Info): Statement = this.copy(f(info)) - def foreachStmt(f: Statement => Unit): Unit = () - def foreachExpr(f: Expression => Unit): Unit = () - def foreachType(f: Type => Unit): Unit = f(tpe) - def foreachString(f: String => Unit): Unit = f(name) - def foreachInfo(f: Info => Unit): Unit = f(info) + extends Statement + with IsDeclaration + with UseSerializer { + 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)) + def mapString(f: String => String): Statement = this.copy(name = f(name)) + def mapInfo(f: Info => Info): Statement = this.copy(f(info)) + def foreachStmt(f: Statement => Unit): Unit = () + def foreachExpr(f: Expression => Unit): Unit = () + def foreachType(f: Type => Unit): Unit = f(tpe) + def foreachString(f: String => Unit): Unit = f(name) + def foreachInfo(f: Info => Unit): Unit = f(info) } object ReadUnderWrite extends Enumeration { @@ -413,56 +448,64 @@ object ReadUnderWrite extends Enumeration { } case class DefMemory( - info: Info, - name: String, - dataType: Type, - depth: BigInt, - writeLatency: Int, - readLatency: Int, - readers: Seq[String], - writers: Seq[String], - readwriters: Seq[String], - // TODO: handle read-under-write - readUnderWrite: ReadUnderWrite.Value = ReadUnderWrite.Undefined) - extends Statement with IsDeclaration with UseSerializer { - 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)) - def mapString(f: String => String): Statement = this.copy(name = f(name)) - def mapInfo(f: Info => Info): Statement = this.copy(info = f(info)) - def foreachStmt(f: Statement => Unit): Unit = () - def foreachExpr(f: Expression => Unit): Unit = () - def foreachType(f: Type => Unit): Unit = f(dataType) - def foreachString(f: String => Unit): Unit = f(name) - def foreachInfo(f: Info => Unit): Unit = f(info) -} -case class DefNode(info: Info, name: String, value: Expression) extends Statement with IsDeclaration with UseSerializer { - 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 - def mapString(f: String => String): Statement = DefNode(info, f(name), value) - def mapInfo(f: Info => Info): Statement = this.copy(info = f(info)) - def foreachStmt(f: Statement => Unit): Unit = () - def foreachExpr(f: Expression => Unit): Unit = f(value) - def foreachType(f: Type => Unit): Unit = () - def foreachString(f: String => Unit): Unit = f(name) - def foreachInfo(f: Info => Unit): Unit = f(info) + info: Info, + name: String, + dataType: Type, + depth: BigInt, + writeLatency: Int, + readLatency: Int, + readers: Seq[String], + writers: Seq[String], + readwriters: Seq[String], + // TODO: handle read-under-write + readUnderWrite: ReadUnderWrite.Value = ReadUnderWrite.Undefined) + extends Statement + with IsDeclaration + with UseSerializer { + 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)) + def mapString(f: String => String): Statement = this.copy(name = f(name)) + def mapInfo(f: Info => Info): Statement = this.copy(info = f(info)) + def foreachStmt(f: Statement => Unit): Unit = () + def foreachExpr(f: Expression => Unit): Unit = () + def foreachType(f: Type => Unit): Unit = f(dataType) + def foreachString(f: String => Unit): Unit = f(name) + def foreachInfo(f: Info => Unit): Unit = f(info) +} +case class DefNode(info: Info, name: String, value: Expression) + extends Statement + with IsDeclaration + with UseSerializer { + 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 + def mapString(f: String => String): Statement = DefNode(info, f(name), value) + def mapInfo(f: Info => Info): Statement = this.copy(info = f(info)) + def foreachStmt(f: Statement => Unit): Unit = () + def foreachExpr(f: Expression => Unit): Unit = f(value) + def foreachType(f: Type => Unit): Unit = () + def foreachString(f: String => Unit): Unit = f(name) + def foreachInfo(f: Info => Unit): Unit = f(info) } case class Conditionally( - info: Info, - pred: Expression, - conseq: Statement, - alt: Statement) extends Statement with HasInfo with UseSerializer { - 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 - def mapString(f: String => String): Statement = this - def mapInfo(f: Info => Info): Statement = this.copy(info = f(info)) + info: Info, + pred: Expression, + conseq: Statement, + alt: Statement) + extends Statement + with HasInfo + with UseSerializer { + 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 + def mapString(f: String => String): Statement = this + def mapInfo(f: Info => Info): Statement = this.copy(info = f(info)) def foreachStmt(f: Statement => Unit): Unit = { f(conseq); f(alt) } - def foreachExpr(f: Expression => Unit): Unit = f(pred) - def foreachType(f: Type => Unit): Unit = () - def foreachString(f: String => Unit): Unit = () - def foreachInfo(f: Info => Unit): Unit = f(info) + def foreachExpr(f: Expression => Unit): Unit = f(pred) + def foreachType(f: Type => Unit): Unit = () + def foreachString(f: String => Unit): Unit = () + def foreachInfo(f: Info => Unit): Unit = f(info) } object Block { @@ -489,94 +532,101 @@ case class Block(stmts: Seq[Statement]) extends Statement with UseSerializer { } Block(res.toSeq) } - def mapExpr(f: Expression => Expression): Statement = this - def mapType(f: Type => Type): Statement = this - def mapString(f: String => String): Statement = this - def mapInfo(f: Info => Info): Statement = this - def foreachStmt(f: Statement => Unit): Unit = stmts.foreach(f) - def foreachExpr(f: Expression => Unit): Unit = () - def foreachType(f: Type => Unit): Unit = () - def foreachString(f: String => Unit): Unit = () - def foreachInfo(f: Info => Unit): Unit = () + def mapExpr(f: Expression => Expression): Statement = this + def mapType(f: Type => Type): Statement = this + def mapString(f: String => String): Statement = this + def mapInfo(f: Info => Info): Statement = this + def foreachStmt(f: Statement => Unit): Unit = stmts.foreach(f) + def foreachExpr(f: Expression => Unit): Unit = () + def foreachType(f: Type => Unit): Unit = () + def foreachString(f: String => Unit): Unit = () + def foreachInfo(f: Info => Unit): Unit = () } case class PartialConnect(info: Info, loc: Expression, expr: Expression) - extends Statement with HasInfo with UseSerializer { - 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 - def mapString(f: String => String): Statement = this - def mapInfo(f: Info => Info): Statement = this.copy(info = f(info)) - def foreachStmt(f: Statement => Unit): Unit = () + extends Statement + with HasInfo + with UseSerializer { + 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 + def mapString(f: String => String): Statement = this + def mapInfo(f: Info => Info): Statement = this.copy(info = f(info)) + def foreachStmt(f: Statement => Unit): Unit = () def foreachExpr(f: Expression => Unit): Unit = { f(loc); f(expr) } - def foreachType(f: Type => Unit): Unit = () + def foreachType(f: Type => Unit): Unit = () def foreachString(f: String => Unit): Unit = () - def foreachInfo(f: Info => Unit): Unit = f(info) -} -case class Connect(info: Info, loc: Expression, expr: Expression) - extends Statement with HasInfo with UseSerializer { - 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 - def mapString(f: String => String): Statement = this - def mapInfo(f: Info => Info): Statement = this.copy(info = f(info)) - def foreachStmt(f: Statement => Unit): Unit = () + def foreachInfo(f: Info => Unit): Unit = f(info) +} +case class Connect(info: Info, loc: Expression, expr: Expression) extends Statement with HasInfo with UseSerializer { + 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 + def mapString(f: String => String): Statement = this + def mapInfo(f: Info => Info): Statement = this.copy(info = f(info)) + def foreachStmt(f: Statement => Unit): Unit = () def foreachExpr(f: Expression => Unit): Unit = { f(loc); f(expr) } - def foreachType(f: Type => Unit): Unit = () + def foreachType(f: Type => Unit): Unit = () def foreachString(f: String => Unit): Unit = () - def foreachInfo(f: Info => Unit): Unit = f(info) + def foreachInfo(f: Info => Unit): Unit = f(info) } case class IsInvalid(info: Info, expr: Expression) extends Statement with HasInfo with UseSerializer { - def mapStmt(f: Statement => Statement): Statement = this - def mapExpr(f: Expression => Expression): Statement = IsInvalid(info, f(expr)) - def mapType(f: Type => Type): Statement = this - def mapString(f: String => String): Statement = this - def mapInfo(f: Info => Info): Statement = this.copy(info = f(info)) - def foreachStmt(f: Statement => Unit): Unit = () - def foreachExpr(f: Expression => Unit): Unit = f(expr) - def foreachType(f: Type => Unit): Unit = () - def foreachString(f: String => Unit): Unit = () - def foreachInfo(f: Info => Unit): Unit = f(info) + def mapStmt(f: Statement => Statement): Statement = this + def mapExpr(f: Expression => Expression): Statement = IsInvalid(info, f(expr)) + def mapType(f: Type => Type): Statement = this + def mapString(f: String => String): Statement = this + def mapInfo(f: Info => Info): Statement = this.copy(info = f(info)) + def foreachStmt(f: Statement => Unit): Unit = () + def foreachExpr(f: Expression => Unit): Unit = f(expr) + def foreachType(f: Type => Unit): Unit = () + def foreachString(f: String => Unit): Unit = () + def foreachInfo(f: Info => Unit): Unit = f(info) } case class Attach(info: Info, exprs: Seq[Expression]) extends Statement with HasInfo with UseSerializer { - 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 - def mapString(f: String => String): Statement = this - def mapInfo(f: Info => Info): Statement = this.copy(info = f(info)) - def foreachStmt(f: Statement => Unit): Unit = () - def foreachExpr(f: Expression => Unit): Unit = exprs.foreach(f) - def foreachType(f: Type => Unit): Unit = () - def foreachString(f: String => Unit): Unit = () - def foreachInfo(f: Info => Unit): Unit = f(info) -} -case class Stop(info: Info, ret: Int, clk: Expression, en: Expression) extends Statement with HasInfo with UseSerializer { - 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 - def mapString(f: String => String): Statement = this - def mapInfo(f: Info => Info): Statement = this.copy(info = f(info)) - def foreachStmt(f: Statement => Unit): Unit = () + 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 + def mapString(f: String => String): Statement = this + def mapInfo(f: Info => Info): Statement = this.copy(info = f(info)) + def foreachStmt(f: Statement => Unit): Unit = () + def foreachExpr(f: Expression => Unit): Unit = exprs.foreach(f) + def foreachType(f: Type => Unit): Unit = () + def foreachString(f: String => Unit): Unit = () + def foreachInfo(f: Info => Unit): Unit = f(info) +} +case class Stop(info: Info, ret: Int, clk: Expression, en: Expression) + extends Statement + with HasInfo + with UseSerializer { + 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 + def mapString(f: String => String): Statement = this + def mapInfo(f: Info => Info): Statement = this.copy(info = f(info)) + def foreachStmt(f: Statement => Unit): Unit = () def foreachExpr(f: Expression => Unit): Unit = { f(clk); f(en) } - def foreachType(f: Type => Unit): Unit = () + def foreachType(f: Type => Unit): Unit = () def foreachString(f: String => Unit): Unit = () - def foreachInfo(f: Info => Unit): Unit = f(info) + def foreachInfo(f: Info => Unit): Unit = f(info) } case class Print( - info: Info, - string: StringLit, - args: Seq[Expression], - clk: Expression, - en: Expression) extends Statement with HasInfo with UseSerializer { - 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 - def mapString(f: String => String): Statement = this - def mapInfo(f: Info => Info): Statement = this.copy(info = f(info)) - def foreachStmt(f: Statement => Unit): Unit = () + info: Info, + string: StringLit, + args: Seq[Expression], + clk: Expression, + en: Expression) + extends Statement + with HasInfo + with UseSerializer { + 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 + def mapString(f: String => String): Statement = this + def mapInfo(f: Info => Info): Statement = this.copy(info = f(info)) + def foreachStmt(f: Statement => Unit): Unit = () def foreachExpr(f: Expression => Unit): Unit = { args.foreach(f); f(clk); f(en) } - def foreachType(f: Type => Unit): Unit = () + def foreachType(f: Type => Unit): Unit = () def foreachString(f: String => Unit): Unit = () - def foreachInfo(f: Info => Unit): Unit = f(info) + def foreachInfo(f: Info => Unit): Unit = f(info) } // formal @@ -587,38 +637,40 @@ object Formal extends Enumeration { } case class Verification( - op: Formal.Value, + op: Formal.Value, info: Info, - clk: Expression, + clk: Expression, pred: Expression, - en: Expression, - msg: StringLit -) extends Statement with HasInfo with UseSerializer { + en: Expression, + msg: StringLit) + extends Statement + with HasInfo + with UseSerializer { def mapStmt(f: Statement => Statement): Statement = this def mapExpr(f: Expression => Expression): Statement = copy(clk = f(clk), pred = f(pred), en = f(en)) - def mapType(f: Type => Type): Statement = this - def mapString(f: String => String): Statement = this - def mapInfo(f: Info => Info): Statement = copy(info = f(info)) + def mapType(f: Type => Type): Statement = this + def mapString(f: String => String): Statement = this + def mapInfo(f: Info => Info): Statement = copy(info = f(info)) def foreachStmt(f: Statement => Unit): Unit = () def foreachExpr(f: Expression => Unit): Unit = { f(clk); f(pred); f(en); } - def foreachType(f: Type => Unit): Unit = () + def foreachType(f: Type => Unit): Unit = () def foreachString(f: String => Unit): Unit = () - def foreachInfo(f: Info => Unit): Unit = f(info) + def foreachInfo(f: Info => Unit): Unit = f(info) } // end formal case object EmptyStmt extends Statement with UseSerializer { - def mapStmt(f: Statement => Statement): Statement = this - def mapExpr(f: Expression => Expression): Statement = this - def mapType(f: Type => Type): Statement = this - def mapString(f: String => String): Statement = this - def mapInfo(f: Info => Info): Statement = this - def foreachStmt(f: Statement => Unit): Unit = () - def foreachExpr(f: Expression => Unit): Unit = () - def foreachType(f: Type => Unit): Unit = () - def foreachString(f: String => Unit): Unit = () - def foreachInfo(f: Info => Unit): Unit = () + def mapStmt(f: Statement => Statement): Statement = this + def mapExpr(f: Expression => Expression): Statement = this + def mapType(f: Type => Type): Statement = this + def mapString(f: String => String): Statement = this + def mapInfo(f: Info => Info): Statement = this + def foreachStmt(f: Statement => Unit): Unit = () + def foreachExpr(f: Expression => Unit): Unit = () + def foreachType(f: Type => Unit): Unit = () + def foreachString(f: String => Unit): Unit = () + def foreachInfo(f: Info => Unit): Unit = () } abstract class Width extends FirrtlNode { @@ -631,14 +683,15 @@ abstract class Width extends FirrtlNode { case _ => UnknownWidth } def max(x: Width): Width = (this, x) match { - case (a: IntWidth, b: IntWidth) => IntWidth(a.width max b.width) + case (a: IntWidth, b: IntWidth) => IntWidth(a.width.max(b.width)) case _ => UnknownWidth } def min(x: Width): Width = (this, x) match { - case (a: IntWidth, b: IntWidth) => IntWidth(a.width min b.width) + case (a: IntWidth, b: IntWidth) => IntWidth(a.width.min(b.width)) case _ => UnknownWidth } } + /** Positive Integer Bit Width of a [[GroundType]] */ object IntWidth { private val maxCached = 1024 @@ -665,7 +718,7 @@ class IntWidth(val width: BigInt) extends Width with Product with UseSerializer override def hashCode = width.toInt override def productPrefix = "IntWidth" override def toString = s"$productPrefix($width)" - def copy(width: BigInt = width) = IntWidth(width) + def copy(width: BigInt = width) = IntWidth(width) def canEqual(that: Any) = that.isInstanceOf[Width] def productArity = 1 def productElement(int: Int) = int match { @@ -693,19 +746,18 @@ case object Flip extends Orientation { /** Field of [[BundleType]] */ case class Field(name: String, flip: Orientation, tpe: Type) extends FirrtlNode with HasName with UseSerializer - /** Bounds of [[IntervalType]] */ trait Bound extends Constraint case object UnknownBound extends Bound { def serialize: String = Serializer.serialize(this) - def map(f: Constraint=>Constraint): Constraint = this + 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 = Serializer.serialize(this) - def map(f: Constraint=>Constraint): Constraint = f(arg) + def map(f: Constraint => Constraint): Constraint = f(arg) override def reduce(): Constraint = arg val children = Vector(arg) } @@ -727,58 +779,60 @@ case class Open(value: BigDecimal) extends IsKnown with Bound { def +(that: IsKnown): IsKnown = Open(value + that.value) def *(that: IsKnown): IsKnown = that match { case Closed(x) if x == 0 => Closed(x) - case _ => Open(value * that.value) + case _ => Open(value * that.value) } - def min(that: IsKnown): IsKnown = if(value < that.value) this else that - def max(that: IsKnown): IsKnown = if(value > that.value) this else that - def neg: IsKnown = Open(-value) - def floor: IsKnown = Open(value.setScale(0, BigDecimal.RoundingMode.FLOOR)) - def pow: IsKnown = if(value.isBinaryDouble) Open(BigDecimal(BigInt(1) << value.toInt)) else sys.error("Shouldn't be here") + def min(that: IsKnown): IsKnown = if (value < that.value) this else that + def max(that: IsKnown): IsKnown = if (value > that.value) this else that + def neg: IsKnown = Open(-value) + def floor: IsKnown = Open(value.setScale(0, BigDecimal.RoundingMode.FLOOR)) + 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: String = Serializer.serialize(this) def +(that: IsKnown): IsKnown = that match { - case Open(x) => Open(value + x) + case Open(x) => Open(value + x) case Closed(x) => Closed(value + x) } def *(that: IsKnown): IsKnown = that match { case IsKnown(x) if value == BigInt(0) => Closed(0) - case Open(x) => Open(value * x) - case Closed(x) => Closed(value * x) + case Open(x) => Open(value * x) + case Closed(x) => Closed(value * x) } - def min(that: IsKnown): IsKnown = if(value <= that.value) this else that - def max(that: IsKnown): IsKnown = if(value >= that.value) this else that - def neg: IsKnown = Closed(-value) + def min(that: IsKnown): IsKnown = if (value <= that.value) this else that + def max(that: IsKnown): IsKnown = if (value >= that.value) this else that + def neg: IsKnown = Closed(-value) def floor: IsKnown = Closed(value.setScale(0, BigDecimal.RoundingMode.FLOOR)) - def pow: IsKnown = if(value.isBinaryDouble) Closed(BigDecimal(BigInt(1) << value.toInt)) else sys.error("Shouldn't be here") + def pow: IsKnown = + if (value.isBinaryDouble) Closed(BigDecimal(BigInt(1) << value.toInt)) else sys.error("Shouldn't be here") } /** Types of [[FirrtlNode]] */ abstract class Type extends FirrtlNode { - def mapType(f: Type => Type): Type - def mapWidth(f: Width => Width): Type - def foreachType(f: Type => Unit): Unit - def foreachWidth(f: Width => Unit): Unit + def mapType(f: Type => Type): Type + def mapWidth(f: Width => Width): Type + def foreachType(f: Type => Unit): Unit + def foreachWidth(f: Width => Unit): Unit } abstract class GroundType extends Type { val width: Width - def mapType(f: Type => Type): Type = this + def mapType(f: Type => Type): Type = this def foreachType(f: Type => Unit): Unit = () } object GroundType { def unapply(ground: GroundType): Option[Width] = Some(ground.width) } abstract class AggregateType extends Type { - def mapWidth(f: Width => Width): Type = this - def foreachWidth(f: Width => Unit): Unit = () + def mapWidth(f: Width => Width): Type = this + def foreachWidth(f: Width => Unit): Unit = () } case class UIntType(width: Width) extends GroundType with UseSerializer { - def mapWidth(f: Width => Width): Type = UIntType(f(width)) - def foreachWidth(f: Width => Unit): Unit = f(width) + def mapWidth(f: Width => Width): Type = UIntType(f(width)) + def foreachWidth(f: Width => Unit): Unit = f(width) } case class SIntType(width: Width) extends GroundType with UseSerializer { - def mapWidth(f: Width => Width): Type = SIntType(f(width)) - def foreachWidth(f: Width => Unit): Unit = f(width) + 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 with UseSerializer { def mapWidth(f: Width => Width): Type = FixedType(f(width), f(point)) @@ -790,21 +844,21 @@ case class IntervalType(lower: Bound, upper: Bound, point: Width) extends Ground case Open(l) => s"(${dec2string(l)}, " case Closed(l) => s"[${dec2string(l)}, " case UnknownBound => s"[?, " - case _ => s"[?, " + case _ => s"[?, " } val upperString = upper match { case Open(u) => s"${dec2string(u)})" case Closed(u) => s"${dec2string(u)}]" case UnknownBound => s"?]" - case _ => s"?]" + case _ => s"?]" } val bounds = (lower, upper) match { case (k1: IsKnown, k2: IsKnown) => lowerString + upperString case _ => "" } val pointString = point match { - case IntWidth(i) => "." + i.toString - case _ => "" + case IntWidth(i) => "." + i.toString + case _ => "" } "Interval" + bounds + pointString } @@ -813,35 +867,43 @@ case class IntervalType(lower: Bound, upper: Bound, point: Width) extends Ground private def precision: Option[BigDecimal] = point match { case IntWidth(width) => val bp = width.toInt - if(bp >= 0) Some(BigDecimal(1) / BigDecimal(BigInt(1) << bp)) else Some(BigDecimal(BigInt(1) << -bp)) + if (bp >= 0) Some(BigDecimal(1) / BigDecimal(BigInt(1) << bp)) else Some(BigDecimal(BigInt(1) << -bp)) case other => None } def min: Option[BigDecimal] = (lower, precision) match { - case (Open(a), Some(prec)) => a / prec match { - case x if trim(x).isWhole => Some(a + prec) // add precision for open lower bound i.e. (-4 -> [3 for bp = 0 - case x => Some(x.setScale(0, CEILING) * prec) // Deal with unrepresentable bound representations (finite BP) -- new closed form l > original l - } + case (Open(a), Some(prec)) => + a / prec match { + case x if trim(x).isWhole => Some(a + prec) // add precision for open lower bound i.e. (-4 -> [3 for bp = 0 + case x => + Some( + x.setScale(0, CEILING) * prec + ) // Deal with unrepresentable bound representations (finite BP) -- new closed form l > original l + } case (Closed(a), Some(prec)) => Some((a / prec).setScale(0, CEILING) * prec) - case other => None + case other => None } def max: Option[BigDecimal] = (upper, precision) match { - case (Open(a), Some(prec)) => a / prec match { - case x if trim(x).isWhole => Some(a - prec) // subtract precision for open upper bound - case x => Some(x.setScale(0, FLOOR) * prec) - } + case (Open(a), Some(prec)) => + a / prec match { + case x if trim(x).isWhole => Some(a - prec) // subtract precision for open upper bound + case x => Some(x.setScale(0, FLOOR) * prec) + } case (Closed(a), Some(prec)) => Some((a / prec).setScale(0, FLOOR) * prec) } def minAdjusted: Option[BigInt] = min.map(_ * BigDecimal(BigInt(1) << bp) match { case x if trim(x).isWhole | x.doubleValue == 0.0 => x.toBigInt - case x => sys.error(s"MinAdjusted should be a whole number: $x. Min is $min. BP is $bp. Precision is $precision. Lower is ${lower}.") + case x => + sys.error( + s"MinAdjusted should be a whole number: $x. Min is $min. BP is $bp. Precision is $precision. Lower is ${lower}." + ) }) def maxAdjusted: Option[BigInt] = max.map(_ * BigDecimal(BigInt(1) << bp) match { case x if trim(x).isWhole => x.toBigInt - case x => sys.error(s"MaxAdjusted should be a whole number: $x") + case x => sys.error(s"MaxAdjusted should be a whole number: $x") }) /** If bounds are known, calculates the width, otherwise returns UnknownWidth */ @@ -854,48 +916,48 @@ case class IntervalType(lower: Bound, upper: Bound, point: Width) extends Ground /** If bounds are known, returns a sequence of all possible values inside this interval */ lazy val range: Option[Seq[BigDecimal]] = (lower, upper, point) match { case (l: IsKnown, u: IsKnown, p: IntWidth) => - if(min.get > max.get) Some(Nil) else Some(Range.BigDecimal(min.get, max.get, precision.get)) + if (min.get > max.get) Some(Nil) else Some(Range.BigDecimal(min.get, max.get, precision.get)) case _ => None } - override def mapWidth(f: Width => Width): Type = this.copy(point = f(point)) - override def foreachWidth(f: Width => Unit): Unit = f(point) + override def mapWidth(f: Width => Width): Type = this.copy(point = f(point)) + override def foreachWidth(f: Width => Unit): Unit = f(point) } case class BundleType(fields: Seq[Field]) extends AggregateType with UseSerializer { 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) } + 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 with UseSerializer { - def mapType(f: Type => Type): Type = this.copy(tpe = f(tpe)) + def mapType(f: Type => Type): Type = this.copy(tpe = f(tpe)) def foreachType(f: Type => Unit): Unit = f(tpe) } case object ClockType extends GroundType with UseSerializer { val width = IntWidth(1) - def mapWidth(f: Width => Width): Type = this - def foreachWidth(f: Width => Unit): Unit = () + 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 with UseSerializer { val width = IntWidth(1) - def mapWidth(f: Width => Width): Type = this - def foreachWidth(f: Width => Unit): Unit = () + def mapWidth(f: Width => Width): Type = this + def foreachWidth(f: Width => Unit): Unit = () } case object AsyncResetType extends GroundType with UseSerializer { val width = IntWidth(1) - def mapWidth(f: Width => Width): Type = this - def foreachWidth(f: Width => Unit): Unit = () + def mapWidth(f: Width => Width): Type = this + def foreachWidth(f: Width => Unit): Unit = () } case class AnalogType(width: Width) extends GroundType with UseSerializer { - def mapWidth(f: Width => Width): Type = AnalogType(f(width)) - def foreachWidth(f: Width => Unit): Unit = f(width) + def mapWidth(f: Width => Width): Type = AnalogType(f(width)) + def foreachWidth(f: Width => Unit): Unit = f(width) } case object UnknownType extends Type with UseSerializer { - def mapType(f: Type => Type): Type = this - def mapWidth(f: Width => Width): Type = this - def foreachType(f: Type => Unit): Unit = () - def foreachWidth(f: Width => Unit): Unit = () + def mapType(f: Type => Type): Type = this + def mapWidth(f: Width => Width): Type = this + def foreachType(f: Type => Unit): Unit = () + def foreachWidth(f: Width => Unit): Unit = () } /** [[Port]] Direction */ @@ -909,11 +971,14 @@ case object Output extends Direction { /** [[DefModule]] Port */ case class Port( - info: Info, - name: String, - direction: Direction, - tpe: Type) extends FirrtlNode with IsDeclaration with UseSerializer { - def mapType(f: Type => Type): Port = Port(info, name, direction, f(tpe)) + info: Info, + name: String, + direction: Direction, + tpe: Type) + extends FirrtlNode + with IsDeclaration + with UseSerializer { + def mapType(f: Type => Type): Port = Port(info, name, direction, f(tpe)) def mapString(f: String => String): Port = Port(info, f(name), direction, tpe) } @@ -921,12 +986,16 @@ case class Port( sealed abstract class Param extends FirrtlNode { def name: String } + /** Integer (of any width) Parameter */ case class IntParam(name: String, value: BigInt) extends Param with UseSerializer + /** IEEE Double Precision Parameter (for Verilog real) */ case class DoubleParam(name: String, value: Double) extends Param with UseSerializer + /** String Parameter */ case class StringParam(name: String, value: StringLit) extends Param with UseSerializer + /** Raw String Parameter * Useful for Verilog type parameters * @note Firrtl doesn't guarantee anything about this String being legal in any backend @@ -935,59 +1004,65 @@ case class RawStringParam(name: String, value: String) extends Param with UseSer /** Base class for modules */ abstract class DefModule extends FirrtlNode with IsDeclaration { - val info : Info - val name : String - val ports : Seq[Port] - def mapStmt(f: Statement => Statement): DefModule - def mapPort(f: Port => Port): DefModule - def mapString(f: String => String): DefModule - def mapInfo(f: Info => Info): DefModule - def foreachStmt(f: Statement => Unit): Unit - def foreachPort(f: Port => Unit): Unit - def foreachString(f: String => Unit): Unit - def foreachInfo(f: Info => Unit): Unit + val info: Info + val name: String + val ports: Seq[Port] + def mapStmt(f: Statement => Statement): DefModule + def mapPort(f: Port => Port): DefModule + def mapString(f: String => String): DefModule + def mapInfo(f: Info => Info): DefModule + def foreachStmt(f: Statement => Unit): Unit + def foreachPort(f: Port => Unit): Unit + def foreachString(f: String => Unit): Unit + def foreachInfo(f: Info => Unit): Unit } + /** Internal Module * * An instantiable hardware block */ case class Module(info: Info, name: String, ports: Seq[Port], body: Statement) extends DefModule with UseSerializer { - 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)) - def mapInfo(f: Info => Info): DefModule = this.copy(f(info)) - def foreachStmt(f: Statement => Unit): Unit = f(body) - def foreachPort(f: Port => Unit): Unit = ports.foreach(f) - def foreachString(f: String => Unit): Unit = f(name) - def foreachInfo(f: Info => Unit): Unit = f(info) + 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)) + def mapInfo(f: Info => Info): DefModule = this.copy(f(info)) + def foreachStmt(f: Statement => Unit): Unit = f(body) + def foreachPort(f: Port => Unit): Unit = ports.foreach(f) + def foreachString(f: String => Unit): Unit = f(name) + def foreachInfo(f: Info => Unit): Unit = f(info) } + /** External Module * * Generally used for Verilog black boxes * @param defname Defined name of the external module (ie. the name Firrtl will emit) */ case class ExtModule( - info: Info, - name: String, - ports: Seq[Port], - defname: String, - params: Seq[Param]) extends DefModule with UseSerializer { - 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)) - def mapInfo(f: Info => Info): DefModule = this.copy(f(info)) - def foreachStmt(f: Statement => Unit): Unit = () - def foreachPort(f: Port => Unit): Unit = ports.foreach(f) - def foreachString(f: String => Unit): Unit = f(name) - def foreachInfo(f: Info => Unit): Unit = f(info) + info: Info, + name: String, + ports: Seq[Port], + defname: String, + params: Seq[Param]) + extends DefModule + with UseSerializer { + 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)) + def mapInfo(f: Info => Info): DefModule = this.copy(f(info)) + def foreachStmt(f: Statement => Unit): Unit = () + def foreachPort(f: Port => Unit): Unit = ports.foreach(f) + def foreachString(f: String => Unit): Unit = f(name) + def foreachInfo(f: Info => Unit): Unit = f(info) } case class Circuit(info: Info, modules: Seq[DefModule], main: String) - extends FirrtlNode with HasInfo with UseSerializer { - 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)) - def foreachModule(f: DefModule => Unit): Unit = modules foreach f - def foreachString(f: String => Unit): Unit = f(main) - def foreachInfo(f: Info => Unit): Unit = f(info) + extends FirrtlNode + with HasInfo + with UseSerializer { + 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)) + def foreachModule(f: DefModule => Unit): Unit = modules.foreach(f) + def foreachString(f: String => Unit): Unit = f(main) + def foreachInfo(f: Info => Unit): Unit = f(info) } diff --git a/src/main/scala/firrtl/ir/Serializer.scala b/src/main/scala/firrtl/ir/Serializer.scala index ea304cf3..bf9a57c1 100644 --- a/src/main/scala/firrtl/ir/Serializer.scala +++ b/src/main/scala/firrtl/ir/Serializer.scala @@ -13,19 +13,19 @@ object Serializer { val builder = new StringBuilder() val indent = 0 node match { - case n : Info => s(n)(builder, indent) - case n : StringLit => s(n)(builder, indent) - case n : Expression => s(n)(builder, indent) - case n : Statement => s(n)(builder, indent) - case n : Width => s(n)(builder, indent) - case n : Orientation => s(n)(builder, indent) - case n : Field => s(n)(builder, indent) - case n : Type => s(n)(builder, indent) - case n : Direction => s(n)(builder, indent) - case n : Port => s(n)(builder, indent) - case n : Param => s(n)(builder, indent) - case n : DefModule => s(n)(builder, indent) - case n : Circuit => s(n)(builder, indent) + case n: Info => s(n)(builder, indent) + case n: StringLit => s(n)(builder, indent) + case n: Expression => s(n)(builder, indent) + case n: Statement => s(n)(builder, indent) + case n: Width => s(n)(builder, indent) + case n: Orientation => s(n)(builder, indent) + case n: Field => s(n)(builder, indent) + case n: Type => s(n)(builder, indent) + case n: Direction => s(n)(builder, indent) + case n: Port => s(n)(builder, indent) + case n: Param => s(n)(builder, indent) + case n: DefModule => s(n)(builder, indent) + case n: Circuit => s(n)(builder, indent) } builder.toString() } @@ -39,16 +39,16 @@ object Serializer { private def flattenInfo(infos: Seq[Info]): Seq[FileInfo] = infos.flatMap { case NoInfo => Seq() - case f : FileInfo => Seq(f) + case f: FileInfo => Seq(f) case MultiInfo(infos) => flattenInfo(infos) } private def s(node: Info)(implicit b: StringBuilder, indent: Int): Unit = node match { - case f : FileInfo => b ++= " @[" ; b ++= f.escaped ; b ++= "]" + case f: FileInfo => b ++= " @["; b ++= f.escaped; b ++= "]" case NoInfo => // empty string - case m : MultiInfo => + case m: MultiInfo => val infos = m.flatten - if(infos.nonEmpty) { + if (infos.nonEmpty) { val lastId = infos.length - 1 b ++= " @[" infos.zipWithIndex.foreach { case (f, i) => b ++= f.escaped; if (i < lastId) b += ' ' } @@ -61,103 +61,113 @@ object Serializer { private def s(node: Expression)(implicit b: StringBuilder, indent: Int): Unit = node match { case Reference(name, _, _, _) => b ++= name case DoPrim(op, args, consts, _) => - b ++= op.toString ; b += '(' ; s(args, ", ", consts.isEmpty) ; s(consts, ", ") ; b += ')' + b ++= op.toString; b += '('; s(args, ", ", consts.isEmpty); s(consts, ", "); b += ')' case UIntLiteral(value, width) => - b ++= "UInt" ; s(width) ; b ++= "(\"h" ; b ++= value.toString(16) ; b ++= "\")" - case SubField(expr, name, _, _) => s(expr) ; b += '.' ; b ++= name - case SubIndex(expr, value, _, _) => s(expr) ; b += '[' ; b ++= value.toString ; b += ']' - case SubAccess(expr, index, _, _) => s(expr) ; b += '[' ; s(index) ; b += ']' + b ++= "UInt"; s(width); b ++= "(\"h"; b ++= value.toString(16); b ++= "\")" + case SubField(expr, name, _, _) => s(expr); b += '.'; b ++= name + case SubIndex(expr, value, _, _) => s(expr); b += '['; b ++= value.toString; b += ']' + case SubAccess(expr, index, _, _) => s(expr); b += '['; s(index); b += ']' case Mux(cond, tval, fval, _) => - b ++= "mux(" ; s(cond) ; b ++= ", " ; s(tval) ; b ++= ", " ; s(fval) ; b += ')' - case ValidIf(cond, value, _) => b ++= "validif(" ; s(cond) ; b ++= ", " ; s(value) ; b += ')' + b ++= "mux("; s(cond); b ++= ", "; s(tval); b ++= ", "; s(fval); b += ')' + case ValidIf(cond, value, _) => b ++= "validif("; s(cond); b ++= ", "; s(value); b += ')' case SIntLiteral(value, width) => - b ++= "SInt" ; s(width) ; b ++= "(\"h" ; b ++= value.toString(16) ; b ++= "\")" + b ++= "SInt"; s(width); b ++= "(\"h"; b ++= value.toString(16); b ++= "\")" case FixedLiteral(value, width, point) => - b ++= "Fixed" ; s(width) ; sPoint(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" + case firrtl.WVoid => b ++= "VOID" + case firrtl.WInvalid => b ++= "INVALID" case firrtl.EmptyExpression => b ++= "EMPTY" } private def s(node: Statement)(implicit b: StringBuilder, indent: Int): Unit = node match { - case DefNode(info, name, value) => b ++= "node " ; b ++= name ; b ++= " = " ; s(value) ; s(info) - case Connect(info, loc, expr) => s(loc) ; b ++= " <= " ; s(expr) ; s(info) + case DefNode(info, name, value) => b ++= "node "; b ++= name; b ++= " = "; s(value); s(info) + case Connect(info, loc, expr) => s(loc); b ++= " <= "; s(expr); s(info) case Conditionally(info, pred, conseq, alt) => - b ++= "when " ; s(pred) ; b ++= " :" ; s(info) - newLineAndIndent(1) ; s(conseq)(b, indent + 1) - if(alt != EmptyStmt) { - newLineAndIndent() ; b ++= "else :" - newLineAndIndent(1) ; s(alt)(b, indent + 1) + b ++= "when "; s(pred); b ++= " :"; s(info) + newLineAndIndent(1); s(conseq)(b, indent + 1) + if (alt != EmptyStmt) { + newLineAndIndent(); b ++= "else :" + newLineAndIndent(1); s(alt)(b, indent + 1) } - case EmptyStmt => b ++= "skip" + case EmptyStmt => b ++= "skip" case Block(Seq()) => b ++= "skip" case Block(stmts) => val it = stmts.iterator - while(it.hasNext) { + while (it.hasNext) { s(it.next) - if(it.hasNext) newLineAndIndent() + if (it.hasNext) newLineAndIndent() } case Stop(info, ret, clk, en) => - b ++= "stop(" ; s(clk) ; b ++= ", " ; s(en) ; b ++= ", " ; b ++= ret.toString ; b += ')' ; s(info) + b ++= "stop("; s(clk); b ++= ", "; s(en); b ++= ", "; b ++= ret.toString; b += ')'; s(info) case Print(info, string, args, clk, en) => - b ++= "printf(" ; s(clk) ; b ++= ", " ; s(en) ; b ++= ", " ; b ++= string.escape - if(args.nonEmpty) b ++= ", " ; s(args, ", ") ; b += ')' ; s(info) - case IsInvalid(info, expr) => s(expr) ; b ++= " is invalid" ; s(info) - case DefWire(info, name, tpe) => b ++= "wire " ; b ++= name ; b ++= " : " ; s(tpe) ; s(info) + b ++= "printf("; s(clk); b ++= ", "; s(en); b ++= ", "; b ++= string.escape + if (args.nonEmpty) b ++= ", "; s(args, ", "); b += ')'; s(info) + case IsInvalid(info, expr) => s(expr); b ++= " is invalid"; s(info) + case DefWire(info, name, tpe) => b ++= "wire "; b ++= name; b ++= " : "; s(tpe); s(info) case DefRegister(info, name, tpe, clock, reset, init) => - b ++= "reg " ; b ++= name ; b ++= " : " ; s(tpe) ; b ++= ", " ; s(clock) ; b ++= " with :" ; newLineAndIndent(1) - b ++= "reset => (" ; s(reset) ; b ++= ", " ; s(init) ; b += ')' ; s(info) - case DefInstance(info, name, module, _) => b ++= "inst " ; b ++= name ; b ++= " of " ; b ++= module ; s(info) - case DefMemory(info, name, dataType, depth, writeLatency, readLatency, readers, writers, - readwriters, readUnderWrite) => - b ++= "mem " ; b ++= name ; b ++= " :" ; s(info) ; newLineAndIndent(1) - b ++= "data-type => " ; s(dataType) ; newLineAndIndent(1) - b ++= "depth => " ; b ++= depth.toString() ; newLineAndIndent(1) - b ++= "read-latency => " ; b ++= readLatency.toString ; newLineAndIndent(1) - b ++= "write-latency => " ; b ++= writeLatency.toString ; newLineAndIndent(1) - readers.foreach{ r => b ++= "reader => " ; b ++= r ; newLineAndIndent(1) } - writers.foreach{ w => b ++= "writer => " ; b ++= w ; newLineAndIndent(1) } - readwriters.foreach{ r => b ++= "readwriter => " ; b ++= r ; newLineAndIndent(1) } - b ++= "read-under-write => " ; b ++= readUnderWrite.toString - case PartialConnect(info, loc, expr) => s(loc) ; b ++= " <- " ; s(expr) ; s(info) - case Attach(info, exprs) => + b ++= "reg "; b ++= name; b ++= " : "; s(tpe); b ++= ", "; s(clock); b ++= " with :"; newLineAndIndent(1) + b ++= "reset => ("; s(reset); b ++= ", "; s(init); b += ')'; s(info) + case DefInstance(info, name, module, _) => b ++= "inst "; b ++= name; b ++= " of "; b ++= module; s(info) + case DefMemory( + info, + name, + dataType, + depth, + writeLatency, + readLatency, + readers, + writers, + readwriters, + readUnderWrite + ) => + b ++= "mem "; b ++= name; b ++= " :"; s(info); newLineAndIndent(1) + b ++= "data-type => "; s(dataType); newLineAndIndent(1) + b ++= "depth => "; b ++= depth.toString(); newLineAndIndent(1) + b ++= "read-latency => "; b ++= readLatency.toString; newLineAndIndent(1) + b ++= "write-latency => "; b ++= writeLatency.toString; newLineAndIndent(1) + readers.foreach { r => b ++= "reader => "; b ++= r; newLineAndIndent(1) } + writers.foreach { w => b ++= "writer => "; b ++= w; newLineAndIndent(1) } + readwriters.foreach { r => b ++= "readwriter => "; b ++= r; newLineAndIndent(1) } + b ++= "read-under-write => "; b ++= readUnderWrite.toString + case PartialConnect(info, loc, expr) => s(loc); b ++= " <- "; s(expr); s(info) + case Attach(info, exprs) => // exprs should never be empty since the attach statement takes *at least* two signals according to the spec - b ++= "attach (" ; s(exprs, ", ") ; b += ')' ; s(info) + b ++= "attach ("; s(exprs, ", "); b += ')'; s(info) case Verification(op, info, clk, pred, en, msg) => - b ++= op.toString ; b += '(' ; s(List(clk, pred, en), ", ", false) ; b ++= msg.escape - b += ')' ; s(info) + b ++= op.toString; b += '('; s(List(clk, pred, en), ", ", false); b ++= msg.escape + b += ')'; s(info) // WIR case firrtl.CDefMemory(info, name, tpe, size, seq, readUnderWrite) => - if(seq) b ++= "smem " else b ++= "cmem " - b ++= name ; b ++= " : " ; s(tpe) ; b ++= " [" ; b ++= size.toString() ; b += ']' ; s(info) + if (seq) b ++= "smem " else b ++= "cmem " + b ++= name; b ++= " : "; s(tpe); b ++= " ["; b ++= size.toString(); b += ']'; s(info) 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) + 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) + 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 { 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 += '>' + case UnknownWidth => // empty string + case CalcWidth(arg) => b ++= "calcw("; s(arg); b += ')' + 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 ++= ">>" + 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 " + case Flip => b ++= "flip " } private def s(node: Field)(implicit b: StringBuilder, indent: Int): Unit = node match { @@ -169,19 +179,19 @@ object Serializer { case UIntType(width: Width) => b ++= "UInt"; s(width) case SIntType(width: Width) => b ++= "SInt"; s(width) 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" - case ResetType => b ++= "Reset" - case AsyncResetType => b ++= "AsyncReset" - case AnalogType(width) => b ++= "Analog"; s(width) - case UnknownType => b += '?' + case BundleType(fields) => b ++= "{ "; sField(fields, ", "); b += '}' + case VectorType(tpe, size) => s(tpe); b += '['; b ++= size.toString; b += ']' + case ClockType => b ++= "Clock" + case ResetType => b ++= "Reset" + case AsyncResetType => b ++= "AsyncReset" + case AnalogType(width) => b ++= "Analog"; s(width) + case UnknownType => b += '?' // the IntervalType has a complicated custom serialization method which does not recurse case i: IntervalType => b ++= i.serialize } private def s(node: Direction)(implicit b: StringBuilder, indent: Int): Unit = node match { - case Input => b ++= "input" + case Input => b ++= "input" case Output => b ++= "output" } @@ -191,50 +201,50 @@ object Serializer { } private def s(node: Param)(implicit b: StringBuilder, indent: Int): Unit = node match { - case IntParam(name, value) => b ++= "parameter " ; b ++= name ; b ++= " = " ; b ++= value.toString - case DoubleParam(name, value) => b ++= "parameter " ; b ++= name ; b ++= " = " ; b ++= value.toString - case StringParam(name, value) => b ++= "parameter " ; b ++= name ; b ++= " = " ; b ++= value.escape + case IntParam(name, value) => b ++= "parameter "; b ++= name; b ++= " = "; b ++= value.toString + case DoubleParam(name, value) => b ++= "parameter "; b ++= name; b ++= " = "; b ++= value.toString + case StringParam(name, value) => b ++= "parameter "; b ++= name; b ++= " = "; b ++= value.escape case RawStringParam(name, value) => - b ++= "parameter " ; b ++= name ; b ++= " = " - b += '\'' ; b ++= value.replace("'", "\\'") ; b += '\'' + b ++= "parameter "; b ++= name; b ++= " = " + b += '\''; b ++= value.replace("'", "\\'"); b += '\'' } private def s(node: DefModule)(implicit b: StringBuilder, indent: Int): Unit = node match { case Module(info, name, ports, body) => - b ++= "module " ; b ++= name ; b ++= " :" ; s(info) - ports.foreach{ p => newLineAndIndent(1) ; s(p) } + b ++= "module "; b ++= name; b ++= " :"; s(info) + ports.foreach { p => newLineAndIndent(1); s(p) } newLineNoIndent() // add a new line between port declaration and body - newLineAndIndent(1) ; s(body)(b, indent + 1) + 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) } - newLineAndIndent(1) ; b ++= "defname = " ; b ++= defname - params.foreach{ p => newLineAndIndent(1) ; s(p) } + b ++= "extmodule "; b ++= name; b ++= " :"; s(info) + ports.foreach { p => newLineAndIndent(1); s(p) } + newLineAndIndent(1); b ++= "defname = "; b ++= defname + params.foreach { p => newLineAndIndent(1); s(p) } } private def s(node: Circuit)(implicit b: StringBuilder, indent: Int): Unit = node match { case Circuit(info, modules, main) => - b ++= "circuit " ; b ++= main ; b ++= " :" ; s(info) - if(modules.nonEmpty) { - newLineAndIndent(1) ; s(modules.head)(b, indent + 1) - modules.drop(1).foreach{m => newLineNoIndent(); newLineAndIndent(1) ; s(m)(b, indent + 1) } + b ++= "circuit "; b ++= main; b ++= " :"; s(info) + if (modules.nonEmpty) { + newLineAndIndent(1); s(modules.head)(b, indent + 1) + modules.drop(1).foreach { m => newLineNoIndent(); newLineAndIndent(1); s(m)(b, indent + 1) } } } // serialize constraints private def s(const: Constraint)(implicit b: StringBuilder): Unit = const match { // Bounds - case UnknownBound => b += '?' - case CalcBound(arg) => b ++= "calcb(" ; s(arg) ; b += ')' + case UnknownBound => b += '?' + case CalcBound(arg) => b ++= "calcb("; s(arg); b += ')' 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 + 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 */ private def newLineAndIndent(inc: Int = 0)(implicit b: StringBuilder, indent: Int): Unit = { - b += NewLine ; doIndent(inc) + b += NewLine; doIndent(inc) } private def newLineNoIndent()(implicit b: StringBuilder): Unit = b += NewLine @@ -245,32 +255,37 @@ object Serializer { } /** serialize firrtl Expression nodes with a custom separator and the option to include the separator at the end */ - private def s(nodes: Iterable[Expression], sep: String, noFinalSep: Boolean = true) - (implicit b: StringBuilder, indent: Int): Unit = { + private def s( + nodes: Iterable[Expression], + sep: String, + noFinalSep: Boolean = true + )( + implicit b: StringBuilder, + indent: Int + ): Unit = { val it = nodes.iterator - while(it.hasNext) { + while (it.hasNext) { s(it.next()) - if(!noFinalSep || it.hasNext) b ++= sep + if (!noFinalSep || 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: Iterable[Field], sep: String) - (implicit b: StringBuilder, indent: Int): Unit = { + private def sField(nodes: Iterable[Field], sep: String)(implicit b: StringBuilder, indent: Int): Unit = { val it = nodes.iterator - while(it.hasNext) { + while (it.hasNext) { s(it.next()) - if(it.hasNext) b ++= sep + if (it.hasNext) b ++= sep } } /** serialize BigInts with a custom separator */ private def s(consts: Iterable[BigInt], sep: String)(implicit b: StringBuilder): Unit = { val it = consts.iterator - while(it.hasNext) { + while (it.hasNext) { b ++= it.next().toString() - if(it.hasNext) b ++= sep + if (it.hasNext) b ++= sep } } } diff --git a/src/main/scala/firrtl/ir/StructuralHash.scala b/src/main/scala/firrtl/ir/StructuralHash.scala index 1b38dec1..f1ed91f3 100644 --- a/src/main/scala/firrtl/ir/StructuralHash.scala +++ b/src/main/scala/firrtl/ir/StructuralHash.scala @@ -24,7 +24,7 @@ import scala.collection.mutable * of the same circuit and thus all modules referred to in DefInstance are the same. * * @author Kevin Laeufer <laeufer@cs.berkeley.edu> - * */ + */ object StructuralHash { def sha256(node: DefModule, moduleRename: String => String = identity): HashCode = { val m = MessageDigest.getInstance(SHA256) @@ -59,19 +59,19 @@ object StructuralHash { private val SHA256 = "SHA-256" private def hash(node: FirrtlNode, h: Hasher, rename: String => String): Unit = node match { - case n : Expression => new StructuralHash(h, rename).hash(n) - case n : Statement => new StructuralHash(h, rename).hash(n) - case n : Type => new StructuralHash(h, rename).hash(n) - case n : Width => new StructuralHash(h, rename).hash(n) - case n : Orientation => new StructuralHash(h, rename).hash(n) - case n : Field => new StructuralHash(h, rename).hash(n) - case n : Direction => new StructuralHash(h, rename).hash(n) - case n : Port => new StructuralHash(h, rename).hash(n) - case n : Param => new StructuralHash(h, rename).hash(n) - case _ : Info => throw new RuntimeException("The structural hash of Info is meaningless.") - case n : DefModule => new StructuralHash(h, rename).hash(n) - case n : Circuit => hashCircuit(n, h, rename) - case n : StringLit => h.update(n.toString) + case n: Expression => new StructuralHash(h, rename).hash(n) + case n: Statement => new StructuralHash(h, rename).hash(n) + case n: Type => new StructuralHash(h, rename).hash(n) + case n: Width => new StructuralHash(h, rename).hash(n) + case n: Orientation => new StructuralHash(h, rename).hash(n) + case n: Field => new StructuralHash(h, rename).hash(n) + case n: Direction => new StructuralHash(h, rename).hash(n) + case n: Port => new StructuralHash(h, rename).hash(n) + case n: Param => new StructuralHash(h, rename).hash(n) + case _: Info => throw new RuntimeException("The structural hash of Info is meaningless.") + case n: DefModule => new StructuralHash(h, rename).hash(n) + case n: Circuit => hashCircuit(n, h, rename) + case n: StringLit => h.update(n.toString) } private def hashModuleAndPortNames(m: DefModule, h: Hasher, rename: String => String): Unit = { @@ -85,9 +85,9 @@ object StructuralHash { } private def hashPortTypeName(tpe: Type, h: String => Unit): Unit = tpe match { - case BundleType(fields) => fields.foreach{ f => h(f.name) ; hashPortTypeName(f.tpe, h) } - case VectorType(vt, _) => hashPortTypeName(vt, h) - case _ => // ignore ground types since they do not have field names nor sub-types + case BundleType(fields) => fields.foreach { f => h(f.name); hashPortTypeName(f.tpe, h) } + case VectorType(vt, _) => hashPortTypeName(vt, h) + case _ => // ignore ground types since they do not have field names nor sub-types } private def hashCircuit(c: Circuit, h: Hasher, rename: String => String): Unit = { @@ -101,8 +101,8 @@ object StructuralHash { } } - private val primOpToId = PrimOps.builtinPrimOps.zipWithIndex.map{ case (op, i) => op -> (-i -1).toByte }.toMap - assert(primOpToId.values.max == -1, "PrimOp nodes use ids -1 ... -50") + private val primOpToId = PrimOps.builtinPrimOps.zipWithIndex.map { case (op, i) => op -> (-i - 1).toByte }.toMap + assert(primOpToId.values.max == -1, "PrimOp nodes use ids -1 ... -50") assert(primOpToId.values.min >= -50, "PrimOp nodes use ids -1 ... -50") private def primOp(p: PrimOp): Byte = primOpToId(p) @@ -110,7 +110,7 @@ object StructuralHash { private def verificationOp(op: Formal.Value): Byte = op match { case Formal.Assert => 0 case Formal.Assume => 1 - case Formal.Cover => 2 + case Formal.Cover => 2 } } @@ -129,14 +129,14 @@ private class MDHashCode(code: Array[Byte]) extends HashCode { /** Generic hashing interface which allows us to use different backends to trade of speed and collision resistance */ private trait Hasher { - def update(b: Byte): Unit - def update(i: Int): Unit - def update(l: Long): Unit - def update(s: String): Unit + def update(b: Byte): Unit + def update(i: Int): Unit + def update(l: Long): Unit + def update(s: String): Unit def update(b: Array[Byte]): Unit def update(d: Double): Unit = update(java.lang.Double.doubleToRawLongBits(d)) - def update(i: BigInt): Unit = update(i.toByteArray) - def update(b: Boolean): Unit = if(b) update(1.toByte) else update(0.toByte) + def update(i: BigInt): Unit = update(i.toByteArray) + def update(b: Boolean): Unit = if (b) update(1.toByte) else update(0.toByte) def update(i: BigDecimal): Unit = { // this might be broken, tried to borrow some code from BigDecimal.computeHashCode val temp = i.bigDecimal.stripTrailingZeros() @@ -149,14 +149,14 @@ private trait Hasher { private class MessageDigestHasher(m: MessageDigest) extends Hasher { override def update(b: Byte): Unit = m.update(b) override def update(i: Int): Unit = { - m.update(((i >> 0) & 0xff).toByte) - m.update(((i >> 8) & 0xff).toByte) + m.update(((i >> 0) & 0xff).toByte) + m.update(((i >> 8) & 0xff).toByte) m.update(((i >> 16) & 0xff).toByte) m.update(((i >> 24) & 0xff).toByte) } override def update(l: Long): Unit = { - m.update(((l >> 0) & 0xff).toByte) - m.update(((l >> 8) & 0xff).toByte) + m.update(((l >> 0) & 0xff).toByte) + m.update(((l >> 8) & 0xff).toByte) m.update(((l >> 16) & 0xff).toByte) m.update(((l >> 24) & 0xff).toByte) m.update(((l >> 32) & 0xff).toByte) @@ -165,42 +165,47 @@ private class MessageDigestHasher(m: MessageDigest) extends Hasher { m.update(((l >> 56) & 0xff).toByte) } // the encoding of the bytes should not matter as long as we are on the same platform - override def update(s: String): Unit = m.update(s.getBytes()) + override def update(s: String): Unit = m.update(s.getBytes()) override def update(b: Array[Byte]): Unit = m.update(b) } -class StructuralHash private(h: Hasher, renameModule: String => String) { +class StructuralHash private (h: Hasher, renameModule: String => String) { // replace identifiers with incrementing integers private val nameToInt = mutable.HashMap[String, Int]() private var nameCounter: Int = 0 - @inline private def n(name: String): Unit = hash(nameToInt.getOrElseUpdate(name, { - val ii = nameCounter - nameCounter = nameCounter + 1 - ii - })) + @inline private def n(name: String): Unit = hash( + nameToInt.getOrElseUpdate( + name, { + val ii = nameCounter + nameCounter = nameCounter + 1 + ii + } + ) + ) // internal convenience methods - @inline private def id(b: Byte): Unit = h.update(b) - @inline private def hash(i: Int): Unit = h.update(i) - @inline private def hash(b: Boolean): Unit = h.update(b) - @inline private def hash(d: Double): Unit = h.update(d) - @inline private def hash(i: BigInt): Unit = h.update(i) + @inline private def id(b: Byte): Unit = h.update(b) + @inline private def hash(i: Int): Unit = h.update(i) + @inline private def hash(b: Boolean): Unit = h.update(b) + @inline private def hash(d: Double): Unit = h.update(d) + @inline private def hash(i: BigInt): Unit = h.update(i) @inline private def hash(i: BigDecimal): Unit = h.update(i) - @inline private def hash(s: String): Unit = h.update(s) + @inline private def hash(s: String): Unit = h.update(s) private def hash(node: Expression): Unit = node match { - case Reference(name, _, _, _) => id(0) ; n(name) + case Reference(name, _, _, _) => id(0); n(name) case DoPrim(op, args, consts, _) => // no need to hash the number of arguments or constants since that is implied by the op - id(1) ; h.update(StructuralHash.primOp(op)) ; args.foreach(hash) ; consts.foreach(hash) - case UIntLiteral(value, width) => id(2) ; hash(value) ; hash(width) + id(1); h.update(StructuralHash.primOp(op)); args.foreach(hash); consts.foreach(hash) + case UIntLiteral(value, width) => id(2); hash(value); hash(width) // We hash bundles as if fields are accessed by their index. // Thus we need to also hash field accesses that way. // This has the side-effect that `x.y` might hash to the same value as `z.r`, for example if the // types are `x: {y: UInt<1>, ...}` and `z: {r: UInt<1>, ...}` respectively. // They do not hash to the same value if the type of `z` is e.g., `z: {..., r: UInt<1>, ...}` // as that would have the `r` field at a different index. - case SubField(expr, name, _, _) => id(3) ; hash(expr) + case SubField(expr, name, _, _) => + id(3); hash(expr) // find field index and hash that instead of the field name val fields = expr.tpe match { case b: BundleType => b.fields @@ -209,93 +214,115 @@ class StructuralHash private(h: Hasher, renameModule: String => String) { } val index = fields.zipWithIndex.find(_._1.name == name).map(_._2).get hash(index) - case SubIndex(expr, value, _, _) => id(4) ; hash(expr) ; hash(value) - case SubAccess(expr, index, _, _) => id(5) ; hash(expr) ; hash(index) - case Mux(cond, tval, fval, _) => id(6) ; hash(cond) ; hash(tval) ; hash(fval) - case ValidIf(cond, value, _) => id(7) ; hash(cond) ; hash(value) - case SIntLiteral(value, width) => id(8) ; hash(value) ; hash(width) - case FixedLiteral(value, width, point) => id(9) ; hash(value) ; hash(width) ; hash(point) + case SubIndex(expr, value, _, _) => id(4); hash(expr); hash(value) + case SubAccess(expr, index, _, _) => id(5); hash(expr); hash(index) + case Mux(cond, tval, fval, _) => id(6); hash(cond); hash(tval); hash(fval) + case ValidIf(cond, value, _) => id(7); hash(cond); hash(value) + case SIntLiteral(value, width) => id(8); hash(value); hash(width) + case FixedLiteral(value, width, point) => id(9); hash(value); hash(width); hash(point) // WIR - case firrtl.WVoid => id(10) - case firrtl.WInvalid => id(11) + case firrtl.WVoid => id(10) + case firrtl.WInvalid => id(11) case firrtl.EmptyExpression => id(12) // VRandom is used in the Emitter - case firrtl.VRandom(width) => id(13) ; hash(width) + case firrtl.VRandom(width) => id(13); hash(width) // ids 14 ... 19 are reserved for future Expression nodes } private def hash(node: Statement): Unit = node match { // all info fields are ignore - case DefNode(_, name, value) => id(20) ; n(name) ; hash(value) - case Connect(_, loc, expr) => id(21) ; hash(loc) ; hash(expr) + case DefNode(_, name, value) => id(20); n(name); hash(value) + case Connect(_, loc, expr) => id(21); hash(loc); hash(expr) // we place the unique id 23 between conseq and alt to distinguish between them in case conseq is empty // we place the unique id 24 after alt to distinguish between alt and the next statement in case alt is empty - case Conditionally(_, pred, conseq, alt) => id(22) ; hash(pred) ; hash(conseq) ; id(23) ; hash(alt) ; id(24) - case EmptyStmt => // empty statements are ignored - case Block(stmts) => stmts.foreach(hash) // block structure is ignored - case Stop(_, ret, clk, en) => id(25) ; hash(ret) ; hash(clk) ; hash(en) - case Print(_, string, args, clk, en) => + case Conditionally(_, pred, conseq, alt) => id(22); hash(pred); hash(conseq); id(23); hash(alt); id(24) + case EmptyStmt => // empty statements are ignored + case Block(stmts) => stmts.foreach(hash) // block structure is ignored + case Stop(_, ret, clk, en) => id(25); hash(ret); hash(clk); hash(en) + case Print(_, string, args, clk, en) => // the string is part of the side effect and thus part of the circuit behavior - id(26) ; hash(string.string) ; hash(args.length) ; args.foreach(hash) ; hash(clk) ; hash(en) - case IsInvalid(_, expr) => id(27) ; hash(expr) - case DefWire(_, name, tpe) => id(28) ; n(name) ; hash(tpe) + id(26); hash(string.string); hash(args.length); args.foreach(hash); hash(clk); hash(en) + case IsInvalid(_, expr) => id(27); hash(expr) + case DefWire(_, name, tpe) => id(28); n(name); hash(tpe) case DefRegister(_, name, tpe, clock, reset, init) => - id(29) ; n(name) ; hash(tpe) ; hash(clock) ; hash(reset) ; hash(init) + id(29); n(name); hash(tpe); hash(clock); hash(reset); hash(init) case DefInstance(_, name, module, _) => // Module is in the global namespace which is why we cannot replace it with a numeric id. // However, it might have been renamed as part of the dedup consolidation. - id(30) ; n(name) ; hash(renameModule(module)) + id(30); n(name); hash(renameModule(module)) // descriptions on statements are ignores case firrtl.DescribedStmt(_, stmt) => hash(stmt) - case DefMemory(_, name, dataType, depth, writeLatency, readLatency, readers, writers, - readwriters, readUnderWrite) => - id(30) ; n(name) ; hash(dataType) ; hash(depth) ; hash(writeLatency) ; hash(readLatency) - hash(readers.length) ; readers.foreach(hash) - hash(writers.length) ; writers.foreach(hash) - hash(readwriters.length) ; readwriters.foreach(hash) + case DefMemory( + _, + name, + dataType, + depth, + writeLatency, + readLatency, + readers, + writers, + readwriters, + readUnderWrite + ) => + id(30); n(name); hash(dataType); hash(depth); hash(writeLatency); hash(readLatency) + hash(readers.length); readers.foreach(hash) + hash(writers.length); writers.foreach(hash) + hash(readwriters.length); readwriters.foreach(hash) hash(readUnderWrite) - case PartialConnect(_, loc, expr) => id(31) ; hash(loc) ; hash(expr) - case Attach(_, exprs) => id(32) ; hash(exprs.length) ; exprs.foreach(hash) + case PartialConnect(_, loc, expr) => id(31); hash(loc); hash(expr) + case Attach(_, exprs) => id(32); hash(exprs.length); exprs.foreach(hash) // WIR case firrtl.CDefMemory(_, name, tpe, size, seq, readUnderWrite) => - id(33) ; n(name) ; hash(tpe); hash(size) ; hash(seq) ; hash(readUnderWrite) + id(33); n(name); hash(tpe); hash(size); hash(seq); hash(readUnderWrite) case firrtl.CDefMPort(_, name, _, mem, exps, direction) => // the type of the MPort depends only on the memory (in well types firrtl) and can thus be ignored - id(34) ; n(name) ; n(mem) ; hash(exps.length) ; exps.foreach(hash) ; hash(direction) + id(34); n(name); n(mem); hash(exps.length); exps.foreach(hash); hash(direction) // DefAnnotatedMemory from MemIR.scala - case firrtl.passes.memlib.DefAnnotatedMemory(_, name, dataType, depth, writeLatency, readLatency, readers, writers, - readwriters, readUnderWrite, maskGran, memRef) => - id(35) ; n(name) ; hash(dataType) ; hash(depth) ; hash(writeLatency) ; hash(readLatency) - hash(readers.length) ; readers.foreach(hash) - hash(writers.length) ; writers.foreach(hash) - hash(readwriters.length) ; readwriters.foreach(hash) + case firrtl.passes.memlib.DefAnnotatedMemory( + _, + name, + dataType, + depth, + writeLatency, + readLatency, + readers, + writers, + readwriters, + readUnderWrite, + maskGran, + memRef + ) => + id(35); n(name); hash(dataType); hash(depth); hash(writeLatency); hash(readLatency) + hash(readers.length); readers.foreach(hash) + hash(writers.length); writers.foreach(hash) + hash(readwriters.length); readwriters.foreach(hash) hash(readUnderWrite.toString) - hash(maskGran.size) ; maskGran.foreach(hash) - hash(memRef.size) ; memRef.foreach{ case (a, b) => hash(a) ; hash(b) } + hash(maskGran.size); maskGran.foreach(hash) + hash(memRef.size); memRef.foreach { case (a, b) => hash(a); hash(b) } case Verification(op, _, clk, pred, en, msg) => - id(36) ; hash(StructuralHash.verificationOp(op)) ; hash(clk) ; hash(pred) ; hash(en) ; hash(msg.string) + id(36); hash(StructuralHash.verificationOp(op)); hash(clk); hash(pred); hash(en); hash(msg.string) // ids 37 ... 39 are reserved for future Statement nodes } // ReadUnderWrite is never used in place of a FirrtlNode and thus we can start a new id namespace private def hash(ruw: ReadUnderWrite.Value): Unit = ruw match { - case ReadUnderWrite.New => id(0) - case ReadUnderWrite.Old => id(1) + case ReadUnderWrite.New => id(0) + case ReadUnderWrite.Old => id(1) case ReadUnderWrite.Undefined => id(2) } private def hash(node: Width): Unit = node match { - case IntWidth(width) => id(40) ; hash(width) - case UnknownWidth => id(41) - case CalcWidth(arg) => id(42) ; hash(arg) + case IntWidth(width) => id(40); hash(width) + case UnknownWidth => id(41) + case CalcWidth(arg) => id(42); hash(arg) // we are hashing the name of the `VarWidth` instead of using `n` since these Vars exist in a different namespace - case VarWidth(name) => id(43) ; hash(name) + case VarWidth(name) => id(43); hash(name) // ids 44 + 45 are reserved for future Width nodes } private def hash(node: Orientation): Unit = node match { case Default => id(46) - case Flip => id(47) + case Flip => id(47) } private def hash(node: Field): Unit = { @@ -306,81 +333,81 @@ class StructuralHash private(h: Hasher, renameModule: String => String) { // has been used in the Dedup pass for a long time. // This position-based notion of equality requires us to replace field names with field indexes when hashing // SubField accesses. - id(48) ; hash(node.flip) ; hash(node.tpe) + id(48); hash(node.flip); hash(node.tpe) } private def hash(node: Type): Unit = node match { // Types - case UIntType(width: Width) => id(50) ; hash(width) - case SIntType(width: Width) => id(51) ; hash(width) - case FixedType(width, point) => id(52) ; hash(width) ; hash(point) - case BundleType(fields) => id(53) ; hash(fields.length) ; fields.foreach(hash) - case VectorType(tpe, size) => id(54) ; hash(tpe) ; hash(size) - case ClockType => id(55) - case ResetType => id(56) - case AsyncResetType => id(57) - case AnalogType(width) => id(58) ; hash(width) - case UnknownType => id(59) - case IntervalType(lower, upper, point) => id(60) ; hash(lower) ; hash(upper) ; hash(point) + case UIntType(width: Width) => id(50); hash(width) + case SIntType(width: Width) => id(51); hash(width) + case FixedType(width, point) => id(52); hash(width); hash(point) + case BundleType(fields) => id(53); hash(fields.length); fields.foreach(hash) + case VectorType(tpe, size) => id(54); hash(tpe); hash(size) + case ClockType => id(55) + case ResetType => id(56) + case AsyncResetType => id(57) + case AnalogType(width) => id(58); hash(width) + case UnknownType => id(59) + case IntervalType(lower, upper, point) => id(60); hash(lower); hash(upper); hash(point) // ids 61 ... 65 are reserved for future Type nodes } private def hash(node: Direction): Unit = node match { - case Input => id(66) + case Input => id(66) case Output => id(67) } private def hash(node: Port): Unit = { - id(68) ; n(node.name) ; hash(node.direction) ; hash(node.tpe) + id(68); n(node.name); hash(node.direction); hash(node.tpe) } private def hash(node: Param): Unit = node match { - case IntParam(name, value) => id(70) ; n(name) ; hash(value) - case DoubleParam(name, value) => id(71) ; n(name) ; hash(value) - case StringParam(name, value) => id(72) ; n(name) ; hash(value.string) - case RawStringParam(name, value) => id(73) ; n(name) ; hash(value) + case IntParam(name, value) => id(70); n(name); hash(value) + case DoubleParam(name, value) => id(71); n(name); hash(value) + case StringParam(name, value) => id(72); n(name); hash(value.string) + case RawStringParam(name, value) => id(73); n(name); hash(value) // id 74 is reserved for future use } private def hash(node: DefModule): Unit = node match { // the module name is ignored since it does not affect module functionality case Module(_, _name, ports, body) => - id(75) ; hash(ports.length) ; ports.foreach(hash) ; hash(body) + id(75); hash(ports.length); ports.foreach(hash); hash(body) // the module name is ignored since it does not affect module functionality case ExtModule(_, name, ports, defname, params) => - id(76) ; hash(ports.length) ; ports.foreach(hash) ; hash(defname) - hash(params.length) ; params.foreach(hash) + id(76); hash(ports.length); ports.foreach(hash); hash(defname) + hash(params.length); params.foreach(hash) } // id 127 is reserved for Circuit nodes private def hash(d: firrtl.MPortDir): Unit = d match { - case firrtl.MInfer => id(-70) - case firrtl.MRead => id(-71) - case firrtl.MWrite => id(-72) + case firrtl.MInfer => id(-70) + case firrtl.MRead => id(-71) + case firrtl.MWrite => id(-72) case firrtl.MReadWrite => id(-73) } private def hash(c: firrtl.constraint.Constraint): Unit = c match { case b: Bound => hash(b) /* uses ids -80 ... -84 */ case firrtl.constraint.IsAdd(known, maxs, mins, others) => - id(-85) ; hash(known.nonEmpty) ; known.foreach(hash) - hash(maxs.length) ; maxs.foreach(hash) - hash(mins.length) ; mins.foreach(hash) - hash(others.length) ; others.foreach(hash) - case firrtl.constraint.IsFloor(child, dummyArg) => id(-86) ; hash(child) ; hash(dummyArg) - case firrtl.constraint.IsKnown(decimal) => id(-87) ; hash(decimal) - case firrtl.constraint.IsNeg(child, dummyArg) => id(-88) ; hash(child) ; hash(dummyArg) - case firrtl.constraint.IsPow(child, dummyArg) => id(-89) ; hash(child) ; hash(dummyArg) - case firrtl.constraint.IsVar(str) => id(-90) ; n(str) + id(-85); hash(known.nonEmpty); known.foreach(hash) + hash(maxs.length); maxs.foreach(hash) + hash(mins.length); mins.foreach(hash) + hash(others.length); others.foreach(hash) + case firrtl.constraint.IsFloor(child, dummyArg) => id(-86); hash(child); hash(dummyArg) + case firrtl.constraint.IsKnown(decimal) => id(-87); hash(decimal) + case firrtl.constraint.IsNeg(child, dummyArg) => id(-88); hash(child); hash(dummyArg) + case firrtl.constraint.IsPow(child, dummyArg) => id(-89); hash(child); hash(dummyArg) + case firrtl.constraint.IsVar(str) => id(-90); n(str) } private def hash(b: Bound): Unit = b match { case UnknownBound => id(-80) - case CalcBound(arg) => id(-81) ; hash(arg) + case CalcBound(arg) => id(-81); hash(arg) // we are hashing the name of the `VarBound` instead of using `n` since these Vars exist in a different namespace - case VarBound(name) => id(-82) ; hash(name) - case Open(value) => id(-83) ; hash(value) - case Closed(value) => id(-84) ; hash(value) + case VarBound(name) => id(-82); hash(name) + case Open(value) => id(-83); hash(value) + case Closed(value) => id(-84); hash(value) } -}
\ No newline at end of file +} |
