summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorducky2016-05-05 13:22:04 -0700
committerducky2016-05-20 16:02:49 -0700
commite92f2f69477a6ce86fc148a1a95db5797f2e3051 (patch)
tree2f1511e3395299fd4f1e98c3f75886e06c0cd096
parent84de04606bc972bd6a83f67913a0e30c4c46ee5e (diff)
Implementation of source locators
-rw-r--r--build.sbt15
-rw-r--r--chiselFrontend/src/main/scala/Chisel/Aggregate.scala73
-rw-r--r--chiselFrontend/src/main/scala/Chisel/Assert.scala (renamed from chiselFrontend/src/main/scala/Chisel/CoreUtil.scala)50
-rw-r--r--chiselFrontend/src/main/scala/Chisel/BitPat.scala14
-rw-r--r--chiselFrontend/src/main/scala/Chisel/Bits.scala495
-rw-r--r--chiselFrontend/src/main/scala/Chisel/BlackBox.scala5
-rw-r--r--chiselFrontend/src/main/scala/Chisel/Data.scala49
-rw-r--r--chiselFrontend/src/main/scala/Chisel/Mem.scala35
-rw-r--r--chiselFrontend/src/main/scala/Chisel/Module.scala32
-rw-r--r--chiselFrontend/src/main/scala/Chisel/Printf.scala36
-rw-r--r--chiselFrontend/src/main/scala/Chisel/Reg.scala25
-rw-r--r--chiselFrontend/src/main/scala/Chisel/SeqUtils.scala20
-rw-r--r--chiselFrontend/src/main/scala/Chisel/When.scala21
-rw-r--r--chiselFrontend/src/main/scala/Chisel/internal/SourceInfo.scala51
-rw-r--r--chiselFrontend/src/main/scala/Chisel/internal/firrtl/IR.scala37
-rw-r--r--coreMacros/src/main/scala/Chisel/internal/sourceinfo/SourceInfoTransform.scala156
-rw-r--r--src/main/scala/Chisel/internal/firrtl/Emitter.scala (renamed from chiselFrontend/src/main/scala/Chisel/internal/firrtl/Emitter.scala)53
-rw-r--r--src/main/scala/Chisel/testers/BasicTester.scala8
18 files changed, 850 insertions, 325 deletions
diff --git a/build.sbt b/build.sbt
index 06a73d88..be039872 100644
--- a/build.sbt
+++ b/build.sbt
@@ -79,17 +79,28 @@ lazy val chiselSettings = Seq (
// }
)
-lazy val chiselFrontend = (project in file("chiselFrontend")).
+lazy val coreMacros = (project in file("coreMacros")).
settings(commonSettings: _*).
settings(
libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaVersion.value
)
+lazy val chiselFrontend = (project in file("chiselFrontend")).
+ settings(commonSettings: _*).
+ settings(
+ libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaVersion.value
+ ).
+ dependsOn(coreMacros)
+
lazy val chisel = (project in file(".")).
settings(commonSettings: _*).
settings(chiselSettings: _*).
- dependsOn(chiselFrontend).settings(
+ dependsOn(coreMacros).
+ dependsOn(chiselFrontend).
+ settings(
// Include macro classes, resources, and sources main jar.
+ mappings in (Compile, packageBin) <++= mappings in (coreMacros, Compile, packageBin),
+ mappings in (Compile, packageSrc) <++= mappings in (coreMacros, Compile, packageSrc),
mappings in (Compile, packageBin) <++= mappings in (chiselFrontend, Compile, packageBin),
mappings in (Compile, packageSrc) <++= mappings in (chiselFrontend, Compile, packageSrc)
)
diff --git a/chiselFrontend/src/main/scala/Chisel/Aggregate.scala b/chiselFrontend/src/main/scala/Chisel/Aggregate.scala
index 4d35e2f0..197135d7 100644
--- a/chiselFrontend/src/main/scala/Chisel/Aggregate.scala
+++ b/chiselFrontend/src/main/scala/Chisel/Aggregate.scala
@@ -4,10 +4,12 @@ package Chisel
import scala.collection.immutable.ListMap
import scala.collection.mutable.{ArrayBuffer, HashSet, LinkedHashMap}
+import scala.language.experimental.macros
import internal._
import internal.Builder.pushCommand
import internal.firrtl._
+import internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, VecTransform, SourceInfoTransform}
/** An abstract class for data types that solely consist of (are an aggregate
* of) other Data objects.
@@ -36,14 +38,15 @@ object Vec {
* element
* @note output elements are connected from the input elements
*/
- def apply[T <: Data](elts: Seq[T]): Vec[T] = {
+ def apply[T <: Data](elts: Seq[T]): Vec[T] = macro VecTransform.apply_elts
+
+ def do_apply[T <: Data](elts: Seq[T])(implicit sourceInfo: SourceInfo): Vec[T] = {
// REVIEW TODO: this should be removed in favor of the apply(elts: T*)
// varargs constructor, which is more in line with the style of the Scala
// collection API. However, a deprecation phase isn't possible, since
// changing apply(elt0, elts*) to apply(elts*) causes a function collision
// with apply(Seq) after type erasure. Workarounds by either introducing a
// DummyImplicit or additional type parameter will break some code.
-
require(!elts.isEmpty)
val width = elts.map(_.width).reduce(_ max _)
val vec = Wire(new Vec(elts.head.cloneTypeWidth(width), elts.length))
@@ -60,7 +63,9 @@ object Vec {
* element
* @note output elements are connected from the input elements
*/
- def apply[T <: Data](elt0: T, elts: T*): Vec[T] =
+ def apply[T <: Data](elt0: T, elts: T*): Vec[T] = macro VecTransform.apply_elt0
+
+ def do_apply[T <: Data](elt0: T, elts: T*)(implicit sourceInfo: SourceInfo): Vec[T] =
apply(elt0 +: elts.toSeq)
/** Creates a new [[Vec]] of length `n` composed of the results of the given
@@ -71,7 +76,9 @@ object Vec {
* @param gen function that takes in an Int (the index) and returns a
* [[Data]] that becomes the output element
*/
- def tabulate[T <: Data](n: Int)(gen: (Int) => T): Vec[T] =
+ def tabulate[T <: Data](n: Int)(gen: (Int) => T): Vec[T] = macro VecTransform.tabulate
+
+ def do_tabulate[T <: Data](n: Int)(gen: (Int) => T)(implicit sourceInfo: SourceInfo): Vec[T] =
apply((0 until n).map(i => gen(i)))
/** Creates a new [[Vec]] of length `n` composed of the result of the given
@@ -82,7 +89,10 @@ object Vec {
* @param gen function that generates the [[Data]] that becomes the output
* element
*/
- def fill[T <: Data](n: Int)(gen: => T): Vec[T] = apply(Seq.fill(n)(gen))
+ def fill[T <: Data](n: Int)(gen: => T): Vec[T] = macro VecTransform.fill
+
+ def do_fill[T <: Data](n: Int)(gen: => T)(implicit sourceInfo: SourceInfo): Vec[T] =
+ apply(Seq.fill(n)(gen))
}
/** A vector (array) of [[Data]] elements. Provides hardware versions of various
@@ -102,18 +112,18 @@ sealed class Vec[T <: Data] private (gen: => T, val length: Int)
private val self = IndexedSeq.fill(length)(gen)
- override def <> (that: Data): Unit = this := that
+ override def <> (that: Data)(implicit sourceInfo: SourceInfo): Unit = this := that
/** Strong bulk connect, assigning elements in this Vec from elements in a Seq.
*
* @note the length of this Vec must match the length of the input Seq
*/
- def <> (that: Seq[T]): Unit = this := that
+ def <> (that: Seq[T])(implicit sourceInfo: SourceInfo): Unit = this := that
// TODO: eliminate once assign(Seq) isn't ambiguous with assign(Data) since Vec extends Seq and Data
- def <> (that: Vec[T]): Unit = this := that.asInstanceOf[Data]
+ def <> (that: Vec[T])(implicit sourceInfo: SourceInfo): Unit = this := that.asInstanceOf[Data]
- override def := (that: Data): Unit = that match {
+ override def := (that: Data)(implicit sourceInfo: SourceInfo): Unit = that match {
case _: Vec[_] => this connect that
case _ => this badConnect that
}
@@ -122,14 +132,14 @@ sealed class Vec[T <: Data] private (gen: => T, val length: Int)
*
* @note the length of this Vec must match the length of the input Seq
*/
- def := (that: Seq[T]): Unit = {
+ def := (that: Seq[T])(implicit sourceInfo: SourceInfo): Unit = {
require(this.length == that.length)
for ((a, b) <- this zip that)
a := b
}
// TODO: eliminate once assign(Seq) isn't ambiguous with assign(Data) since Vec extends Seq and Data
- def := (that: Vec[T]): Unit = this connect that
+ def := (that: Vec[T])(implicit sourceInfo: SourceInfo): Unit = this connect that
/** Creates a dynamically indexed read or write accessor into the array.
*/
@@ -147,7 +157,7 @@ sealed class Vec[T <: Data] private (gen: => T, val length: Int)
def read(idx: UInt): T = apply(idx)
@deprecated("Use Vec.apply instead", "chisel3")
- def write(idx: UInt, data: T): Unit = apply(idx) := data
+ def write(idx: UInt, data: T): Unit = apply(idx).:=(data)(DeprecatedSourceInfo)
override def cloneType: this.type =
Vec(length, gen).asInstanceOf[this.type]
@@ -175,20 +185,32 @@ trait VecLike[T <: Data] extends collection.IndexedSeq[T] {
/** Outputs true if p outputs true for every element.
*/
- def forall(p: T => Bool): Bool = (this map p).fold(Bool(true))(_ && _)
+ def forall(p: T => Bool): Bool = macro SourceInfoTransform.pArg
+
+ def do_forall(p: T => Bool)(implicit sourceInfo: SourceInfo): Bool =
+ (this map p).fold(Bool(true))(_ && _)
/** Outputs true if p outputs true for at least one element.
*/
- def exists(p: T => Bool): Bool = (this map p).fold(Bool(false))(_ || _)
+ def exists(p: T => Bool): Bool = macro SourceInfoTransform.pArg
+
+ def do_exists(p: T => Bool)(implicit sourceInfo: SourceInfo): Bool =
+ (this map p).fold(Bool(false))(_ || _)
/** Outputs true if the vector contains at least one element equal to x (using
* the === operator).
*/
- def contains(x: T)(implicit evidence: T <:< UInt): Bool = this.exists(_ === x)
+ def contains(x: T)(implicit ev: T <:< UInt): Bool = macro VecTransform.contains
+
+ def do_contains(x: T)(implicit sourceInfo: SourceInfo, ev: T <:< UInt): Bool =
+ this.exists(_ === x)
/** Outputs the number of elements for which p is true.
*/
- def count(p: T => Bool): UInt = SeqUtils.count(this map p)
+ def count(p: T => Bool): UInt = macro SourceInfoTransform.pArg
+
+ def do_count(p: T => Bool)(implicit sourceInfo: SourceInfo): UInt =
+ SeqUtils.count(this map p)
/** Helper function that appends an index (literal value) to each element,
* useful for hardware generators which output an index.
@@ -197,11 +219,17 @@ trait VecLike[T <: Data] extends collection.IndexedSeq[T] {
/** Outputs the index of the first element for which p outputs true.
*/
- def indexWhere(p: T => Bool): UInt = SeqUtils.priorityMux(indexWhereHelper(p))
+ def indexWhere(p: T => Bool): UInt = macro SourceInfoTransform.pArg
+
+ def do_indexWhere(p: T => Bool)(implicit sourceInfo: SourceInfo): UInt =
+ SeqUtils.priorityMux(indexWhereHelper(p))
/** Outputs the index of the last element for which p outputs true.
*/
- def lastIndexWhere(p: T => Bool): UInt = SeqUtils.priorityMux(indexWhereHelper(p).reverse)
+ def lastIndexWhere(p: T => Bool): UInt = macro SourceInfoTransform.pArg
+
+ def do_lastIndexWhere(p: T => Bool)(implicit sourceInfo: SourceInfo): UInt =
+ SeqUtils.priorityMux(indexWhereHelper(p).reverse)
/** Outputs the index of the element for which p outputs true, assuming that
* the there is exactly one such element.
@@ -213,7 +241,10 @@ trait VecLike[T <: Data] extends collection.IndexedSeq[T] {
* true is NOT checked (useful in cases where the condition doesn't always
* hold, but the results are not used in those cases)
*/
- def onlyIndexWhere(p: T => Bool): UInt = SeqUtils.oneHotMux(indexWhereHelper(p))
+ def onlyIndexWhere(p: T => Bool): UInt = macro SourceInfoTransform.pArg
+
+ def do_onlyIndexWhere(p: T => Bool)(implicit sourceInfo: SourceInfo): UInt =
+ SeqUtils.oneHotMux(indexWhereHelper(p))
}
/** Base class for data types defined as a bundle of other data types.
@@ -237,13 +268,13 @@ class Bundle extends Aggregate(NO_DIR) {
* mySubModule.io <> io
* }}}
*/
- override def <> (that: Data): Unit = that match {
+ override def <> (that: Data)(implicit sourceInfo: SourceInfo): Unit = that match {
case _: Bundle => this bulkConnect that
case _ => this badConnect that
}
// TODO: replace with better defined FIRRTL strong-connect operator
- override def := (that: Data): Unit = this <> that
+ override def := (that: Data)(implicit sourceInfo: SourceInfo): Unit = this <> that
lazy val elements: ListMap[String, Data] = ListMap(namedElts:_*)
diff --git a/chiselFrontend/src/main/scala/Chisel/CoreUtil.scala b/chiselFrontend/src/main/scala/Chisel/Assert.scala
index 708b516e..c086f014 100644
--- a/chiselFrontend/src/main/scala/Chisel/CoreUtil.scala
+++ b/chiselFrontend/src/main/scala/Chisel/Assert.scala
@@ -2,12 +2,13 @@
package Chisel
+import scala.reflect.macros.blackbox.Context
+import scala.language.experimental.macros
+
import internal._
import internal.Builder.pushCommand
import internal.firrtl._
-
-import scala.language.experimental.macros
-import scala.reflect.macros.blackbox.Context
+import internal.sourceinfo.SourceInfo
object assert { // scalastyle:ignore object.name
/** Checks for a condition to be valid in the circuit at all times. If the
@@ -28,32 +29,33 @@ object assert { // scalastyle:ignore object.name
* defs need to be compiled first and the SBT project is not set up to do
* that
*/
- def apply(cond: Bool, message: String): Unit = macro apply_impl_msg
- def apply(cond: Bool): Unit = macro apply_impl // macros currently can't take default arguments
+ // Macros currently can't take default arguments, so we need two functions to emulate defaults.
+ def apply(cond: Bool, message: String)(implicit sourceInfo: SourceInfo): Unit = macro apply_impl_msg
+ def apply(cond: Bool)(implicit sourceInfo: SourceInfo): Unit = macro apply_impl
- def apply_impl_msg(c: Context)(cond: c.Tree, message: c.Tree): c.Tree = {
+ def apply_impl_msg(c: Context)(cond: c.Tree, message: c.Tree)(sourceInfo: c.Tree): c.Tree = {
import c.universe._
val p = c.enclosingPosition
val condStr = s"${p.source.file.name}:${p.line} ${p.lineContent.trim}"
val apply_impl_do = symbolOf[this.type].asClass.module.info.member(TermName("apply_impl_do"))
- q"$apply_impl_do($cond, $condStr, _root_.scala.Some($message))"
+ q"$apply_impl_do($cond, $condStr, _root_.scala.Some($message))($sourceInfo)"
}
- def apply_impl(c: Context)(cond: c.Tree): c.Tree = {
+ def apply_impl(c: Context)(cond: c.Tree)(sourceInfo: c.Tree): c.Tree = {
import c.universe._
val p = c.enclosingPosition
val condStr = s"${p.source.file.name}:${p.line} ${p.lineContent.trim}"
val apply_impl_do = symbolOf[this.type].asClass.module.info.member(TermName("apply_impl_do"))
- q"$apply_impl_do($cond, $condStr, _root_.scala.None)"
+ q"$apply_impl_do($cond, $condStr, _root_.scala.None)($sourceInfo)"
}
- def apply_impl_do(cond: Bool, line: String, message: Option[String]) {
+ def apply_impl_do(cond: Bool, line: String, message: Option[String])(implicit sourceInfo: SourceInfo) {
when (!(cond || Builder.dynamicContext.currentModule.get.reset)) {
message match {
case Some(str) => printf.printfWithoutReset(s"Assertion failed: $str\n at $line\n")
case None => printf.printfWithoutReset(s"Assertion failed\n at $line\n")
}
- pushCommand(Stop(Node(Builder.dynamicContext.currentModule.get.clock), 1))
+ pushCommand(Stop(sourceInfo, Node(Builder.dynamicContext.currentModule.get.clock), 1))
}
}
@@ -69,29 +71,3 @@ object assert { // scalastyle:ignore object.name
Predef.assert(cond, "")
}
}
-
-object printf { // scalastyle:ignore object.name
- /** Prints a message in simulation.
- *
- * Does not fire when in reset (defined as the encapsulating Module's
- * reset). If your definition of reset is not the encapsulating Module's
- * reset, you will need to gate this externally.
- *
- * May be called outside of a Module (like defined in a function), so
- * functions using printf make the standard Module assumptions (single clock
- * and single reset).
- *
- * @param fmt printf format string
- * @param data format string varargs containing data to print
- */
- def apply(fmt: String, data: Bits*) {
- when (!Builder.dynamicContext.currentModule.get.reset) {
- printfWithoutReset(fmt, data:_*)
- }
- }
-
- private[Chisel] def printfWithoutReset(fmt: String, data: Bits*) {
- val clock = Builder.dynamicContext.currentModule.get.clock
- pushCommand(Printf(Node(clock), fmt, data.map((d: Bits) => d.ref)))
- }
-}
diff --git a/chiselFrontend/src/main/scala/Chisel/BitPat.scala b/chiselFrontend/src/main/scala/Chisel/BitPat.scala
index a1bf1985..cf412542 100644
--- a/chiselFrontend/src/main/scala/Chisel/BitPat.scala
+++ b/chiselFrontend/src/main/scala/Chisel/BitPat.scala
@@ -2,6 +2,10 @@
package Chisel
+import scala.language.experimental.macros
+
+import Chisel.internal.sourceinfo.{SourceInfo, SourceInfoTransform}
+
object BitPat {
/** Parses a bit pattern string into (bits, mask, width).
*
@@ -74,7 +78,11 @@ object BitPat {
*/
sealed class BitPat(val value: BigInt, val mask: BigInt, width: Int) {
def getWidth: Int = width
- def === (other: UInt): Bool = UInt(value) === (other & UInt(mask))
- def =/= (other: UInt): Bool = !(this === other)
- def != (other: UInt): Bool = this =/= other
+ def === (that: UInt): Bool = macro SourceInfoTransform.thatArg
+ def =/= (that: UInt): Bool = macro SourceInfoTransform.thatArg
+ def != (that: UInt): Bool = macro SourceInfoTransform.thatArg
+
+ def do_=== (that: UInt)(implicit sourceInfo: SourceInfo): Bool = UInt(value) === (that & UInt(mask))
+ def do_=/= (that: UInt)(implicit sourceInfo: SourceInfo): Bool = !(this === that)
+ def do_!= (that: UInt)(implicit sourceInfo: SourceInfo): Bool = this =/= that
}
diff --git a/chiselFrontend/src/main/scala/Chisel/Bits.scala b/chiselFrontend/src/main/scala/Chisel/Bits.scala
index ce177ef1..2783c160 100644
--- a/chiselFrontend/src/main/scala/Chisel/Bits.scala
+++ b/chiselFrontend/src/main/scala/Chisel/Bits.scala
@@ -2,9 +2,13 @@
package Chisel
+import scala.language.experimental.macros
+
import internal._
import internal.Builder.pushOp
import internal.firrtl._
+import internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, SourceInfoTransform, SourceInfoWhiteboxTransform,
+ UIntTransform, MuxTransform}
import firrtl.PrimOp._
/** Element is a leaf data type: it cannot contain other Data objects. Example
@@ -27,37 +31,43 @@ sealed abstract class Bits(dirArg: Direction, width: Width, override val litArg:
def cloneType: this.type = cloneTypeWidth(width)
- override def <> (that: Data): Unit = this := that
+ override def <> (that: Data)(implicit sourceInfo: SourceInfo): Unit = this := that
+
+ final def tail(n: Int): UInt = macro SourceInfoTransform.nArg
+ final def head(n: Int): UInt = macro SourceInfoTransform.nArg
- def tail(n: Int): UInt = {
+ def do_tail(n: Int)(implicit sourceInfo: SourceInfo): UInt = {
val w = width match {
case KnownWidth(x) =>
require(x >= n, s"Can't tail($n) for width $x < $n")
Width(x - n)
case UnknownWidth() => Width()
}
- binop(UInt(width = w), TailOp, n)
+ binop(sourceInfo, UInt(width = w), TailOp, n)
}
- def head(n: Int): UInt = {
+
+ def do_head(n: Int)(implicit sourceInfo: SourceInfo): UInt = {
width match {
case KnownWidth(x) => require(x >= n, s"Can't head($n) for width $x < $n")
case UnknownWidth() =>
}
- binop(UInt(width = n), HeadOp, n)
+ binop(sourceInfo, UInt(width = n), HeadOp, n)
}
/** Returns the specified bit on this wire as a [[Bool]], statically
* addressed.
*/
- final def apply(x: BigInt): Bool = {
+ final def apply(x: BigInt): Bool = macro SourceInfoTransform.xArg
+
+ final def do_apply(x: BigInt)(implicit sourceInfo: SourceInfo): Bool = {
if (x < 0) {
Builder.error(s"Negative bit indices are illegal (got $x)")
}
if (isLit()) {
Bool(((litValue() >> x.toInt) & 1) == 1)
} else {
- pushOp(DefPrim(Bool(), BitsExtractOp, this.ref, ILit(x), ILit(x)))
+ pushOp(DefPrim(sourceInfo, Bool(), BitsExtractOp, this.ref, ILit(x), ILit(x)))
}
}
@@ -66,14 +76,18 @@ sealed abstract class Bits(dirArg: Direction, width: Width, override val litArg:
*
* @note convenience method allowing direct use of Ints without implicits
*/
- final def apply(x: Int): Bool =
- apply(BigInt(x))
+ final def apply(x: Int): Bool = macro SourceInfoTransform.xArg
+
+ final def do_apply(x: Int)(implicit sourceInfo: SourceInfo): Bool = apply(BigInt(x))
/** Returns the specified bit on this wire as a [[Bool]], dynamically
* addressed.
*/
- final def apply(x: UInt): Bool =
+ final def apply(x: UInt): Bool = macro SourceInfoTransform.xArg
+
+ final def do_apply(x: UInt)(implicit sourceInfo: SourceInfo): Bool = {
(this >> x)(0)
+ }
/** Returns a subset of bits on this wire from `hi` to `lo` (inclusive),
* statically addressed.
@@ -84,7 +98,9 @@ sealed abstract class Bits(dirArg: Direction, width: Width, override val litArg:
* myBits(1,0) => 0b01 // extracts the two least significant bits
* }}}
*/
- final def apply(x: Int, y: Int): UInt = {
+ final def apply(x: Int, y: Int): UInt = macro SourceInfoTransform.xyArg
+
+ final def do_apply(x: Int, y: Int)(implicit sourceInfo: SourceInfo): UInt = {
if (x < y || y < 0) {
Builder.error(s"Invalid bit range ($x,$y)")
}
@@ -92,114 +108,154 @@ sealed abstract class Bits(dirArg: Direction, width: Width, override val litArg:
if (isLit()) {
UInt((litValue >> y) & ((BigInt(1) << w) - 1), w)
} else {
- pushOp(DefPrim(UInt(width = w), BitsExtractOp, this.ref, ILit(x), ILit(y)))
+ pushOp(DefPrim(sourceInfo, UInt(width = w), BitsExtractOp, this.ref, ILit(x), ILit(y)))
}
}
// REVIEW TODO: again, is this necessary? Or just have this and use implicits?
- final def apply(x: BigInt, y: BigInt): UInt = apply(x.toInt, y.toInt)
-
- private[Chisel] def unop[T <: Data](dest: T, op: PrimOp): T =
- pushOp(DefPrim(dest, op, this.ref))
- private[Chisel] def binop[T <: Data](dest: T, op: PrimOp, other: BigInt): T =
- pushOp(DefPrim(dest, op, this.ref, ILit(other)))
- private[Chisel] def binop[T <: Data](dest: T, op: PrimOp, other: Bits): T =
- pushOp(DefPrim(dest, op, this.ref, other.ref))
- private[Chisel] def compop(op: PrimOp, other: Bits): Bool =
- pushOp(DefPrim(Bool(), op, this.ref, other.ref))
- private[Chisel] def redop(op: PrimOp): Bool =
- pushOp(DefPrim(Bool(), op, this.ref))
+ final def apply(x: BigInt, y: BigInt): UInt = macro SourceInfoTransform.xyArg
+
+ final def do_apply(x: BigInt, y: BigInt)(implicit sourceInfo: SourceInfo): UInt =
+ apply(x.toInt, y.toInt)
+
+ private[Chisel] def unop[T <: Data](sourceInfo: SourceInfo, dest: T, op: PrimOp): T =
+ pushOp(DefPrim(sourceInfo, dest, op, this.ref))
+ private[Chisel] def binop[T <: Data](sourceInfo: SourceInfo, dest: T, op: PrimOp, other: BigInt): T =
+ pushOp(DefPrim(sourceInfo, dest, op, this.ref, ILit(other)))
+ private[Chisel] def binop[T <: Data](sourceInfo: SourceInfo, dest: T, op: PrimOp, other: Bits): T =
+ pushOp(DefPrim(sourceInfo, dest, op, this.ref, other.ref))
+
+ private[Chisel] def compop(sourceInfo: SourceInfo, op: PrimOp, other: Bits): Bool =
+ pushOp(DefPrim(sourceInfo, Bool(), op, this.ref, other.ref))
+ private[Chisel] def redop(sourceInfo: SourceInfo, op: PrimOp): Bool =
+ pushOp(DefPrim(sourceInfo, Bool(), op, this.ref))
/** Returns this wire zero padded up to the specified width.
*
* @note for SInts only, this does sign extension
*/
- def pad (other: Int): this.type = binop(cloneTypeWidth(this.width max Width(other)), PadOp, other)
+ final def pad(that: Int): this.type = macro SourceInfoTransform.thatArg
+
+ def do_pad(that: Int)(implicit sourceInfo: SourceInfo): this.type =
+ binop(sourceInfo, cloneTypeWidth(this.width max Width(that)), PadOp, that)
+
+ /** Returns this wire bitwise-inverted. */
+ final def unary_~ (): Bits = macro SourceInfoWhiteboxTransform.noArg
+
+ def do_unary_~ (implicit sourceInfo: SourceInfo): Bits
+
/** Shift left operation */
// REVIEW TODO: redundant
// REVIEW TODO: should these return this.type or Bits?
- def << (other: BigInt): Bits
+ final def << (that: BigInt): Bits = macro SourceInfoWhiteboxTransform.thatArg
+
+ def do_<< (that: BigInt)(implicit sourceInfo: SourceInfo): Bits
/** Returns this wire statically left shifted by the specified amount,
* inserting zeros into the least significant bits.
*
* The width of the output is `other` larger than the input.
*/
- def << (other: Int): Bits
+ final def << (that: Int): Bits = macro SourceInfoWhiteboxTransform.thatArg
+
+ def do_<< (that: Int)(implicit sourceInfo: SourceInfo): Bits
/** Returns this wire dynamically left shifted by the specified amount,
* inserting zeros into the least significant bits.
*
* The width of the output is `pow(2, width(other))` larger than the input.
*/
- def << (other: UInt): Bits
+ final def << (that: UInt): Bits = macro SourceInfoWhiteboxTransform.thatArg
+
+ def do_<< (that: UInt)(implicit sourceInfo: SourceInfo): Bits
/** Shift right operation */
// REVIEW TODO: redundant
- def >> (other: BigInt): Bits
+ final def >> (that: BigInt): Bits = macro SourceInfoWhiteboxTransform.thatArg
+
+ def do_>> (that: BigInt)(implicit sourceInfo: SourceInfo): Bits
/** Returns this wire statically right shifted by the specified amount,
* inserting zeros into the most significant bits.
*
* The width of the output is the same as the input.
*/
- def >> (other: Int): Bits
+ final def >> (that: Int): Bits = macro SourceInfoWhiteboxTransform.thatArg
+
+ def do_>> (that: Int)(implicit sourceInfo: SourceInfo): Bits
/** Returns this wire dynamically right shifted by the specified amount,
* inserting zeros into the most significant bits.
*
* The width of the output is the same as the input.
*/
- def >> (other: UInt): Bits
+ final def >> (that: UInt): Bits = macro SourceInfoWhiteboxTransform.thatArg
+
+ def do_>> (that: UInt)(implicit sourceInfo: SourceInfo): Bits
/** Returns the contents of this wire as a [[Vec]] of [[Bool]]s.
*/
- def toBools: Seq[Bool] = Seq.tabulate(this.getWidth)(i => this(i))
+ final def toBools(): Seq[Bool] = macro SourceInfoTransform.noArg
+
+ def toBools(implicit sourceInfo: SourceInfo): Seq[Bool] =
+ Seq.tabulate(this.getWidth)(i => this(i))
/** Reinterpret cast to a SInt.
*
* @note value not guaranteed to be preserved: for example, an UInt of width
* 3 and value 7 (0b111) would become a SInt with value -1
*/
- def asSInt(): SInt
+ final def asSInt(): SInt = macro SourceInfoTransform.noArg
+
+ def do_asSInt(implicit sourceInfo: SourceInfo): SInt
/** Reinterpret cast to an UInt.
*
* @note value not guaranteed to be preserved: for example, a SInt of width
* 3 and value -1 (0b111) would become an UInt with value 7
*/
- def asUInt(): UInt
+ final def asUInt(): UInt = macro SourceInfoTransform.noArg
+
+ def do_asUInt(implicit sourceInfo: SourceInfo): UInt
/** Reinterpret cast to Bits. */
- def asBits(): Bits = asUInt
+ final def asBits(): Bits = macro SourceInfoTransform.noArg
+
+ def do_asBits(implicit sourceInfo: SourceInfo): Bits = asUInt()
@deprecated("Use asSInt, which makes the reinterpret cast more explicit", "chisel3")
- final def toSInt(): SInt = asSInt
+ final def toSInt(): SInt = do_asSInt(DeprecatedSourceInfo)
@deprecated("Use asUInt, which makes the reinterpret cast more explicit", "chisel3")
- final def toUInt(): UInt = asUInt
+ final def toUInt(): UInt = do_asUInt(DeprecatedSourceInfo)
+
+ final def toBool(): Bool = macro SourceInfoTransform.noArg
- def toBool(): Bool = width match {
+ def do_toBool(implicit sourceInfo: SourceInfo): Bool = {
+ width match {
case KnownWidth(1) => this(0)
case _ => throwException(s"can't covert UInt<$width> to Bool")
}
+ }
/** Returns this wire concatenated with `other`, where this wire forms the
* most significant part and `other` forms the least significant part.
*
* The width of the output is sum of the inputs.
*/
- def ## (other: Bits): UInt = {
- val w = this.width + other.width
- pushOp(DefPrim(UInt(w), ConcatOp, this.ref, other.ref))
+ final def ## (that: Bits): UInt = macro SourceInfoTransform.thatArg
+
+ def do_## (that: Bits)(implicit sourceInfo: SourceInfo): UInt = {
+ val w = this.width + that.width
+ pushOp(DefPrim(sourceInfo, UInt(w), ConcatOp, this.ref, that.ref))
}
@deprecated("Use asBits, which makes the reinterpret cast more explicit and actually returns Bits", "chisel3")
- override def toBits: UInt = asUInt
+ override def toBits: UInt = do_asUInt(DeprecatedSourceInfo)
- override def fromBits(n: Bits): this.type = {
- val res = Wire(this).asInstanceOf[this.type]
- res := n
+ override def do_fromBits(that: Bits)(implicit sourceInfo: SourceInfo): this.type = {
+ val res = Wire(this, null).asInstanceOf[this.type]
+ res := that
res
}
}
@@ -223,7 +279,9 @@ abstract trait Num[T <: Data] {
/** Outputs the sum of `this` and `b`. The resulting width is the max of the
* operands plus 1 (should not overflow).
*/
- def + (b: T): T
+ final def + (that: T): T = macro SourceInfoTransform.thatArg
+
+ def do_+ (that: T)(implicit sourceInfo: SourceInfo): T
/** Outputs the product of `this` and `b`. The resulting width is the sum of
* the operands.
@@ -231,46 +289,68 @@ abstract trait Num[T <: Data] {
* @note can generate a single-cycle multiplier, which can result in
* significant cycle time and area costs
*/
- def * (b: T): T
+ final def * (that: T): T = macro SourceInfoTransform.thatArg
+
+ def do_* (that: T)(implicit sourceInfo: SourceInfo): T
/** Outputs the quotient of `this` and `b`.
*
* TODO: full rules
*/
- def / (b: T): T
+ final def / (that: T): T = macro SourceInfoTransform.thatArg
- def % (b: T): T
+ def do_/ (that: T)(implicit sourceInfo: SourceInfo): T
+
+ final def % (that: T): T = macro SourceInfoTransform.thatArg
+
+ def do_% (that: T)(implicit sourceInfo: SourceInfo): T
/** Outputs the difference of `this` and `b`. The resulting width is the max
* of the operands plus 1 (should not overflow).
*/
- def - (b: T): T
+ final def - (that: T): T = macro SourceInfoTransform.thatArg
+
+ def do_- (that: T)(implicit sourceInfo: SourceInfo): T
/** Outputs true if `this` < `b`.
*/
- def < (b: T): Bool
+ final def < (that: T): Bool = macro SourceInfoTransform.thatArg
+
+ def do_< (that: T)(implicit sourceInfo: SourceInfo): Bool
/** Outputs true if `this` <= `b`.
*/
- def <= (b: T): Bool
+ final def <= (that: T): Bool = macro SourceInfoTransform.thatArg
+
+ def do_<= (that: T)(implicit sourceInfo: SourceInfo): Bool
/** Outputs true if `this` > `b`.
*/
- def > (b: T): Bool
+ final def > (that: T): Bool = macro SourceInfoTransform.thatArg
+
+ def do_> (that: T)(implicit sourceInfo: SourceInfo): Bool
/** Outputs true if `this` >= `b`.
*/
- def >= (b: T): Bool
+ final def >= (that: T): Bool = macro SourceInfoTransform.thatArg
+
+ def do_>= (that: T)(implicit sourceInfo: SourceInfo): Bool
/** Outputs the minimum of `this` and `b`. The resulting width is the max of
* the operands.
*/
- def min(b: T): T = Mux(this < b, this.asInstanceOf[T], b)
+ final def min(that: T): T = macro SourceInfoTransform.thatArg
+
+ def do_min(that: T)(implicit sourceInfo: SourceInfo): T =
+ Mux(this < that, this.asInstanceOf[T], that)
/** Outputs the maximum of `this` and `b`. The resulting width is the max of
* the operands.
*/
- def max(b: T): T = Mux(this < b, b, this.asInstanceOf[T])
+ final def max(that: T): T = macro SourceInfoTransform.thatArg
+
+ def do_max(that: T)(implicit sourceInfo: SourceInfo): T =
+ Mux(this < that, that, this.asInstanceOf[T])
}
/** A data type for unsigned integers, represented as a binary bitvector.
@@ -285,76 +365,128 @@ sealed class UInt private[Chisel] (dir: Direction, width: Width, lit: Option[ULi
override private[Chisel] def fromInt(value: BigInt, width: Int): this.type =
UInt(value, width).asInstanceOf[this.type]
- override def := (that: Data): Unit = that match {
+ override def := (that: Data)(implicit sourceInfo: SourceInfo): Unit = that match {
case _: UInt => this connect that
case _ => this badConnect that
}
// TODO: refactor to share documentation with Num or add independent scaladoc
- def unary_- : UInt = UInt(0) - this
- def unary_-% : UInt = UInt(0) -% this
- def +& (other: UInt): UInt = binop(UInt((this.width max other.width) + 1), AddOp, other)
- def + (other: UInt): UInt = this +% other
- def +% (other: UInt): UInt = (this +& other) tail 1
- def -& (other: UInt): UInt = binop(UInt((this.width max other.width) + 1), SubOp, other)
- def - (other: UInt): UInt = this -% other
- def -% (other: UInt): UInt = (this -& other) tail 1
- def * (other: UInt): UInt = binop(UInt(this.width + other.width), TimesOp, other)
- def * (other: SInt): SInt = other * this
- def / (other: UInt): UInt = binop(UInt(this.width), DivideOp, other)
- def % (other: UInt): UInt = binop(UInt(this.width), RemOp, other)
-
- def & (other: UInt): UInt = binop(UInt(this.width max other.width), BitAndOp, other)
- def | (other: UInt): UInt = binop(UInt(this.width max other.width), BitOrOp, other)
- def ^ (other: UInt): UInt = binop(UInt(this.width max other.width), BitXorOp, other)
+ final def unary_- (): UInt = macro SourceInfoTransform.noArg
+ final def unary_-% (): UInt = macro SourceInfoTransform.noArg
+
+ def do_unary_- (implicit sourceInfo: SourceInfo) : UInt = UInt(0) - this
+ def do_unary_-% (implicit sourceInfo: SourceInfo): UInt = UInt(0) -% this
+
+ override def do_+ (that: UInt)(implicit sourceInfo: SourceInfo): UInt = this +% that
+ override def do_- (that: UInt)(implicit sourceInfo: SourceInfo): UInt = this -% that
+ override def do_/ (that: UInt)(implicit sourceInfo: SourceInfo): UInt =
+ binop(sourceInfo, UInt(this.width), DivideOp, that)
+ override def do_% (that: UInt)(implicit sourceInfo: SourceInfo): UInt =
+ binop(sourceInfo, UInt(this.width), RemOp, that)
+ override def do_* (that: UInt)(implicit sourceInfo: SourceInfo): UInt =
+ binop(sourceInfo, UInt(this.width + that.width), TimesOp, that)
+
+ final def * (that: SInt): SInt = macro SourceInfoTransform.thatArg
+ def do_* (that: SInt)(implicit sourceInfo: SourceInfo): SInt = that * this
+
+ final def +& (that: UInt): UInt = macro SourceInfoTransform.thatArg
+ final def +% (that: UInt): UInt = macro SourceInfoTransform.thatArg
+ final def -& (that: UInt): UInt = macro SourceInfoTransform.thatArg
+ final def -% (that: UInt): UInt = macro SourceInfoTransform.thatArg
+
+ def do_+& (that: UInt)(implicit sourceInfo: SourceInfo): UInt =
+ binop(sourceInfo, UInt((this.width max that.width) + 1), AddOp, that)
+ def do_+% (that: UInt)(implicit sourceInfo: SourceInfo): UInt =
+ (this +& that).tail(1)
+ def do_-& (that: UInt)(implicit sourceInfo: SourceInfo): UInt =
+ binop(sourceInfo, UInt((this.width max that.width) + 1), SubOp, that)
+ def do_-% (that: UInt)(implicit sourceInfo: SourceInfo): UInt =
+ (this -& that).tail(1)
+
+ final def & (that: UInt): UInt = macro SourceInfoTransform.thatArg
+ final def | (that: UInt): UInt = macro SourceInfoTransform.thatArg
+ final def ^ (that: UInt): UInt = macro SourceInfoTransform.thatArg
+
+ def do_& (that: UInt)(implicit sourceInfo: SourceInfo): UInt =
+ binop(sourceInfo, UInt(this.width max that.width), BitAndOp, that)
+ def do_| (that: UInt)(implicit sourceInfo: SourceInfo): UInt =
+ binop(sourceInfo, UInt(this.width max that.width), BitOrOp, that)
+ def do_^ (that: UInt)(implicit sourceInfo: SourceInfo): UInt =
+ binop(sourceInfo, UInt(this.width max that.width), BitXorOp, that)
/** Returns this wire bitwise-inverted. */
- def unary_~ : UInt = unop(UInt(width = width), BitNotOp)
+ def do_unary_~ (implicit sourceInfo: SourceInfo): UInt =
+ unop(sourceInfo, UInt(width = width), BitNotOp)
// REVIEW TODO: Can this be defined on Bits?
- def orR: Bool = this != UInt(0)
- def andR: Bool = ~this === UInt(0)
- def xorR: Bool = redop(XorReduceOp)
-
- def < (other: UInt): Bool = compop(LessOp, other)
- def > (other: UInt): Bool = compop(GreaterOp, other)
- def <= (other: UInt): Bool = compop(LessEqOp, other)
- def >= (other: UInt): Bool = compop(GreaterEqOp, other)
- def != (other: UInt): Bool = compop(NotEqualOp, other)
- def =/= (other: UInt): Bool = compop(NotEqualOp, other)
- def === (other: UInt): Bool = compop(EqualOp, other)
- def unary_! : Bool = this === Bits(0)
-
- // REVIEW TODO: Can these also not be defined on Bits?
- def << (other: Int): UInt = binop(UInt(this.width + other), ShiftLeftOp, other)
- def << (other: BigInt): UInt = this << other.toInt
- def << (other: UInt): UInt = binop(UInt(this.width.dynamicShiftLeft(other.width)), DynamicShiftLeftOp, other)
- def >> (other: Int): UInt = binop(UInt(this.width.shiftRight(other)), ShiftRightOp, other)
- def >> (other: BigInt): UInt = this >> other.toInt
- def >> (other: UInt): UInt = binop(UInt(this.width), DynamicShiftRightOp, other)
-
- def bitSet(off: UInt, dat: Bool): UInt = {
+ final def orR(): Bool = macro SourceInfoTransform.noArg
+ final def andR(): Bool = macro SourceInfoTransform.noArg
+ final def xorR(): Bool = macro SourceInfoTransform.noArg
+
+ def do_orR(implicit sourceInfo: SourceInfo): Bool = this != UInt(0)
+ def do_andR(implicit sourceInfo: SourceInfo): Bool = ~this === UInt(0)
+ def do_xorR(implicit sourceInfo: SourceInfo): Bool = redop(sourceInfo, XorReduceOp)
+
+ override def do_< (that: UInt)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, LessOp, that)
+ override def do_> (that: UInt)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, GreaterOp, that)
+ override def do_<= (that: UInt)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, LessEqOp, that)
+ override def do_>= (that: UInt)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, GreaterEqOp, that)
+
+ final def != (that: UInt): Bool = macro SourceInfoTransform.thatArg
+ final def =/= (that: UInt): Bool = macro SourceInfoTransform.thatArg
+ final def === (that: UInt): Bool = macro SourceInfoTransform.thatArg
+
+ def do_!= (that: UInt)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, NotEqualOp, that)
+ def do_=/= (that: UInt)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, NotEqualOp, that)
+ def do_=== (that: UInt)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, EqualOp, that)
+
+ final def unary_! () : Bool = macro SourceInfoTransform.noArg
+
+ def do_unary_! (implicit sourceInfo: SourceInfo) : Bool = this === Bits(0)
+
+ override def do_<< (that: Int)(implicit sourceInfo: SourceInfo): UInt =
+ binop(sourceInfo, UInt(this.width + that), ShiftLeftOp, that)
+ override def do_<< (that: BigInt)(implicit sourceInfo: SourceInfo): UInt =
+ this << that.toInt
+ override def do_<< (that: UInt)(implicit sourceInfo: SourceInfo): UInt =
+ binop(sourceInfo, UInt(this.width.dynamicShiftLeft(that.width)), DynamicShiftLeftOp, that)
+ override def do_>> (that: Int)(implicit sourceInfo: SourceInfo): UInt =
+ binop(sourceInfo, UInt(this.width.shiftRight(that)), ShiftRightOp, that)
+ override def do_>> (that: BigInt)(implicit sourceInfo: SourceInfo): UInt =
+ this >> that.toInt
+ override def do_>> (that: UInt)(implicit sourceInfo: SourceInfo): UInt =
+ binop(sourceInfo, UInt(this.width), DynamicShiftRightOp, that)
+
+ final def bitSet(off: UInt, dat: Bool): UInt = macro UIntTransform.bitset
+
+ def do_bitSet(off: UInt, dat: Bool)(implicit sourceInfo: SourceInfo): UInt = {
val bit = UInt(1, 1) << off
Mux(dat, this | bit, ~(~this | bit))
}
- def === (that: BitPat): Bool = that === this
- def != (that: BitPat): Bool = that != this
- def =/= (that: BitPat): Bool = that =/= this
+ final def === (that: BitPat): Bool = macro SourceInfoTransform.thatArg
+ final def != (that: BitPat): Bool = macro SourceInfoTransform.thatArg
+ final def =/= (that: BitPat): Bool = macro SourceInfoTransform.thatArg
+
+ def do_=== (that: BitPat)(implicit sourceInfo: SourceInfo): Bool = that === this
+ def do_!= (that: BitPat)(implicit sourceInfo: SourceInfo): Bool = that != this
+ def do_=/= (that: BitPat)(implicit sourceInfo: SourceInfo): Bool = that =/= this
/** Returns this UInt as a [[SInt]] with an additional zero in the MSB.
*/
// TODO: this eventually will be renamed as toSInt, once the existing toSInt
// completes its deprecation phase.
- def zext(): SInt = pushOp(DefPrim(SInt(width + 1), ConvertOp, ref))
+ final def zext(): SInt = macro SourceInfoTransform.noArg
+ def do_zext(implicit sourceInfo: SourceInfo): SInt =
+ pushOp(DefPrim(sourceInfo, SInt(width + 1), ConvertOp, ref))
/** Returns this UInt as a [[SInt]], without changing width or bit value. The
* SInt is not guaranteed to have the same value (for example, if the MSB is
* high, it will be interpreted as a negative value).
*/
- def asSInt(): SInt = pushOp(DefPrim(SInt(width), AsSIntOp, ref))
-
- def asUInt(): UInt = this
+ override def do_asSInt(implicit sourceInfo: SourceInfo): SInt =
+ pushOp(DefPrim(sourceInfo, SInt(width), AsSIntOp, ref))
+ override def do_asUInt(implicit sourceInfo: SourceInfo): UInt = this
}
// This is currently a factory because both Bits and UInt inherit it.
@@ -415,7 +547,7 @@ sealed class SInt private (dir: Direction, width: Width, lit: Option[SLit] = Non
new SInt(dir, w).asInstanceOf[this.type]
private[Chisel] def toType = s"SInt$width"
- override def := (that: Data): Unit = that match {
+ override def := (that: Data)(implicit sourceInfo: SourceInfo): Unit = that match {
case _: SInt => this connect that
case _ => this badConnect that
}
@@ -423,50 +555,94 @@ sealed class SInt private (dir: Direction, width: Width, lit: Option[SLit] = Non
override private[Chisel] def fromInt(value: BigInt, width: Int): this.type =
SInt(value, width).asInstanceOf[this.type]
- def unary_- : SInt = SInt(0) - this
- def unary_-% : SInt = SInt(0) -% this
- /** add (width +1) operator */
- def +& (other: SInt): SInt = binop(SInt((this.width max other.width) + 1), AddOp, other)
+ final def unary_- (): SInt = macro SourceInfoTransform.noArg
+ final def unary_-% (): SInt = macro SourceInfoTransform.noArg
+
+ def unary_- (implicit sourceInfo: SourceInfo): SInt = SInt(0) - this
+ def unary_-% (implicit sourceInfo: SourceInfo): SInt = SInt(0) -% this
+
/** add (default - no growth) operator */
- def + (other: SInt): SInt = this +% other
+ override def do_+ (that: SInt)(implicit sourceInfo: SourceInfo): SInt =
+ this +% that
+ /** subtract (default - no growth) operator */
+ override def do_- (that: SInt)(implicit sourceInfo: SourceInfo): SInt =
+ this -% that
+ override def do_* (that: SInt)(implicit sourceInfo: SourceInfo): SInt =
+ binop(sourceInfo, SInt(this.width + that.width), TimesOp, that)
+ override def do_/ (that: SInt)(implicit sourceInfo: SourceInfo): SInt =
+ binop(sourceInfo, SInt(this.width), DivideOp, that)
+ override def do_% (that: SInt)(implicit sourceInfo: SourceInfo): SInt =
+ binop(sourceInfo, SInt(this.width), RemOp, that)
+
+ final def * (that: UInt): SInt = macro SourceInfoTransform.thatArg
+ def do_* (that: UInt)(implicit sourceInfo: SourceInfo): SInt =
+ binop(sourceInfo, SInt(this.width + that.width), TimesOp, that)
+
+ /** add (width +1) operator */
+ final def +& (that: SInt): SInt = macro SourceInfoTransform.thatArg
/** add (no growth) operator */
- def +% (other: SInt): SInt = (this +& other).tail(1).asSInt
+ final def +% (that: SInt): SInt = macro SourceInfoTransform.thatArg
/** subtract (width +1) operator */
- def -& (other: SInt): SInt = binop(SInt((this.width max other.width) + 1), SubOp, other)
- /** subtract (default - no growth) operator */
- def - (other: SInt): SInt = this -% other
+ final def -& (that: SInt): SInt = macro SourceInfoTransform.thatArg
/** subtract (no growth) operator */
- def -% (other: SInt): SInt = (this -& other).tail(1).asSInt
- def * (other: SInt): SInt = binop(SInt(this.width + other.width), TimesOp, other)
- def * (other: UInt): SInt = binop(SInt(this.width + other.width), TimesOp, other)
- def / (other: SInt): SInt = binop(SInt(this.width), DivideOp, other)
- def % (other: SInt): SInt = binop(SInt(this.width), RemOp, other)
-
- def & (other: SInt): SInt = binop(UInt(this.width max other.width), BitAndOp, other).asSInt
- def | (other: SInt): SInt = binop(UInt(this.width max other.width), BitOrOp, other).asSInt
- def ^ (other: SInt): SInt = binop(UInt(this.width max other.width), BitXorOp, other).asSInt
+ final def -% (that: SInt): SInt = macro SourceInfoTransform.thatArg
+
+ def do_+& (that: SInt)(implicit sourceInfo: SourceInfo): SInt =
+ binop(sourceInfo, SInt((this.width max that.width) + 1), AddOp, that)
+ def do_+% (that: SInt)(implicit sourceInfo: SourceInfo): SInt =
+ (this +& that).tail(1).asSInt
+ def do_-& (that: SInt)(implicit sourceInfo: SourceInfo): SInt =
+ binop(sourceInfo, SInt((this.width max that.width) + 1), SubOp, that)
+ def do_-% (that: SInt)(implicit sourceInfo: SourceInfo): SInt =
+ (this -& that).tail(1).asSInt
+
+ final def & (that: SInt): SInt = macro SourceInfoTransform.thatArg
+ final def | (that: SInt): SInt = macro SourceInfoTransform.thatArg
+ final def ^ (that: SInt): SInt = macro SourceInfoTransform.thatArg
+
+ def do_& (that: SInt)(implicit sourceInfo: SourceInfo): SInt =
+ binop(sourceInfo, UInt(this.width max that.width), BitAndOp, that).asSInt
+ def do_| (that: SInt)(implicit sourceInfo: SourceInfo): SInt =
+ binop(sourceInfo, UInt(this.width max that.width), BitOrOp, that).asSInt
+ def do_^ (that: SInt)(implicit sourceInfo: SourceInfo): SInt =
+ binop(sourceInfo, UInt(this.width max that.width), BitXorOp, that).asSInt
/** Returns this wire bitwise-inverted. */
- def unary_~ : SInt = unop(UInt(width = width), BitNotOp).asSInt
-
- def < (other: SInt): Bool = compop(LessOp, other)
- def > (other: SInt): Bool = compop(GreaterOp, other)
- def <= (other: SInt): Bool = compop(LessEqOp, other)
- def >= (other: SInt): Bool = compop(GreaterEqOp, other)
- def != (other: SInt): Bool = compop(NotEqualOp, other)
- def =/= (other: SInt): Bool = compop(NotEqualOp, other)
- def === (other: SInt): Bool = compop(EqualOp, other)
- def abs(): UInt = Mux(this < SInt(0), (-this).asUInt, this.asUInt)
-
- def << (other: Int): SInt = binop(SInt(this.width + other), ShiftLeftOp, other)
- def << (other: BigInt): SInt = this << other.toInt
- def << (other: UInt): SInt = binop(SInt(this.width.dynamicShiftLeft(other.width)), DynamicShiftLeftOp, other)
- def >> (other: Int): SInt = binop(SInt(this.width.shiftRight(other)), ShiftRightOp, other)
- def >> (other: BigInt): SInt = this >> other.toInt
- def >> (other: UInt): SInt = binop(SInt(this.width), DynamicShiftRightOp, other)
-
- def asUInt(): UInt = pushOp(DefPrim(UInt(this.width), AsUIntOp, ref))
- def asSInt(): SInt = this
+ def do_unary_~ (implicit sourceInfo: SourceInfo): SInt =
+ unop(sourceInfo, UInt(width = width), BitNotOp).asSInt
+
+ override def do_< (that: SInt)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, LessOp, that)
+ override def do_> (that: SInt)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, GreaterOp, that)
+ override def do_<= (that: SInt)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, LessEqOp, that)
+ override def do_>= (that: SInt)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, GreaterEqOp, that)
+
+ final def != (that: SInt): Bool = macro SourceInfoTransform.thatArg
+ final def =/= (that: SInt): Bool = macro SourceInfoTransform.thatArg
+ final def === (that: SInt): Bool = macro SourceInfoTransform.thatArg
+
+ def do_!= (that: SInt)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, NotEqualOp, that)
+ def do_=/= (that: SInt)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, NotEqualOp, that)
+ def do_=== (that: SInt)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, EqualOp, that)
+
+ final def abs(): UInt = macro SourceInfoTransform.noArg
+
+ def do_abs(implicit sourceInfo: SourceInfo): UInt = Mux(this < SInt(0), (-this).asUInt, this.asUInt)
+
+ override def do_<< (that: Int)(implicit sourceInfo: SourceInfo): SInt =
+ binop(sourceInfo, SInt(this.width + that), ShiftLeftOp, that)
+ override def do_<< (that: BigInt)(implicit sourceInfo: SourceInfo): SInt =
+ this << that.toInt
+ override def do_<< (that: UInt)(implicit sourceInfo: SourceInfo): SInt =
+ binop(sourceInfo, SInt(this.width.dynamicShiftLeft(that.width)), DynamicShiftLeftOp, that)
+ override def do_>> (that: Int)(implicit sourceInfo: SourceInfo): SInt =
+ binop(sourceInfo, SInt(this.width.shiftRight(that)), ShiftRightOp, that)
+ override def do_>> (that: BigInt)(implicit sourceInfo: SourceInfo): SInt =
+ this >> that.toInt
+ override def do_>> (that: UInt)(implicit sourceInfo: SourceInfo): SInt =
+ binop(sourceInfo, SInt(this.width), DynamicShiftRightOp, that)
+
+ override def do_asUInt(implicit sourceInfo: SourceInfo): UInt = pushOp(DefPrim(sourceInfo, UInt(this.width), AsUIntOp, ref))
+ override def do_asSInt(implicit sourceInfo: SourceInfo): SInt = this
}
object SInt {
@@ -510,20 +686,32 @@ sealed class Bool(dir: Direction, lit: Option[ULit] = None) extends UInt(dir, Wi
// REVIEW TODO: Why does this need to exist and have different conventions
// than Bits?
- def & (other: Bool): Bool = binop(Bool(), BitAndOp, other)
- def | (other: Bool): Bool = binop(Bool(), BitOrOp, other)
- def ^ (other: Bool): Bool = binop(Bool(), BitXorOp, other)
+ final def & (that: Bool): Bool = macro SourceInfoTransform.thatArg
+ final def | (that: Bool): Bool = macro SourceInfoTransform.thatArg
+ final def ^ (that: Bool): Bool = macro SourceInfoTransform.thatArg
+
+ def do_& (that: Bool)(implicit sourceInfo: SourceInfo): Bool =
+ binop(sourceInfo, Bool(), BitAndOp, that)
+ def do_| (that: Bool)(implicit sourceInfo: SourceInfo): Bool =
+ binop(sourceInfo, Bool(), BitOrOp, that)
+ def do_^ (that: Bool)(implicit sourceInfo: SourceInfo): Bool =
+ binop(sourceInfo, Bool(), BitXorOp, that)
/** Returns this wire bitwise-inverted. */
- override def unary_~ : Bool = unop(Bool(), BitNotOp)
+ override def do_unary_~ (implicit sourceInfo: SourceInfo): Bool =
+ unop(sourceInfo, Bool(), BitNotOp)
/** Outputs the logical OR of two Bools.
*/
- def || (that: Bool): Bool = this | that
+ def || (that: Bool): Bool = macro SourceInfoTransform.thatArg
+
+ def do_|| (that: Bool)(implicit sourceInfo: SourceInfo): Bool = this | that
/** Outputs the logical AND of two Bools.
*/
- def && (that: Bool): Bool = this & that
+ def && (that: Bool): Bool = macro SourceInfoTransform.thatArg
+
+ def do_&& (that: Bool)(implicit sourceInfo: SourceInfo): Bool = this & that
}
object Bool {
@@ -548,7 +736,10 @@ object Mux {
* val muxOut = Mux(data_in === UInt(3), UInt(3, 4), UInt(0, 4))
* }}}
*/
- def apply[T <: Data](cond: Bool, con: T, alt: T): T = (con, alt) match {
+ def apply[T <: Data](cond: Bool, con: T, alt: T): T = macro MuxTransform.apply[T]
+
+ def do_apply[T <: Data](cond: Bool, con: T, alt: T)(implicit sourceInfo: SourceInfo): T =
+ (con, alt) match {
// Handle Mux(cond, UInt, Bool) carefully so that the concrete type is UInt
case (c: Bool, a: Bool) => doMux(cond, c, a).asInstanceOf[T]
case (c: UInt, a: Bool) => doMux(cond, c, a << 0).asInstanceOf[T]
@@ -557,13 +748,13 @@ object Mux {
case _ => doAggregateMux(cond, con, alt)
}
- private def doMux[T <: Data](cond: Bool, con: T, alt: T): T = {
+ private def doMux[T <: Data](cond: Bool, con: T, alt: T)(implicit sourceInfo: SourceInfo): T = {
require(con.getClass == alt.getClass, s"can't Mux between ${con.getClass} and ${alt.getClass}")
val d = alt.cloneTypeWidth(con.width max alt.width)
- pushOp(DefPrim(d, MultiplexOp, cond.ref, con.ref, alt.ref))
+ pushOp(DefPrim(sourceInfo, d, MultiplexOp, cond.ref, con.ref, alt.ref))
}
- private def doAggregateMux[T <: Data](cond: Bool, con: T, alt: T): T = {
+ private def doAggregateMux[T <: Data](cond: Bool, con: T, alt: T)(implicit sourceInfo: SourceInfo): T = {
require(con.getClass == alt.getClass, s"can't Mux between ${con.getClass} and ${alt.getClass}")
for ((c, a) <- con.flatten zip alt.flatten)
require(c.width == a.width, "can't Mux between aggregates of different width")
diff --git a/chiselFrontend/src/main/scala/Chisel/BlackBox.scala b/chiselFrontend/src/main/scala/Chisel/BlackBox.scala
index be72934d..b634f021 100644
--- a/chiselFrontend/src/main/scala/Chisel/BlackBox.scala
+++ b/chiselFrontend/src/main/scala/Chisel/BlackBox.scala
@@ -4,6 +4,7 @@ package Chisel
import internal.Builder.pushCommand
import internal.firrtl.{ModuleIO, DefInvalid}
+import internal.sourceinfo.SourceInfo
/** Defines a black box, which is a module that can be referenced from within
* Chisel, but is not defined in the emitted Verilog. Useful for connecting
@@ -39,10 +40,10 @@ abstract class BlackBox extends Module {
// Don't setup clock, reset
// Cann't invalide io in one bunch, must invalidate each part separately
- override private[Chisel] def setupInParent(): this.type = _parent match {
+ override private[Chisel] def setupInParent(implicit sourceInfo: SourceInfo): this.type = _parent match {
case Some(p) => {
// Just init instance inputs
- for((_,port) <- ports) pushCommand(DefInvalid(port.ref))
+ for((_,port) <- ports) pushCommand(DefInvalid(sourceInfo, port.ref))
this
}
case None => this
diff --git a/chiselFrontend/src/main/scala/Chisel/Data.scala b/chiselFrontend/src/main/scala/Chisel/Data.scala
index 8879491c..d16843f7 100644
--- a/chiselFrontend/src/main/scala/Chisel/Data.scala
+++ b/chiselFrontend/src/main/scala/Chisel/Data.scala
@@ -2,9 +2,12 @@
package Chisel
+import scala.language.experimental.macros
+
import internal._
import internal.Builder.pushCommand
import internal.firrtl._
+import internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, UnlocatableSourceInfo, WireTransform, SourceInfoTransform}
sealed abstract class Direction(name: String) {
override def toString: String = name
@@ -48,19 +51,21 @@ abstract class Data(dirArg: Direction) extends HasId {
def asOutput: this.type = cloneType.overrideDirection(_ => OUTPUT, _ => false)
def flip(): this.type = cloneType.overrideDirection(_.flip, !_)
- private[Chisel] def badConnect(that: Data): Unit =
+ private[Chisel] def badConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit =
throwException(s"cannot connect ${this} and ${that}")
- private[Chisel] def connect(that: Data): Unit =
- pushCommand(Connect(this.lref, that.ref))
- private[Chisel] def bulkConnect(that: Data): Unit =
- pushCommand(BulkConnect(this.lref, that.lref))
+ private[Chisel] def connect(that: Data)(implicit sourceInfo: SourceInfo): Unit =
+ pushCommand(Connect(sourceInfo, this.lref, that.ref))
+ private[Chisel] def bulkConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit =
+ pushCommand(BulkConnect(sourceInfo, this.lref, that.lref))
private[Chisel] def lref: Node = Node(this)
private[Chisel] def ref: Arg = if (isLit) litArg.get else lref
private[Chisel] def cloneTypeWidth(width: Width): this.type
private[Chisel] def toType: String
- def := (that: Data): Unit = this badConnect that
- def <> (that: Data): Unit = this badConnect that
+ def := (that: Data)(implicit sourceInfo: SourceInfo): Unit = this badConnect that
+
+ def <> (that: Data)(implicit sourceInfo: SourceInfo): Unit = this badConnect that
+
def cloneType: this.type
def litArg(): Option[LitArg] = None
def litValue(): BigInt = litArg.get.num
@@ -90,14 +95,16 @@ abstract class Data(dirArg: Direction) extends HasId {
* @note does NOT check bit widths, may drop bits during assignment
* @note what fromBits assigs to must have known widths
*/
- def fromBits(n: Bits): this.type = {
+ def fromBits(that: Bits): this.type = macro SourceInfoTransform.thatArg
+
+ def do_fromBits(that: Bits)(implicit sourceInfo: SourceInfo): this.type = {
var i = 0
val wire = Wire(this.cloneType)
val bits =
- if (n.width.known && n.width.get >= wire.width.get) {
- n
+ if (that.width.known && that.width.get >= wire.width.get) {
+ that
} else {
- Wire(n.cloneTypeWidth(wire.width), init = n)
+ Wire(that.cloneTypeWidth(wire.width), init = that)
}
for (x <- wire.flatten) {
x := bits(i + x.getWidth-1, i)
@@ -110,23 +117,25 @@ abstract class Data(dirArg: Direction) extends HasId {
*
* This performs the inverse operation of fromBits(Bits).
*/
- def toBits(): UInt = SeqUtils.asUInt(this.flatten)
+ @deprecated("Use asBits, which makes the reinterpret cast more explicit and actually returns Bits", "chisel3")
+ def toBits(): UInt = SeqUtils.do_asUInt(this.flatten)(DeprecatedSourceInfo)
}
object Wire {
- def apply[T <: Data](t: T): T =
- makeWire(t, null.asInstanceOf[T])
+ def apply[T <: Data](t: T): T = macro WireTransform.apply[T]
+ // No source info since Scala macros don't yet support named / default arguments.
def apply[T <: Data](dummy: Int = 0, init: T): T =
- makeWire(null.asInstanceOf[T], init)
+ do_apply(null.asInstanceOf[T], init)(UnlocatableSourceInfo)
+ // No source info since Scala macros don't yet support named / default arguments.
def apply[T <: Data](t: T, init: T): T =
- makeWire(t, init)
+ do_apply(t, init)(UnlocatableSourceInfo)
- private def makeWire[T <: Data](t: T, init: T): T = {
+ def do_apply[T <: Data](t: T, init: T)(implicit sourceInfo: SourceInfo): T = {
val x = Reg.makeType(t, null.asInstanceOf[T], init)
- pushCommand(DefWire(x))
- pushCommand(DefInvalid(x.ref))
+ pushCommand(DefWire(sourceInfo, x))
+ pushCommand(DefInvalid(sourceInfo, x.ref))
if (init != null) {
x := init
}
@@ -145,7 +154,7 @@ sealed class Clock(dirArg: Direction) extends Element(dirArg, Width(1)) {
private[Chisel] def cloneTypeWidth(width: Width): this.type = cloneType
private[Chisel] def toType = "Clock"
- override def := (that: Data): Unit = that match {
+ override def := (that: Data)(implicit sourceInfo: SourceInfo): Unit = that match {
case _: Clock => this connect that
case _ => this badConnect that
}
diff --git a/chiselFrontend/src/main/scala/Chisel/Mem.scala b/chiselFrontend/src/main/scala/Chisel/Mem.scala
index 2958a287..e34d5499 100644
--- a/chiselFrontend/src/main/scala/Chisel/Mem.scala
+++ b/chiselFrontend/src/main/scala/Chisel/Mem.scala
@@ -2,23 +2,28 @@
package Chisel
+import scala.language.experimental.macros
+
import internal._
import internal.Builder.pushCommand
import internal.firrtl._
+import internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, UnlocatableSourceInfo, MemTransform}
object Mem {
@deprecated("Mem argument order should be size, t; this will be removed by the official release", "chisel3")
- def apply[T <: Data](t: T, size: Int): Mem[T] = apply(size, t)
+ def apply[T <: Data](t: T, size: Int): Mem[T] = do_apply(size, t)(UnlocatableSourceInfo)
/** Creates a combinational-read, sequential-write [[Mem]].
*
* @param size number of elements in the memory
* @param t data type of memory element
*/
- def apply[T <: Data](size: Int, t: T): Mem[T] = {
+ def apply[T <: Data](size: Int, t: T): Mem[T] = macro MemTransform.apply[T]
+
+ def do_apply[T <: Data](size: Int, t: T)(implicit sourceInfo: SourceInfo): Mem[T] = {
val mt = t.cloneType
val mem = new Mem(mt, size)
- pushCommand(DefMemory(mem, mt, size)) // TODO multi-clock
+ pushCommand(DefMemory(sourceInfo, mem, mt, size)) // TODO multi-clock
mem
}
}
@@ -34,12 +39,12 @@ sealed abstract class MemBase[T <: Data](t: T, val length: Int) extends HasId wi
/** Creates a read/write accessor into the memory with dynamic addressing.
* See the class documentation of the memory for more detailed information.
*/
- def apply(idx: UInt): T = makePort(idx, MemPortDirection.INFER)
+ def apply(idx: UInt): T = makePort(UnlocatableSourceInfo, idx, MemPortDirection.INFER)
/** Creates a read accessor into the memory with dynamic addressing. See the
* class documentation of the memory for more detailed information.
*/
- def read(idx: UInt): T = makePort(idx, MemPortDirection.READ)
+ def read(idx: UInt): T = makePort(UnlocatableSourceInfo, idx, MemPortDirection.READ)
/** Creates a write accessor into the memory.
*
@@ -47,7 +52,8 @@ sealed abstract class MemBase[T <: Data](t: T, val length: Int) extends HasId wi
* @param data new data to write
*/
def write(idx: UInt, data: T): Unit = {
- makePort(idx, MemPortDirection.WRITE) := data
+ implicit val sourceInfo = UnlocatableSourceInfo
+ makePort(UnlocatableSourceInfo, idx, MemPortDirection.WRITE) := data
}
/** Creates a masked write accessor into the memory.
@@ -60,7 +66,8 @@ sealed abstract class MemBase[T <: Data](t: T, val length: Int) extends HasId wi
* @note this is only allowed if the memory's element data type is a Vec
*/
def write(idx: UInt, data: T, mask: Seq[Bool]) (implicit evidence: T <:< Vec[_]): Unit = {
- val accessor = makePort(idx, MemPortDirection.WRITE).asInstanceOf[Vec[Data]]
+ implicit val sourceInfo = UnlocatableSourceInfo
+ val accessor = makePort(sourceInfo, idx, MemPortDirection.WRITE).asInstanceOf[Vec[Data]]
val dataVec = data.asInstanceOf[Vec[Data]]
if (accessor.length != dataVec.length) {
Builder.error(s"Mem write data must contain ${accessor.length} elements (found ${dataVec.length})")
@@ -72,8 +79,9 @@ sealed abstract class MemBase[T <: Data](t: T, val length: Int) extends HasId wi
when (cond) { port := datum }
}
- private def makePort(idx: UInt, dir: MemPortDirection): T =
- pushCommand(DefMemPort(t.cloneType, Node(this), dir, idx.ref, Node(idx._parent.get.clock))).id
+ private def makePort(sourceInfo: SourceInfo, idx: UInt, dir: MemPortDirection): T =
+ pushCommand(DefMemPort(sourceInfo,
+ t.cloneType, Node(this), dir, idx.ref, Node(idx._parent.get.clock))).id
}
/** A combinational-read, sequential-write memory.
@@ -89,17 +97,19 @@ sealed class Mem[T <: Data](t: T, length: Int) extends MemBase(t, length)
object SeqMem {
@deprecated("SeqMem argument order should be size, t; this will be removed by the official release", "chisel3")
- def apply[T <: Data](t: T, size: Int): SeqMem[T] = apply(size, t)
+ def apply[T <: Data](t: T, size: Int): SeqMem[T] = do_apply(size, t)(DeprecatedSourceInfo)
/** Creates a sequential-read, sequential-write [[SeqMem]].
*
* @param size number of elements in the memory
* @param t data type of memory element
*/
- def apply[T <: Data](size: Int, t: T): SeqMem[T] = {
+ def apply[T <: Data](size: Int, t: T): SeqMem[T] = macro MemTransform.apply[T]
+
+ def do_apply[T <: Data](size: Int, t: T)(implicit sourceInfo: SourceInfo): SeqMem[T] = {
val mt = t.cloneType
val mem = new SeqMem(mt, size)
- pushCommand(DefSeqMemory(mem, mt, size)) // TODO multi-clock
+ pushCommand(DefSeqMemory(sourceInfo, mem, mt, size)) // TODO multi-clock
mem
}
}
@@ -116,6 +126,7 @@ object SeqMem {
*/
sealed class SeqMem[T <: Data](t: T, n: Int) extends MemBase[T](t, n) {
def read(addr: UInt, enable: Bool): T = {
+ implicit val sourceInfo = UnlocatableSourceInfo
val a = Wire(UInt())
when (enable) { a := addr }
read(a)
diff --git a/chiselFrontend/src/main/scala/Chisel/Module.scala b/chiselFrontend/src/main/scala/Chisel/Module.scala
index 3e839cac..45744196 100644
--- a/chiselFrontend/src/main/scala/Chisel/Module.scala
+++ b/chiselFrontend/src/main/scala/Chisel/Module.scala
@@ -3,11 +3,13 @@
package Chisel
import scala.collection.mutable.{ArrayBuffer, HashSet}
+import scala.language.experimental.macros
import internal._
import internal.Builder.pushCommand
import internal.Builder.dynamicContext
import internal.firrtl._
+import internal.sourceinfo.{SourceInfo, InstTransform, UnlocatableSourceInfo}
object Module {
/** A wrapper method that all Module instantiations must be wrapped in
@@ -17,15 +19,21 @@ object Module {
*
* @return the input module `m` with Chisel metadata properly set
*/
- def apply[T <: Module](bc: => T): T = {
+ def apply[T <: Module](bc: => T): T = macro InstTransform.apply[T]
+
+ def do_apply[T <: Module](bc: => T)(implicit sourceInfo: SourceInfo): T = {
+ // Don't generate source info referencing parents inside a module, sincce this interferes with
+ // module de-duplication in FIRRTL emission.
+ val childSourceInfo = UnlocatableSourceInfo
+
val parent = dynamicContext.currentModule
val m = bc.setRefs()
- m._commands.prepend(DefInvalid(m.io.ref)) // init module outputs
+ m._commands.prepend(DefInvalid(childSourceInfo, m.io.ref)) // init module outputs
dynamicContext.currentModule = parent
val ports = m.computePorts
Builder.components += Component(m, m.name, ports, m._commands)
- pushCommand(DefInstance(m, ports))
- m.setupInParent()
+ pushCommand(DefInstance(sourceInfo, m, ports))
+ m.setupInParent(childSourceInfo)
}
}
@@ -70,14 +78,16 @@ extends HasId {
Port(port, if (port.dir == NO_DIR) bundleDir else port.dir)
}
- private[Chisel] def setupInParent(): this.type = _parent match {
- case Some(p) => {
- pushCommand(DefInvalid(io.ref)) // init instance inputs
- clock := override_clock.getOrElse(p.clock)
- reset := override_reset.getOrElse(p.reset)
- this
+ private[Chisel] def setupInParent(implicit sourceInfo: SourceInfo): this.type = {
+ _parent match {
+ case Some(p) => {
+ pushCommand(DefInvalid(sourceInfo, io.ref)) // init instance inputs
+ clock := override_clock.getOrElse(p.clock)
+ reset := override_reset.getOrElse(p.reset)
+ this
+ }
+ case None => this
}
- case None => this
}
private[Chisel] def setRefs(): this.type = {
diff --git a/chiselFrontend/src/main/scala/Chisel/Printf.scala b/chiselFrontend/src/main/scala/Chisel/Printf.scala
new file mode 100644
index 00000000..f068f637
--- /dev/null
+++ b/chiselFrontend/src/main/scala/Chisel/Printf.scala
@@ -0,0 +1,36 @@
+// See LICENSE for license details.
+
+package Chisel
+
+import scala.language.experimental.macros
+
+import internal._
+import internal.Builder.pushCommand
+import internal.firrtl._
+import internal.sourceinfo.SourceInfo
+
+object printf { // scalastyle:ignore object.name
+ /** Prints a message in simulation.
+ *
+ * Does not fire when in reset (defined as the encapsulating Module's
+ * reset). If your definition of reset is not the encapsulating Module's
+ * reset, you will need to gate this externally.
+ *
+ * May be called outside of a Module (like defined in a function), so
+ * functions using printf make the standard Module assumptions (single clock
+ * and single reset).
+ *
+ * @param fmt printf format string
+ * @param data format string varargs containing data to print
+ */
+ def apply(fmt: String, data: Bits*)(implicit sourceInfo: SourceInfo) {
+ when (!(Builder.dynamicContext.currentModule.get.reset)) {
+ printfWithoutReset(fmt, data:_*)
+ }
+ }
+
+ private[Chisel] def printfWithoutReset(fmt: String, data: Bits*)(implicit sourceInfo: SourceInfo) {
+ val clock = Builder.dynamicContext.currentModule.get.clock
+ pushCommand(Printf(sourceInfo, Node(clock), fmt, data.map((d: Bits) => d.ref)))
+ }
+}
diff --git a/chiselFrontend/src/main/scala/Chisel/Reg.scala b/chiselFrontend/src/main/scala/Chisel/Reg.scala
index e69061c5..c8faa5c9 100644
--- a/chiselFrontend/src/main/scala/Chisel/Reg.scala
+++ b/chiselFrontend/src/main/scala/Chisel/Reg.scala
@@ -5,6 +5,7 @@ package Chisel
import internal._
import internal.Builder.pushCommand
import internal.firrtl._
+import internal.sourceinfo.{SourceInfo, UnlocatableSourceInfo}
object Reg {
private[Chisel] def makeType[T <: Data](t: T = null, next: T = null, init: T = null): T = {
@@ -36,7 +37,18 @@ object Reg {
* is a valid value. In those cases, you can either use the outType only Reg
* constructor or pass in `null.asInstanceOf[T]`.
*/
- def apply[T <: Data](t: T = null, next: T = null, init: T = null): T = {
+ def apply[T <: Data](t: T = null, next: T = null, init: T = null): T =
+ // Scala macros can't (yet) handle named or default arguments.
+ do_apply(t, next, init)(UnlocatableSourceInfo)
+
+ /** Creates a register without initialization (reset is ignored). Value does
+ * not change unless assigned to (using the := operator).
+ *
+ * @param outType: data type for the register
+ */
+ def apply[T <: Data](outType: T): T = Reg[T](outType, null.asInstanceOf[T], null.asInstanceOf[T])
+
+ def do_apply[T <: Data](t: T, next: T, init: T)(implicit sourceInfo: SourceInfo): T = {
// TODO: write this in a way that doesn't need nulls (bad Scala style),
// null.asInstanceOf[T], and two constructors. Using Option types are an
// option, but introduces cumbersome syntax (wrap everything in a Some()).
@@ -47,20 +59,13 @@ object Reg {
val x = makeType(t, next, init)
val clock = Node(x._parent.get.clock) // TODO multi-clock
if (init == null) {
- pushCommand(DefReg(x, clock))
+ pushCommand(DefReg(sourceInfo, x, clock))
} else {
- pushCommand(DefRegInit(x, clock, Node(x._parent.get.reset), init.ref))
+ pushCommand(DefRegInit(sourceInfo, x, clock, Node(x._parent.get.reset), init.ref))
}
if (next != null) {
x := next
}
x
}
-
- /** Creates a register without initialization (reset is ignored). Value does
- * not change unless assigned to (using the := operator).
- *
- * @param outType: data type for the register
- */
- def apply[T <: Data](outType: T): T = Reg[T](outType, null.asInstanceOf[T], null.asInstanceOf[T])
}
diff --git a/chiselFrontend/src/main/scala/Chisel/SeqUtils.scala b/chiselFrontend/src/main/scala/Chisel/SeqUtils.scala
index c63f5735..e3e58cb4 100644
--- a/chiselFrontend/src/main/scala/Chisel/SeqUtils.scala
+++ b/chiselFrontend/src/main/scala/Chisel/SeqUtils.scala
@@ -2,9 +2,15 @@
package Chisel
+import scala.language.experimental.macros
+
+import internal.sourceinfo.{SourceInfo, SourceInfoTransform}
+
private[Chisel] object SeqUtils {
/** Equivalent to Cat(r(n-1), ..., r(0)) */
- def asUInt[T <: Bits](in: Seq[T]): UInt = {
+ def asUInt[T <: Bits](in: Seq[T]): UInt = macro SourceInfoTransform.inArg
+
+ def do_asUInt[T <: Bits](in: Seq[T])(implicit sourceInfo: SourceInfo): UInt = {
if (in.tail.isEmpty) {
in.head.asUInt
} else {
@@ -15,7 +21,9 @@ private[Chisel] object SeqUtils {
}
/** Counts the number of true Bools in a Seq */
- def count(in: Seq[Bool]): UInt = {
+ def count(in: Seq[Bool]): UInt = macro SourceInfoTransform.inArg
+
+ def do_count(in: Seq[Bool])(implicit sourceInfo: SourceInfo): UInt = {
if (in.size == 0) {
UInt(0)
} else if (in.size == 1) {
@@ -26,7 +34,9 @@ private[Chisel] object SeqUtils {
}
/** Returns data value corresponding to first true predicate */
- def priorityMux[T <: Bits](in: Seq[(Bool, T)]): T = {
+ def priorityMux[T <: Bits](in: Seq[(Bool, T)]): T = macro SourceInfoTransform.inArg
+
+ def do_priorityMux[T <: Bits](in: Seq[(Bool, T)])(implicit sourceInfo: SourceInfo): T = {
if (in.size == 1) {
in.head._2
} else {
@@ -35,7 +45,9 @@ private[Chisel] object SeqUtils {
}
/** Returns data value corresponding to lone true predicate */
- def oneHotMux[T <: Data](in: Iterable[(Bool, T)]): T = {
+ def oneHotMux[T <: Data](in: Iterable[(Bool, T)]): T = macro SourceInfoTransform.inArg
+
+ def do_oneHotMux[T <: Data](in: Iterable[(Bool, T)])(implicit sourceInfo: SourceInfo): T = {
if (in.tail.isEmpty) {
in.head._2
} else {
diff --git a/chiselFrontend/src/main/scala/Chisel/When.scala b/chiselFrontend/src/main/scala/Chisel/When.scala
index 5f6b02c5..90b3d1a5 100644
--- a/chiselFrontend/src/main/scala/Chisel/When.scala
+++ b/chiselFrontend/src/main/scala/Chisel/When.scala
@@ -2,9 +2,12 @@
package Chisel
+import scala.language.experimental.macros
+
import internal._
import internal.Builder.pushCommand
import internal.firrtl._
+import internal.sourceinfo.{SourceInfo}
object when { // scalastyle:ignore object.name
/** Create a `when` condition block, where whether a block of logic is
@@ -24,8 +27,8 @@ object when { // scalastyle:ignore object.name
* }
* }}}
*/
- def apply(cond: Bool)(block: => Unit): WhenContext = {
- new WhenContext(cond, !cond)(block)
+ def apply(cond: Bool)(block: => Unit)(implicit sourceInfo: SourceInfo): WhenContext = {
+ new WhenContext(sourceInfo, cond, !cond, block)
}
}
@@ -36,21 +39,21 @@ object when { // scalastyle:ignore object.name
* that both the condition is true and all the previous conditions have been
* false.
*/
-class WhenContext(cond: Bool, prevCond: => Bool)(block: => Unit) {
+final class WhenContext(sourceInfo: SourceInfo, cond: Bool, prevCond: => Bool, block: => Unit) {
/** This block of logic gets executed if above conditions have been false
* and this condition is true.
*/
- def elsewhen (elseCond: Bool)(block: => Unit): WhenContext = {
- new WhenContext(prevCond && elseCond, prevCond && !elseCond)(block)
+ def elsewhen (elseCond: Bool)(block: => Unit)(implicit sourceInfo: SourceInfo): WhenContext = {
+ new WhenContext(sourceInfo, prevCond && elseCond, prevCond && !elseCond, block)
}
/** This block of logic gets executed only if the above conditions were all
* false. No additional logic blocks may be appended past the `otherwise`.
*/
- def otherwise(block: => Unit): Unit =
- new WhenContext(prevCond, null)(block)
+ def otherwise(block: => Unit)(implicit sourceInfo: SourceInfo): Unit =
+ new WhenContext(sourceInfo, prevCond, null, block)
- pushCommand(WhenBegin(cond.ref))
+ pushCommand(WhenBegin(sourceInfo, cond.ref))
block
- pushCommand(WhenEnd())
+ pushCommand(WhenEnd(sourceInfo))
}
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/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) = {
diff --git a/coreMacros/src/main/scala/Chisel/internal/sourceinfo/SourceInfoTransform.scala b/coreMacros/src/main/scala/Chisel/internal/sourceinfo/SourceInfoTransform.scala
new file mode 100644
index 00000000..82ad5b9e
--- /dev/null
+++ b/coreMacros/src/main/scala/Chisel/internal/sourceinfo/SourceInfoTransform.scala
@@ -0,0 +1,156 @@
+// See LICENSE for license details.
+
+// This file transform macro definitions to explicitly add implicit source info to Chisel method
+// calls.
+
+package Chisel.internal.sourceinfo
+
+import scala.language.experimental.macros
+import scala.reflect.macros.blackbox.Context
+import scala.reflect.macros.whitebox
+
+
+/** Transforms a function call so that it can both provide implicit-style source information and
+ * have a chained apply call. Without macros, only one is possible, since having a implicit
+ * argument in the definition will cause the compiler to interpret a chained apply as an
+ * explicit implicit argument and give type errors.
+ *
+ * Instead of an implicit argument, the public-facing function no longer takes a SourceInfo at all.
+ * The macro transforms the public-facing function into a call to an internal function that takes
+ * an explicit SourceInfo by inserting an implicitly[SourceInfo] as the explicit argument.
+ */
+trait SourceInfoTransformMacro {
+ val c: Context
+ import c.universe._
+ def thisObj = c.prefix.tree
+ def implicitSourceInfo = q"implicitly[_root_.Chisel.internal.sourceinfo.SourceInfo]"
+}
+
+class WireTransform(val c: Context) extends SourceInfoTransformMacro {
+ import c.universe._
+ def apply[T: c.WeakTypeTag](t: c.Tree): c.Tree = {
+ val tpe = weakTypeOf[T]
+ q"$thisObj.do_apply($t, null.asInstanceOf[$tpe])($implicitSourceInfo)"
+ }
+}
+
+class UIntTransform(val c: Context) extends SourceInfoTransformMacro {
+ import c.universe._
+ def bitset(off: c.Tree, dat: c.Tree): c.Tree = {
+ q"$thisObj.do_bitSet($off, $dat)($implicitSourceInfo)"
+ }
+}
+
+// Module instantiation transform
+class InstTransform(val c: Context) extends SourceInfoTransformMacro {
+ import c.universe._
+ def apply[T: c.WeakTypeTag](bc: c.Tree): c.Tree = {
+ q"$thisObj.do_apply($bc)($implicitSourceInfo)"
+ }
+}
+
+class MemTransform(val c: Context) extends SourceInfoTransformMacro {
+ import c.universe._
+ def apply[T: c.WeakTypeTag](size: c.Tree, t: c.Tree): c.Tree = {
+ q"$thisObj.do_apply($size, $t)($implicitSourceInfo)"
+ }
+}
+
+class RegTransform(val c: Context) extends SourceInfoTransformMacro {
+ import c.universe._
+ def apply[T: c.WeakTypeTag](t: c.Tree): c.Tree = {
+ val tpe = weakTypeOf[T]
+ q"$thisObj.do_apply($t, null.asInstanceOf[$tpe], null.asInstanceOf[$tpe])($implicitSourceInfo)"
+ }
+}
+
+class MuxTransform(val c: Context) extends SourceInfoTransformMacro {
+ import c.universe._
+ def apply[T: c.WeakTypeTag](cond: c.Tree, con: c.Tree, alt: c.Tree): c.Tree = {
+ val tpe = weakTypeOf[T]
+ q"$thisObj.do_apply[$tpe]($cond, $con, $alt)($implicitSourceInfo)"
+ }
+}
+
+class VecTransform(val c: Context) extends SourceInfoTransformMacro {
+ import c.universe._
+ def apply_elts(elts: c.Tree): c.Tree = {
+ q"$thisObj.do_apply($elts)($implicitSourceInfo)"
+ }
+ def apply_elt0(elt0: c.Tree, elts: c.Tree*): c.Tree = {
+ q"$thisObj.do_apply($elt0, ..$elts)($implicitSourceInfo)"
+ }
+ def tabulate(n: c.Tree)(gen: c.Tree): c.Tree = {
+ q"$thisObj.do_tabulate($n)($gen)($implicitSourceInfo)"
+ }
+ def fill(n: c.Tree)(gen: c.Tree): c.Tree = {
+ q"$thisObj.do_fill($n)($gen)($implicitSourceInfo)"
+ }
+ def contains(x: c.Tree)(ev: c.Tree): c.Tree = {
+ q"$thisObj.do_contains($x)($implicitSourceInfo, $ev)"
+ }
+}
+
+/** "Automatic" source information transform / insertion macros, which generate the function name
+ * based on the macro invocation (instead of explicitly writing out every transform).
+ */
+abstract class AutoSourceTransform extends SourceInfoTransformMacro {
+ import c.universe._
+ /** Returns the TermName of the transformed function, which is the applied function name with do_
+ * prepended.
+ */
+ def doFuncTerm = {
+ val funcName = c.macroApplication match {
+ case q"$_.$funcName[..$_](...$_)" => funcName
+ case _ => throw new Exception(s"Chisel Internal Error: Could not resolve function name from macro application: ${showCode(c.macroApplication)}")
+ }
+ TermName("do_" + funcName)
+ }
+}
+
+class SourceInfoTransform(val c: Context) extends AutoSourceTransform {
+ import c.universe._
+
+ def noArg(): c.Tree = {
+ q"$thisObj.$doFuncTerm($implicitSourceInfo)"
+ }
+
+ def thatArg(that: c.Tree): c.Tree = {
+ q"$thisObj.$doFuncTerm($that)($implicitSourceInfo)"
+ }
+
+ def nArg(n: c.Tree): c.Tree = {
+ q"$thisObj.$doFuncTerm($n)($implicitSourceInfo)"
+ }
+
+ def pArg(p: c.Tree): c.Tree = {
+ q"$thisObj.$doFuncTerm($p)($implicitSourceInfo)"
+ }
+
+ def inArg(in: c.Tree): c.Tree = {
+ q"$thisObj.$doFuncTerm($in)($implicitSourceInfo)"
+ }
+
+ def xArg(x: c.Tree): c.Tree = {
+ q"$thisObj.$doFuncTerm($x)($implicitSourceInfo)"
+ }
+
+ def xyArg(x: c.Tree, y: c.Tree): c.Tree = {
+ q"$thisObj.$doFuncTerm($x, $y)($implicitSourceInfo)"
+ }
+}
+
+/** Special whitebox version of the blackbox SourceInfoTransform, used when fun things need to happen to satisfy the
+ * type system while preventing the use of macro overrides.
+ */
+class SourceInfoWhiteboxTransform(val c: whitebox.Context) extends AutoSourceTransform {
+ import c.universe._
+
+ def noArg(): c.Tree = {
+ q"$thisObj.$doFuncTerm($implicitSourceInfo)"
+ }
+
+ def thatArg(that: c.Tree): c.Tree = {
+ q"$thisObj.$doFuncTerm($that)($implicitSourceInfo)"
+ }
+}
diff --git a/chiselFrontend/src/main/scala/Chisel/internal/firrtl/Emitter.scala b/src/main/scala/Chisel/internal/firrtl/Emitter.scala
index 34547503..7ca3268a 100644
--- a/chiselFrontend/src/main/scala/Chisel/internal/firrtl/Emitter.scala
+++ b/src/main/scala/Chisel/internal/firrtl/Emitter.scala
@@ -2,6 +2,7 @@
package Chisel.internal.firrtl
import Chisel._
+import Chisel.internal.sourceinfo.{NoSourceInfo, SourceLine}
private[Chisel] object Emitter {
def emit(circuit: Circuit): String = new Emitter(circuit).toString
@@ -12,30 +13,36 @@ private class Emitter(circuit: Circuit) {
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"
- }
+ private def emit(e: Command, ctx: Component): String = {
+ val firrtlLine = 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"
+ case w: WhenBegin =>
+ indent()
+ s"when ${w.pred.fullName(ctx)} :"
+ case _: WhenEnd =>
+ unindent()
+ s"skip"
+ }
+ e.sourceInfo match {
+ case SourceLine(filename, line, col) => s"${firrtlLine} @[${filename} ${line}:${col}] "
+ case _: NoSourceInfo => firrtlLine
+ }
}
// Map of Module FIRRTL definition to FIRRTL name, if it has been emitted already.
diff --git a/src/main/scala/Chisel/testers/BasicTester.scala b/src/main/scala/Chisel/testers/BasicTester.scala
index d3e9e7c8..b8c1494a 100644
--- a/src/main/scala/Chisel/testers/BasicTester.scala
+++ b/src/main/scala/Chisel/testers/BasicTester.scala
@@ -3,9 +3,12 @@
package Chisel.testers
import Chisel._
+import scala.language.experimental.macros
+
import internal._
import internal.Builder.pushCommand
import internal.firrtl._
+import internal.sourceinfo.SourceInfo
class BasicTester extends Module {
// The testbench has no IOs, rather it should communicate using printf, assert, and stop.
@@ -19,9 +22,10 @@ class BasicTester extends Module {
* reset). If your definition of reset is not the encapsulating Module's
* reset, you will need to gate this externally.
*/
- def stop() {
+ def stop()(implicit sourceInfo: SourceInfo) {
+ // TODO: rewrite this using library-style SourceInfo passing.
when (!reset) {
- pushCommand(Stop(Node(clock), 0))
+ pushCommand(Stop(sourceInfo, Node(clock), 0))
}
}