diff options
Diffstat (limited to 'src/main/scala/firrtl/Utils.scala')
| -rw-r--r-- | src/main/scala/firrtl/Utils.scala | 243 |
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 } } |
