diff options
Diffstat (limited to 'chiselFrontend/src/main/scala/Chisel')
15 files changed, 645 insertions, 403 deletions
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/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) = { |
