diff options
| author | Jack Koenig | 2017-11-02 12:15:28 -0700 |
|---|---|---|
| committer | Adam Izraelevitz | 2017-11-08 13:26:13 -0800 |
| commit | 9a0b7ecc84263e8b242890f4df5780a690ab9475 (patch) | |
| tree | 4de2c59d78aad3ddacb3535b54ca1671454c0c3e /src | |
| parent | aaac74497b33bc62d3410e2269dad895d9bb71f1 (diff) | |
Emit source locators as comments in emitted Verilog
Diffstat (limited to 'src')
| -rw-r--r-- | src/main/scala/firrtl/Emitter.scala | 105 |
1 files changed, 54 insertions, 51 deletions
diff --git a/src/main/scala/firrtl/Emitter.scala b/src/main/scala/firrtl/Emitter.scala index 6386c33a..edeb938d 100644 --- a/src/main/scala/firrtl/Emitter.scala +++ b/src/main/scala/firrtl/Emitter.scala @@ -233,6 +233,10 @@ class VerilogEmitter extends SeqTransform with Emitter { case (i: Int) => w write i.toString case (i: Long) => w write i.toString case (i: BigInt) => w write i.toString + case (i: Info) => i match { + case NoInfo => // Do nothing + case ix => w.write(s" //$ix") + } case (s: Seq[Any]) => s foreach (emit(_, top + 1)) if (top == 0) w write "\n" @@ -378,22 +382,23 @@ class VerilogEmitter extends SeqTransform with Emitter { val at_clock = mutable.LinkedHashMap[Expression,ArrayBuffer[Seq[Any]]]() val initials = ArrayBuffer[Seq[Any]]() val simulates = ArrayBuffer[Seq[Any]]() - def declare(b: String, n: String, t: Type) = t match { + def declare(b: String, n: String, t: Type, info: Info) = t match { case tx: VectorType => - declares += Seq(b, " ", tx.tpe, " ", n, " [0:", tx.size - 1, "];") + declares += Seq(b, " ", tx.tpe, " ", n, " [0:", tx.size - 1, "];",info) case tx => - declares += Seq(b, " ", tx, " ", n,";") + declares += Seq(b, " ", tx, " ", n,";",info) } - def assign(e: Expression, value: Expression) { - assigns += Seq("assign ", e, " = ", value, ";") + def assign(e: Expression, value: Expression, info: Info) { + assigns += Seq("assign ", e, " = ", value, ";", info) } // In simulation, assign garbage under a predicate - def garbageAssign(e: Expression, syn: Expression, garbageCond: Expression) = { + def garbageAssign(e: Expression, syn: Expression, garbageCond: Expression, info: Info) = { assigns += Seq("`ifndef RANDOMIZE_GARBAGE_ASSIGN") - assigns += Seq("assign ", e, " = ", syn, ";") + assigns += Seq("assign ", e, " = ", syn, ";", info) assigns += Seq("`else") - assigns += Seq("assign ", e, " = ", garbageCond, " ? ", rand_string(syn.tpe), " : ", syn, ";") + assigns += Seq("assign ", e, " = ", garbageCond, " ? ", rand_string(syn.tpe), " : ", syn, + ";", info) assigns += Seq("`endif // RANDOMIZE_GARBAGE_ASSIGN") } def invalidAssign(e: Expression) = { @@ -455,12 +460,12 @@ class VerilogEmitter extends SeqTransform with Emitter { } } - def update(e: Expression, value: Expression, clk: Expression, en: Expression) { + def update(e: Expression, value: Expression, clk: Expression, en: Expression, info: Info) = { if (!at_clock.contains(clk)) at_clock(clk) = ArrayBuffer[Seq[Any]]() if (weq(en,one)) at_clock(clk) += Seq(e," <= ",value,";") else { at_clock(clk) += Seq("if(",en,") begin") - at_clock(clk) += Seq(tab,e," <= ",value,";") + at_clock(clk) += Seq(tab,e," <= ",value,";",info) at_clock(clk) += Seq("end") } } @@ -471,7 +476,7 @@ class VerilogEmitter extends SeqTransform with Emitter { val nx = namespace.newName("_RAND") val rand = VRandom(bitWidth(t)) val tx = SIntType(IntWidth(rand.realWidth)) - declare("reg",nx, tx) + declare("reg",nx, tx, NoInfo) initials += Seq(wref(nx, tx), " = ", VRandom(bitWidth(t)), ";") Seq(nx, "[", bitWidth(t) - 1, ":0]") } @@ -492,7 +497,7 @@ class VerilogEmitter extends SeqTransform with Emitter { initials += Seq("`endif // RANDOMIZE_MEM_INIT") } - def simulate(clk: Expression, en: Expression, s: Seq[Any], cond: Option[String]) { + def simulate(clk: Expression, en: Expression, s: Seq[Any], cond: Option[String], info: Info) = { if (!at_clock.contains(clk)) at_clock(clk) = ArrayBuffer[Seq[Any]]() at_clock(clk) += Seq("`ifndef SYNTHESIS") if (cond.nonEmpty) { @@ -501,7 +506,7 @@ class VerilogEmitter extends SeqTransform with Emitter { at_clock(clk) += Seq("`endif") } at_clock(clk) += Seq(tab,tab,"if (",en,") begin") - at_clock(clk) += Seq(tab,tab,tab,s) + at_clock(clk) += Seq(tab,tab,tab,s,info) at_clock(clk) += Seq(tab,tab,"end") if (cond.nonEmpty) { at_clock(clk) += Seq(s"`ifdef ${cond.get}") @@ -539,42 +544,44 @@ class VerilogEmitter extends SeqTransform with Emitter { } // dirs are already padded - portdefs ++= (dirs, padToMax(tpes), m.ports).zipped.map { - case (dir, tpe, Port(_, name, _,_)) => Seq(dir, " " , tpe, " ", name) + portdefs ++= (dirs, padToMax(tpes), m.ports).zipped.toSeq.zipWithIndex.map { + case ((dir, tpe, Port(info, name, _,_)), i) => + if (i != m.ports.size - 1) Seq(dir, " " , tpe, " ", name, ",", info) + else Seq(dir, " " , tpe, " ", name, info) } } def build_streams(s: Statement): Statement = s map build_streams match { case sx @ Connect(info, loc @ WRef(_, _, PortKind | WireKind | InstanceKind, _), expr) => - assign(loc, expr) + assign(loc, expr, info) sx case sx: DefWire => - declare("wire",sx.name,sx.tpe) + declare("wire", sx.name, sx.tpe, sx.info) sx case sx: DefRegister => - declare("reg", sx.name, sx.tpe) + declare("reg", sx.name, sx.tpe, sx.info) val e = wref(sx.name, sx.tpe) update_and_reset(e, sx.clock, sx.reset, sx.init) initialize(e) sx case sx @ IsInvalid(info, expr) => val wref = netlist(expr) match { case e: WRef => e } - declare("reg", wref.name, sx.expr.tpe) + declare("reg", wref.name, sx.expr.tpe, info) initialize(wref) kind(expr) match { - case PortKind | WireKind | InstanceKind => assign(expr, netlist(expr)) + case PortKind | WireKind | InstanceKind => assign(expr, netlist(expr), info) case _ => } sx case sx: DefNode => - declare("wire", sx.name, sx.value.tpe) - assign(WRef(sx.name, sx.value.tpe, NodeKind, MALE), sx.value) + declare("wire", sx.name, sx.value.tpe, sx.info) + assign(WRef(sx.name, sx.value.tpe, NodeKind, MALE), sx.value, sx.info) sx case sx: Stop => - simulate(sx.clk, sx.en, stop(sx.ret), Some("STOP_COND")) + simulate(sx.clk, sx.en, stop(sx.ret), Some("STOP_COND"), sx.info) sx case sx: Print => - simulate(sx.clk, sx.en, printf(sx.string, sx.args), Some("PRINTF_COND")) + simulate(sx.clk, sx.en, printf(sx.string, sx.args), Some("PRINTF_COND"), sx.info) sx // If we are emitting an Attach, it must not have been removable in VerilogPrep case sx: Attach => @@ -583,11 +590,11 @@ class VerilogEmitter extends SeqTransform with Emitter { for (set <- sx.exprs.toSet.subsets(2)) { val (a, b) = set.toSeq match { case Seq(x, y) => (x, y) } // Synthesizable ones as well - attachSynAssigns += Seq("assign ", a, " = ", b, ";") - attachSynAssigns += Seq("assign ", b, " = ", a, ";") + attachSynAssigns += Seq("assign ", a, " = ", b, ";", sx.info) + attachSynAssigns += Seq("assign ", b, " = ", a, ";", sx.info) } // alias implementation for everything else - attachAliases += Seq("alias ", sx.exprs.flatMap(e => Seq(e, " = ")).init, ";") + attachAliases += Seq("alias ", sx.exprs.flatMap(e => Seq(e, " = ")).init, ";", sx.info) sx case sx: WDefInstanceConnector => val (module, params) = moduleMap(sx.module) match { @@ -595,7 +602,7 @@ class VerilogEmitter extends SeqTransform with Emitter { case Module(_, name, _, _) => (name, Seq.empty) } val ps = if (params.nonEmpty) params map stringify mkString ("#(", ", ", ") ") else "" - instdeclares += Seq(module, " ", ps, sx.name ," (") + instdeclares += Seq(module, " ", ps, sx.name ," (", sx.info) for (((port, ref), i) <- sx.portCons.zipWithIndex) { val line = Seq(tab, ".", remove_root(port), "(", ref, ")") if (i != sx.portCons.size - 1) instdeclares += Seq(line, ",") @@ -606,7 +613,7 @@ class VerilogEmitter extends SeqTransform with Emitter { case sx: DefMemory => val fullSize = sx.depth * (sx.dataType match { case GroundType(IntWidth(width)) => width }) val decl = if (fullSize > (1 << 29)) "reg /* sparse */" else "reg" - declare(decl, sx.name, VectorType(sx.dataType, sx.depth)) + declare(decl, sx.name, VectorType(sx.dataType, sx.depth), sx.info) initialize_mem(sx) if (sx.readLatency != 0 || sx.writeLatency != 1) throw EmitterException("All memories should be transformed into " + @@ -618,12 +625,12 @@ class VerilogEmitter extends SeqTransform with Emitter { // Ports should share an always@posedge, so can't have intermediary wire val clk = netlist(memPortField(sx, r, "clk")) - declare("wire", LowerTypes.loweredName(data), data.tpe) - declare("wire", LowerTypes.loweredName(addr), addr.tpe) + declare("wire", LowerTypes.loweredName(data), data.tpe, sx.info) + declare("wire", LowerTypes.loweredName(addr), addr.tpe, sx.info) // declare("wire", LowerTypes.loweredName(en), en.tpe) //; Read port - assign(addr, netlist(addr)) //;Connects value to m.r.addr + assign(addr, netlist(addr), NoInfo) // Info should come from addr connection // assign(en, netlist(en)) //;Connects value to m.r.en val mem = WRef(sx.name, memType(sx), MemKind, UNKNOWNGENDER) val memPort = WSubAccess(mem, addr, sx.dataType, UNKNOWNGENDER) @@ -631,9 +638,9 @@ class VerilogEmitter extends SeqTransform with Emitter { val garbageGuard = DoPrim(Geq, Seq(addr, depthValue), Seq(), UnknownType) if ((sx.depth & (sx.depth - 1)) == 0) - assign(data, memPort) + assign(data, memPort, sx.info) else - garbageAssign(data, memPort, garbageGuard) + garbageAssign(data, memPort, garbageGuard, sx.info) } for (w <- sx.writers) { @@ -644,20 +651,21 @@ class VerilogEmitter extends SeqTransform with Emitter { //Ports should share an always@posedge, so can't have intermediary wire val clk = netlist(memPortField(sx, w, "clk")) - declare("wire", LowerTypes.loweredName(data), data.tpe) - declare("wire", LowerTypes.loweredName(addr), addr.tpe) - declare("wire", LowerTypes.loweredName(mask), mask.tpe) - declare("wire", LowerTypes.loweredName(en), en.tpe) + declare("wire", LowerTypes.loweredName(data), data.tpe, sx.info) + declare("wire", LowerTypes.loweredName(addr), addr.tpe, sx.info) + declare("wire", LowerTypes.loweredName(mask), mask.tpe, sx.info) + declare("wire", LowerTypes.loweredName(en), en.tpe, sx.info) - //; Write port - assign(data, netlist(data)) - assign(addr, netlist(addr)) - assign(mask, netlist(mask)) - assign(en, netlist(en)) + // Write port + // Info should come from netlist + assign(data, netlist(data), NoInfo) + assign(addr, netlist(addr), NoInfo) + assign(mask, netlist(mask), NoInfo) + assign(en, netlist(en), NoInfo) val mem = WRef(sx.name, memType(sx), MemKind, UNKNOWNGENDER) val memPort = WSubAccess(mem, addr, sx.dataType, UNKNOWNGENDER) - update(memPort, data, clk, AND(en, mask)) + update(memPort, data, clk, AND(en, mask), sx.info) } if (sx.readwriters.nonEmpty) @@ -668,13 +676,8 @@ class VerilogEmitter extends SeqTransform with Emitter { } def emit_streams() { - emit(Seq("module ", m.name, "(")) - for ((x, i) <- portdefs.zipWithIndex) { - if (i != portdefs.size - 1) - emit(Seq(tab, x, ",")) - else - emit(Seq(tab, x)) - } + emit(Seq("module ", m.name, "(", m.info)) + for (x <- portdefs) emit(Seq(tab, x)) emit(Seq(");")) if (declares.isEmpty && assigns.isEmpty) emit(Seq(tab, "initial begin end")) |
