aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/firrtl/Utils.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/scala/firrtl/Utils.scala')
-rw-r--r--src/main/scala/firrtl/Utils.scala243
1 files changed, 165 insertions, 78 deletions
diff --git a/src/main/scala/firrtl/Utils.scala b/src/main/scala/firrtl/Utils.scala
index 916408bc..4220e07f 100644
--- a/src/main/scala/firrtl/Utils.scala
+++ b/src/main/scala/firrtl/Utils.scala
@@ -2,77 +2,94 @@
/* TODO
* - Adopt style more similar to Chisel3 Emitter?
+ * - Find way to have generic map function instead of mapE and mapS under Stmt implicits
*/
package firrtl
import scala.collection.mutable.StringBuilder
+import java.io.PrintWriter
+import Primops._
+//import scala.reflect.runtime.universe._
object Utils {
-
- implicit class BigIntUtils(bi: BigInt){
- def serialize(): String =
- "\"h0" + bi.toString(16) + "\""
- }
-
- implicit class PrimOpUtils(op: PrimOp) {
- def serialize(): String = {
- op match {
- case Add => "add"
- case Sub => "sub"
- case Addw => "addw"
- case Subw => "subw"
- case Mul => "mul"
- case Div => "div"
- case Mod => "mod"
- case Quo => "quo"
- case Rem => "rem"
- case Lt => "lt"
- case Leq => "leq"
- case Gt => "gt"
- case Geq => "geq"
- case Eq => "eq"
- case Neq => "neq"
- case Mux => "mux"
- case Pad => "pad"
- case AsUInt => "asUInt"
- case AsSInt => "asSInt"
- case Shl => "shl"
- case Shr => "shr"
- case Dshl => "dshl"
- case Dshr => "dshr"
- case Cvt => "cvt"
- case Neg => "neg"
- case Not => "not"
- case And => "and"
- case Or => "or"
- case Xor => "xor"
- case Andr => "andr"
- case Orr => "orr"
- case Xorr => "xorr"
- case Cat => "cat"
- case Bit => "bit"
- case Bits => "bits"
- }
+
+ // Is there a more elegant way to do this?
+ private type FlagMap = Map[Symbol, Boolean]
+ private val FlagMap = Map[Symbol, Boolean]().withDefaultValue(false)
+
+ def debug(node: AST)(implicit flags: FlagMap): String = {
+ if (!flags.isEmpty) {
+ var str = ""
+ if (flags('types)) {
+ val tpe = node.getType
+ if( tpe != UnknownType ) str += s"@<t:${tpe.wipeWidth.serialize}>"
+ }
+ str
}
+ else {
+ ""
+ }
+ }
+
+ implicit class BigIntUtils(bi: BigInt){
+ def serialize(implicit flags: FlagMap = FlagMap): String =
+ "\"h" + bi.toString(16) + "\""
+ }
+
+ implicit class ASTUtils(ast: AST) {
+ def getType(): Type =
+ ast match {
+ case e: Exp => e.getType
+ case s: Stmt => s.getType
+ //case f: Field => f.getType
+ case t: Type => t.getType
+ case p: Port => p.getType
+ case _ => UnknownType
+ }
+ }
+
+ implicit class PrimopUtils(op: Primop) {
+ def serialize(implicit flags: FlagMap = FlagMap): String = op.getString
}
implicit class ExpUtils(exp: Exp) {
- def serialize(): String =
- exp match {
- case v: UIntValue => s"UInt<${v.width}>(${v.value.serialize})"
- case v: SIntValue => s"SInt<${v.width}>(${v.value.serialize})"
+ def serialize(implicit flags: FlagMap = FlagMap): String = {
+ val ret = exp match {
+ case v: UIntValue => s"UInt${v.width.serialize}(${v.value.serialize})"
+ case v: SIntValue => s"SInt${v.width.serialize}(${v.value.serialize})"
case r: Ref => r.name
case s: Subfield => s"${s.exp.serialize}.${s.name}"
- case s: Subindex => s"${s.exp.serialize}[${s.value}]"
- case p: DoPrimOp =>
+ case s: Index => s"${s.exp.serialize}[${s.value}]"
+ case p: DoPrimop =>
s"${p.op.serialize}(" + (p.args.map(_.serialize) ++ p.consts.map(_.toString)).mkString(", ") + ")"
}
+ ret + debug(exp)
+ }
+
+ def map(f: Exp => Exp): Exp =
+ exp match {
+ case s: Subfield => Subfield(f(s.exp), s.name, s.tpe)
+ case i: Index => Index(f(i.exp), i.value, i.tpe)
+ case p: DoPrimop => DoPrimop(p.op, p.args.map(f), p.consts, p.tpe)
+ case e: Exp => e
+ }
+
+ def getType(): Type = {
+ exp match {
+ case v: UIntValue => UIntType(UnknownWidth)
+ case v: SIntValue => SIntType(UnknownWidth)
+ case r: Ref => r.tpe
+ case s: Subfield => s.tpe
+ case i: Index => i.tpe
+ case p: DoPrimop => p.tpe
+ }
+ }
}
// AccessorDir
implicit class AccessorDirUtils(dir: AccessorDir) {
- def serialize(): String =
+ def serialize(implicit flags: FlagMap = FlagMap): String =
dir match {
case Infer => "infer"
case Read => "read"
@@ -81,10 +98,41 @@ object Utils {
}
}
+ // Some Scala implicit magic to solve type erasure on Stmt map function overloading
+ private trait StmtMagnet {
+ def map(stmt: Stmt): Stmt
+ }
+ private object StmtMagnet {
+ implicit def forStmt(f: Stmt => Stmt) = new StmtMagnet {
+ override def map(stmt: Stmt): Stmt =
+ stmt match {
+ case w: When => When(w.info, w.pred, f(w.conseq), f(w.alt))
+ case b: Block => Block(b.stmts.map(f))
+ case s: Stmt => s
+ }
+ }
+ implicit def forExp(f: Exp => Exp) = new StmtMagnet {
+ override def map(stmt: Stmt): Stmt =
+ stmt match {
+ case r: DefReg => DefReg(r.info, r.name, r.tpe, f(r.clock), f(r.reset))
+ case m: DefMemory => DefMemory(m.info, m.name, m.seq, m.tpe, f(m.clock))
+ case i: DefInst => DefInst(i.info, i.name, f(i.module))
+ case n: DefNode => DefNode(n.info, n.name, f(n.value))
+ case a: DefAccessor => DefAccessor(a.info, a.name, a.dir, f(a.source), f(a.index))
+ case o: OnReset => OnReset(o.info, f(o.lhs), f(o.rhs))
+ case c: Connect => Connect(c.info, f(c.lhs), f(c.rhs))
+ case b: BulkConnect => BulkConnect(b.info, f(b.lhs), f(b.rhs))
+ case w: When => When(w.info, f(w.pred), w.conseq, w.alt)
+ case a: Assert => Assert(a.info, f(a.pred))
+ case s: Stmt => s
+ }
+ }
+ }
implicit class StmtUtils(stmt: Stmt) {
- def serialize(): String =
- stmt match {
+ def serialize(implicit flags: FlagMap = FlagMap): String =
+ {
+ var ret = stmt match {
case w: DefWire => s"wire ${w.name} : ${w.tpe.serialize}"
case r: DefReg => s"reg ${r.name} : ${r.tpe.serialize}, ${r.clock.serialize}, ${r.reset.serialize}"
case m: DefMemory => (if(m.seq) "smem" else "cmem") +
@@ -109,78 +157,117 @@ object Utils {
case b: Block => {
val s = new StringBuilder
b.stmts.foreach { s ++= newline ++ _.serialize }
- s.result
- }
+ s.result + debug(b)
+ }
case a: Assert => s"assert ${a.pred.serialize}"
case EmptyStmt => "skip"
}
+ ret + debug(stmt)
+ }
+
+ // Using implicit types to allow overloading of function type to map, see StmtMagnet above
+ def map[T](f: T => T)(implicit magnet: (T => T) => StmtMagnet): Stmt = magnet(f).map(stmt)
+
+ def getType(): Type =
+ stmt match {
+ case s: DefWire => s.tpe
+ case s: DefReg => s.tpe
+ case s: DefMemory => s.tpe
+ case s: DefPoison => s.tpe
+ case _ => UnknownType
+ }
}
implicit class WidthUtils(w: Width) {
- def serialize(): String =
- w match {
- case UnknownWidth => "?"
- case w: IntWidth => w.width.toString
+ def serialize(implicit flags: FlagMap = FlagMap): String = {
+ val s = w match {
+ case UnknownWidth => "" //"?"
+ case w: IntWidth => s"<${w.width.toString}>"
}
+ s + debug(w)
+ }
}
implicit class FieldDirUtils(dir: FieldDir) {
- def serialize(): String =
- dir match {
- case Reverse => "flip "
+ def serialize(implicit flags: FlagMap = FlagMap): String = {
+ val s = dir match {
+ case Reverse => "flip"
case Default => ""
}
+ s + debug(dir)
+ }
}
implicit class FieldUtils(field: Field) {
- def serialize(): String =
- s"${field.dir.serialize} ${field.name} : ${field.tpe.serialize}"
+ def serialize(implicit flags: FlagMap = FlagMap): String =
+ s"${field.dir.serialize} ${field.name} : ${field.tpe.serialize}" + debug(field)
+
+ def getType(): Type = field.tpe
}
implicit class TypeUtils(t: Type) {
- def serialize(): String = {
+ def serialize(implicit flags: FlagMap = FlagMap): String = {
val commas = ", " // for mkString in BundleType
- t match {
+ val s = t match {
case ClockType => "Clock"
- case UnknownType => "UnknownType"
- case t: UIntType => s"UInt<${t.width.serialize}>"
- case t: SIntType => s"SInt<${t.width.serialize}>"
- case t: BundleType => s"{ ${t.fields.map(_.serialize).mkString(commas)} }"
+ //case UnknownType => "UnknownType"
+ case UnknownType => "?"
+ case t: UIntType => s"UInt${t.width.serialize}"
+ case t: SIntType => s"SInt${t.width.serialize}"
+ case t: BundleType => s"{${t.fields.map(_.serialize).mkString(commas)}}"
case t: VectorType => s"${t.tpe.serialize}[${t.size}]"
}
+ s + debug(t)
}
+
+ def getType(): Type =
+ t match {
+ case v: VectorType => v.tpe
+ case tpe: Type => UnknownType
+ }
+
+ def wipeWidth(): Type =
+ t match {
+ case t: UIntType => UIntType(UnknownWidth)
+ case t: SIntType => SIntType(UnknownWidth)
+ case _ => t
+ }
}
implicit class PortDirUtils(p: PortDir) {
- def serialize(): String =
- p match {
+ def serialize(implicit flags: FlagMap = FlagMap): String = {
+ val s = p match {
case Input => "input"
case Output => "output"
}
+ s + debug(p)
+ }
}
implicit class PortUtils(p: Port) {
- def serialize(): String =
- s"${p.dir.serialize} ${p.name} : ${p.tpe.serialize}"
+ def serialize(implicit flags: FlagMap = FlagMap): String =
+ s"${p.dir.serialize} ${p.name} : ${p.tpe.serialize}" + debug(p)
+ def getType(): Type = p.tpe
}
implicit class ModuleUtils(m: Module) {
- def serialize(): String = {
+ def serialize(implicit flags: FlagMap = FlagMap): String = {
var s = new StringBuilder(s"module ${m.name} : ")
withIndent {
s ++= m.ports.map(newline ++ _.serialize).mkString
s ++= newline ++ m.stmt.serialize
}
+ s ++= debug(m)
s.toString
}
}
implicit class CircuitUtils(c: Circuit) {
- def serialize(): String = {
+ def serialize(implicit flags: FlagMap = FlagMap): String = {
var s = new StringBuilder(s"circuit ${c.name} : ")
- //withIndent { c.modules.foreach(s ++= newline ++ newline ++ _.serialize) }
withIndent { s ++= newline ++ c.modules.map(_.serialize).mkString(newline + newline) }
s ++= newline ++ newline
+ s ++= debug(c)
s.toString
}
}