summaryrefslogtreecommitdiff
path: root/chiselFrontend/src/main/scala/Chisel/internal
diff options
context:
space:
mode:
Diffstat (limited to 'chiselFrontend/src/main/scala/Chisel/internal')
-rw-r--r--chiselFrontend/src/main/scala/Chisel/internal/SourceInfo.scala51
-rw-r--r--chiselFrontend/src/main/scala/Chisel/internal/firrtl/Emitter.scala105
-rw-r--r--chiselFrontend/src/main/scala/Chisel/internal/firrtl/IR.scala37
3 files changed, 71 insertions, 122 deletions
diff --git a/chiselFrontend/src/main/scala/Chisel/internal/SourceInfo.scala b/chiselFrontend/src/main/scala/Chisel/internal/SourceInfo.scala
new file mode 100644
index 00000000..66bfc7a4
--- /dev/null
+++ b/chiselFrontend/src/main/scala/Chisel/internal/SourceInfo.scala
@@ -0,0 +1,51 @@
+// See LICENSE for license details.
+
+// This file contains macros for adding source locators at the point of invocation.
+//
+// This is not part of coreMacros to disallow this macro from being implicitly invoked in Chisel
+// frontend (and generating source locators in Chisel core), which is almost certainly a bug.
+//
+// Note: While these functions and definitions are not private (macros can't be
+// private), these are NOT meant to be part of the public API (yet) and no
+// forward compatibility guarantees are made.
+// A future revision may stabilize the source locator API to allow library
+// writers to append source locator information at the point of a library
+// function invocation.
+
+package Chisel.internal.sourceinfo
+
+import scala.language.experimental.macros
+import scala.reflect.macros.blackbox.Context
+
+/** Abstract base class for generalized source information.
+ */
+sealed trait SourceInfo
+
+sealed trait NoSourceInfo extends SourceInfo
+
+/** For when source info can't be generated because of a technical limitation, like for Reg because
+ * Scala macros don't support named or default arguments.
+ */
+case object UnlocatableSourceInfo extends NoSourceInfo
+
+/** For when source info isn't generated because the function is deprecated and we're lazy.
+ */
+case object DeprecatedSourceInfo extends NoSourceInfo
+
+/** For FIRRTL lines from a Scala source line.
+ */
+case class SourceLine(filename: String, line: Int, col: Int) extends SourceInfo
+
+/** Provides a macro that returns the source information at the invocation point.
+ */
+object SourceInfoMacro {
+ def generate_source_info(c: Context): c.Tree = {
+ import c.universe._
+ val p = c.enclosingPosition
+ q"_root_.Chisel.internal.sourceinfo.SourceLine(${p.source.file.name}, ${p.line}, ${p.column})"
+ }
+}
+
+object SourceInfo {
+ implicit def materialize: SourceInfo = macro SourceInfoMacro.generate_source_info
+}
diff --git a/chiselFrontend/src/main/scala/Chisel/internal/firrtl/Emitter.scala b/chiselFrontend/src/main/scala/Chisel/internal/firrtl/Emitter.scala
deleted file mode 100644
index 34547503..00000000
--- a/chiselFrontend/src/main/scala/Chisel/internal/firrtl/Emitter.scala
+++ /dev/null
@@ -1,105 +0,0 @@
-// See LICENSE for license details.
-
-package Chisel.internal.firrtl
-import Chisel._
-
-private[Chisel] object Emitter {
- def emit(circuit: Circuit): String = new Emitter(circuit).toString
-}
-
-private class Emitter(circuit: Circuit) {
- override def toString: String = res.toString
-
- private def emitPort(e: Port): String =
- s"${e.dir} ${e.id.getRef.name} : ${e.id.toType}"
- private def emit(e: Command, ctx: Component): String = e match {
- case e: DefPrim[_] => s"node ${e.name} = ${e.op.name}(${e.args.map(_.fullName(ctx)).mkString(", ")})"
- case e: DefWire => s"wire ${e.name} : ${e.id.toType}"
- case e: DefReg => s"reg ${e.name} : ${e.id.toType}, ${e.clock.fullName(ctx)}"
- case e: DefRegInit => s"reg ${e.name} : ${e.id.toType}, ${e.clock.fullName(ctx)} with : (reset => (${e.reset.fullName(ctx)}, ${e.init.fullName(ctx)}))"
- case e: DefMemory => s"cmem ${e.name} : ${e.t.toType}[${e.size}]"
- case e: DefSeqMemory => s"smem ${e.name} : ${e.t.toType}[${e.size}]"
- case e: DefMemPort[_] => s"${e.dir} mport ${e.name} = ${e.source.fullName(ctx)}[${e.index.fullName(ctx)}], ${e.clock.fullName(ctx)}"
- case e: Connect => s"${e.loc.fullName(ctx)} <= ${e.exp.fullName(ctx)}"
- case e: BulkConnect => s"${e.loc1.fullName(ctx)} <- ${e.loc2.fullName(ctx)}"
- case e: Stop => s"stop(${e.clk.fullName(ctx)}, UInt<1>(1), ${e.ret})"
- case e: Printf => s"""printf(${e.clk.fullName(ctx)}, UInt<1>(1), "${e.format}"${e.ids.map(_.fullName(ctx)).fold(""){_ + ", " + _}})"""
- case e: DefInvalid => s"${e.arg.fullName(ctx)} is invalid"
- case e: DefInstance => {
- val modName = moduleMap.get(e.id.name).get
- s"inst ${e.name} of $modName"
- }
-
- case w: WhenBegin =>
- indent()
- s"when ${w.pred.fullName(ctx)} :"
- case _: WhenEnd =>
- unindent()
- "skip"
- }
-
- // Map of Module FIRRTL definition to FIRRTL name, if it has been emitted already.
- private val defnMap = collection.mutable.HashMap[String, String]()
- // Map of Component name to FIRRTL id.
- private val moduleMap = collection.mutable.HashMap[String, String]()
-
- /** Generates the FIRRTL module definition with a specified name.
- */
- private def moduleDefn(m: Component, name: String): String = {
- val body = new StringBuilder
- m.id match {
- case _: BlackBox => body ++= newline + s"extmodule $name : "
- case _: Module => body ++= newline + s"module $name : "
- }
- withIndent {
- for (p <- m.ports)
- body ++= newline + emitPort(p)
- body ++= newline
-
- m.id match {
- case _: BlackBox =>
- // TODO: BlackBoxes should be empty, but funkiness in Module() means
- // it's not for now. Eventually, this should assert out.
- case _: Module => for (cmd <- m.commands) {
- body ++= newline + emit(cmd, m)
- }
- }
- body ++= newline
- }
- body.toString()
- }
-
- /** Returns the FIRRTL declaration and body of a module, or nothing if it's a
- * duplicate of something already emitted (on the basis of simple string
- * matching).
- */
- private def emit(m: Component): String = {
- // Generate the body.
- val moduleName = m.id.getClass.getName.split('.').last
- val defn = moduleDefn(m, moduleName)
-
- defnMap get defn match {
- case Some(deduplicatedName) =>
- moduleMap(m.name) = deduplicatedName
- ""
- case None =>
- require(!(moduleMap contains m.name),
- "emitting module with same name but different contents")
-
- moduleMap(m.name) = m.name
- defnMap(defn) = m.name
-
- moduleDefn(m, m.name)
- }
- }
-
- private var indentLevel = 0
- private def newline = "\n" + (" " * indentLevel)
- private def indent(): Unit = indentLevel += 1
- private def unindent() { require(indentLevel > 0); indentLevel -= 1 }
- private def withIndent(f: => Unit) { indent(); f; unindent() }
-
- private val res = new StringBuilder(s"circuit ${circuit.name} : ")
- withIndent { circuit.components.foreach(c => res ++= emit(c)) }
- res ++= newline
-}
diff --git a/chiselFrontend/src/main/scala/Chisel/internal/firrtl/IR.scala b/chiselFrontend/src/main/scala/Chisel/internal/firrtl/IR.scala
index 91dcf5d2..62784cee 100644
--- a/chiselFrontend/src/main/scala/Chisel/internal/firrtl/IR.scala
+++ b/chiselFrontend/src/main/scala/Chisel/internal/firrtl/IR.scala
@@ -3,6 +3,7 @@
package Chisel.internal.firrtl
import Chisel._
import Chisel.internal._
+import Chisel.internal.sourceinfo.{SourceInfo, NoSourceInfo}
case class PrimOp(val name: String) {
override def toString: String = name
@@ -142,29 +143,31 @@ object MemPortDirection {
object INFER extends MemPortDirection("infer")
}
-abstract class Command
+abstract class Command {
+ def sourceInfo: SourceInfo
+}
abstract class Definition extends Command {
def id: HasId
def name: String = id.getRef.name
}
-case class DefPrim[T <: Data](id: T, op: PrimOp, args: Arg*) extends Definition
-case class DefInvalid(arg: Arg) extends Command
-case class DefWire(id: Data) extends Definition
-case class DefReg(id: Data, clock: Arg) extends Definition
-case class DefRegInit(id: Data, clock: Arg, reset: Arg, init: Arg) extends Definition
-case class DefMemory(id: HasId, t: Data, size: Int) extends Definition
-case class DefSeqMemory(id: HasId, t: Data, size: Int) extends Definition
-case class DefMemPort[T <: Data](id: T, source: Node, dir: MemPortDirection, index: Arg, clock: Arg) extends Definition
-case class DefInstance(id: Module, ports: Seq[Port]) extends Definition
-case class WhenBegin(pred: Arg) extends Command
-case class WhenEnd() extends Command
-case class Connect(loc: Node, exp: Arg) extends Command
-case class BulkConnect(loc1: Node, loc2: Node) extends Command
-case class ConnectInit(loc: Node, exp: Arg) extends Command
-case class Stop(clk: Arg, ret: Int) extends Command
+case class DefPrim[T <: Data](sourceInfo: SourceInfo, id: T, op: PrimOp, args: Arg*) extends Definition
+case class DefInvalid(sourceInfo: SourceInfo, arg: Arg) extends Command
+case class DefWire(sourceInfo: SourceInfo, id: Data) extends Definition
+case class DefReg(sourceInfo: SourceInfo, id: Data, clock: Arg) extends Definition
+case class DefRegInit(sourceInfo: SourceInfo, id: Data, clock: Arg, reset: Arg, init: Arg) extends Definition
+case class DefMemory(sourceInfo: SourceInfo, id: HasId, t: Data, size: Int) extends Definition
+case class DefSeqMemory(sourceInfo: SourceInfo, id: HasId, t: Data, size: Int) extends Definition
+case class DefMemPort[T <: Data](sourceInfo: SourceInfo, id: T, source: Node, dir: MemPortDirection, index: Arg, clock: Arg) extends Definition
+case class DefInstance(sourceInfo: SourceInfo, id: Module, ports: Seq[Port]) extends Definition
+case class WhenBegin(sourceInfo: SourceInfo, pred: Arg) extends Command
+case class WhenEnd(sourceInfo: SourceInfo) extends Command
+case class Connect(sourceInfo: SourceInfo, loc: Node, exp: Arg) extends Command
+case class BulkConnect(sourceInfo: SourceInfo, loc1: Node, loc2: Node) extends Command
+case class ConnectInit(sourceInfo: SourceInfo, loc: Node, exp: Arg) extends Command
+case class Stop(sourceInfo: SourceInfo, clk: Arg, ret: Int) extends Command
case class Component(id: Module, name: String, ports: Seq[Port], commands: Seq[Command]) extends Arg
case class Port(id: Data, dir: Direction)
-case class Printf(clk: Arg, formatIn: String, ids: Seq[Arg]) extends Command {
+case class Printf(sourceInfo: SourceInfo, clk: Arg, formatIn: String, ids: Seq[Arg]) extends Command {
require(formatIn.forall(c => c.toInt > 0 && c.toInt < 128), "format strings must comprise non-null ASCII values")
def format: String = {
def escaped(x: Char) = {