diff --git a/core/src/main/scala/chisel3/BitsImpl.scala b/core/src/main/scala/chisel3/BitsImpl.scala index f28dcc3ce3..3c991e39a9 100644 --- a/core/src/main/scala/chisel3/BitsImpl.scala +++ b/core/src/main/scala/chisel3/BitsImpl.scala @@ -142,24 +142,29 @@ private[chisel3] trait BitsImpl extends Element { self: Bits => _applyImpl(castToInt(x, "High index"), castToInt(y, "Low index")) private[chisel3] def unop[T <: Data](sourceInfo: SourceInfo, dest: T, op: PrimOp): T = { + implicit val info: SourceInfo = sourceInfo requireIsHardware(this, "bits operated on") pushOp(DefPrim(sourceInfo, dest, op, this.ref)) } private[chisel3] def binop[T <: Data](sourceInfo: SourceInfo, dest: T, op: PrimOp, other: BigInt): T = { + implicit val info: SourceInfo = sourceInfo requireIsHardware(this, "bits operated on") pushOp(DefPrim(sourceInfo, dest, op, this.ref, ILit(other))) } private[chisel3] def binop[T <: Data](sourceInfo: SourceInfo, dest: T, op: PrimOp, other: Bits): T = { + implicit val info: SourceInfo = sourceInfo requireIsHardware(this, "bits operated on") requireIsHardware(other, "bits operated on") pushOp(DefPrim(sourceInfo, dest, op, this.ref, other.ref)) } private[chisel3] def compop(sourceInfo: SourceInfo, op: PrimOp, other: Bits): Bool = { + implicit val info: SourceInfo = sourceInfo requireIsHardware(this, "bits operated on") requireIsHardware(other, "bits operated on") pushOp(DefPrim(sourceInfo, Bool(), op, this.ref, other.ref)) } private[chisel3] def redop(sourceInfo: SourceInfo, op: PrimOp): Bool = { + implicit val info: SourceInfo = sourceInfo requireIsHardware(this, "bits operated on") pushOp(DefPrim(sourceInfo, Bool(), op, this.ref)) } diff --git a/core/src/main/scala/chisel3/ChiselEnumImpl.scala b/core/src/main/scala/chisel3/ChiselEnumImpl.scala index e6d63509b9..da799c75ef 100644 --- a/core/src/main/scala/chisel3/ChiselEnumImpl.scala +++ b/core/src/main/scala/chisel3/ChiselEnumImpl.scala @@ -33,6 +33,7 @@ private[chisel3] abstract class EnumTypeImpl(private[chisel3] val factory: Chise override def cloneType: this.type = factory().asInstanceOf[this.type] private[chisel3] def compop(sourceInfo: SourceInfo, op: PrimOp, other: EnumType): Bool = { + implicit val info: SourceInfo = sourceInfo requireIsHardware(this, "bits operated on") requireIsHardware(other, "bits operated on") diff --git a/core/src/main/scala/chisel3/DataImpl.scala b/core/src/main/scala/chisel3/DataImpl.scala index 062aba1f1f..9f902999be 100644 --- a/core/src/main/scala/chisel3/DataImpl.scala +++ b/core/src/main/scala/chisel3/DataImpl.scala @@ -697,16 +697,13 @@ private[chisel3] trait DataImpl extends HasId with NamedComponent { self: Data = } } private[chisel3] def visibleFromBlock: Option[SourceInfo] = MonoConnect.checkBlockVisibility(this) - private[chisel3] def requireVisible(): Unit = { + private[chisel3] def requireVisible()(implicit info: SourceInfo): Unit = { if (!isVisibleFromModule) { throwException(s"operand '$this' is not visible from the current module ${Builder.currentModule.get.name}") } visibleFromBlock match { - case Some(sourceInfo) => - throwException( - s"operand '$this' has escaped the scope of the block (${sourceInfo.makeMessage()}) in which it was constructed." - ) - case None => () + case Some(blockInfo) => MonoConnect.escapedScopeError(this, blockInfo) + case None => () } } @@ -727,7 +724,7 @@ private[chisel3] trait DataImpl extends HasId with NamedComponent { self: Data = } // Internal API: returns a ref, if bound - private[chisel3] def ref: Arg = { + private[chisel3] def ref(implicit info: SourceInfo): Arg = { def materializeWire(makeConst: Boolean = false): Arg = { if (!Builder.currentModule.isDefined) throwException(s"internal error: cannot materialize ref for $this") implicit val sourceInfo = UnlocatableSourceInfo diff --git a/core/src/main/scala/chisel3/MemImpl.scala b/core/src/main/scala/chisel3/MemImpl.scala index 5dcb5a3f8a..29f3e5fbf3 100644 --- a/core/src/main/scala/chisel3/MemImpl.scala +++ b/core/src/main/scala/chisel3/MemImpl.scala @@ -165,13 +165,14 @@ private[chisel3] trait MemBaseImpl[T <: Data] extends HasId with NamedComponent dir: MemPortDirection, clock: Clock ): T = { + implicit val info: SourceInfo = sourceInfo if (Builder.currentModule != _parent) { throwException( s"Cannot create a memory port in a different module (${Builder.currentModule.get.name}) than where the memory is (${_parent.get.name})." ) } requireIsHardware(idx, "memory port index") - val i = Vec.truncateIndex(idx, length)(sourceInfo) + val i = Vec.truncateIndex(idx, length) val port = pushCommand( DefMemPort(sourceInfo, t.cloneTypeFull, Node(this), dir, i.ref, clock.ref) diff --git a/core/src/main/scala/chisel3/Printable.scala b/core/src/main/scala/chisel3/Printable.scala index d7646ae5bf..a0dea3591f 100644 --- a/core/src/main/scala/chisel3/Printable.scala +++ b/core/src/main/scala/chisel3/Printable.scala @@ -2,6 +2,7 @@ package chisel3 +import chisel3.experimental.SourceInfo import chisel3.internal.firrtl.ir.Component import scala.collection.mutable @@ -49,7 +50,7 @@ sealed abstract class Printable { * @note This must be called after elaboration when Chisel nodes actually * have names */ - def unpack(ctx: Component): (String, Iterable[String]) + def unpack(ctx: Component)(implicit info: SourceInfo): (String, Iterable[String]) /** Unpack into a Seq of captured Bits arguments */ @@ -139,7 +140,7 @@ object Printable { StringContext(bufEscapeBackSlash.toSeq: _*).cf(data: _*) } - private[chisel3] def checkScope(message: Printable): Unit = { + private[chisel3] def checkScope(message: Printable)(implicit info: SourceInfo): Unit = { def getData(x: Printable): Seq[Data] = { x match { case y: FirrtlFormat => Seq(y.bits) @@ -155,7 +156,7 @@ object Printable { case class Printables(pables: Iterable[Printable]) extends Printable { require(pables.hasDefiniteSize, "Infinite-sized iterables are not supported!") - final def unpack(ctx: Component): (String, Iterable[String]) = { + final def unpack(ctx: Component)(implicit info: SourceInfo): (String, Iterable[String]) = { val (fmts, args) = pables.map(_.unpack(ctx)).unzip (fmts.mkString, args.flatten) } @@ -165,7 +166,7 @@ case class Printables(pables: Iterable[Printable]) extends Printable { /** Wrapper for printing Scala Strings */ case class PString(str: String) extends Printable { - final def unpack(ctx: Component): (String, Iterable[String]) = + final def unpack(ctx: Component)(implicit info: SourceInfo): (String, Iterable[String]) = (str.replaceAll("%", "%%"), List.empty) final def unpackArgs: Seq[Bits] = List.empty @@ -174,7 +175,7 @@ case class PString(str: String) extends Printable { /** Superclass for Firrtl format specifiers for Bits */ sealed abstract class FirrtlFormat(private[chisel3] val specifier: Char) extends Printable { def bits: Bits - def unpack(ctx: Component): (String, Iterable[String]) = { + def unpack(ctx: Component)(implicit info: SourceInfo): (String, Iterable[String]) = { (s"%$specifier", List(bits.ref.fullName(ctx))) } @@ -218,18 +219,19 @@ case class Character(bits: Bits) extends FirrtlFormat('c') /** Put innermost name (eg. field of bundle) */ case class Name(data: Data) extends Printable { - final def unpack(ctx: Component): (String, Iterable[String]) = (data.ref.name, List.empty) + final def unpack(ctx: Component)(implicit info: SourceInfo): (String, Iterable[String]) = (data.ref.name, List.empty) final def unpackArgs: Seq[Bits] = List.empty } /** Put full name within parent namespace (eg. bundleName.field) */ case class FullName(data: Data) extends Printable { - final def unpack(ctx: Component): (String, Iterable[String]) = (data.ref.fullName(ctx), List.empty) + final def unpack(ctx: Component)(implicit info: SourceInfo): (String, Iterable[String]) = + (data.ref.fullName(ctx), List.empty) final def unpackArgs: Seq[Bits] = List.empty } /** Represents escaped percents */ case object Percent extends Printable { - final def unpack(ctx: Component): (String, Iterable[String]) = ("%%", List.empty) + final def unpack(ctx: Component)(implicit info: SourceInfo): (String, Iterable[String]) = ("%%", List.empty) final def unpackArgs: Seq[Bits] = List.empty } diff --git a/core/src/main/scala/chisel3/When.scala b/core/src/main/scala/chisel3/When.scala index ce6d37b59c..c14e7ac414 100644 --- a/core/src/main/scala/chisel3/When.scala +++ b/core/src/main/scala/chisel3/When.scala @@ -150,7 +150,7 @@ final class WhenContext private[chisel3] ( // Create the `When` operation and run the `block` thunk inside the // `ifRegion`. Any commands that this thunk creates will be put inside this // block. - private val whenCommand = pushCommand(new When(sourceInfo, cond().ref)) + private val whenCommand = pushCommand(new When(sourceInfo, cond().ref(sourceInfo))) Builder.pushWhen(this) scope = Some(Scope.If) try { diff --git a/core/src/main/scala/chisel3/internal/Builder.scala b/core/src/main/scala/chisel3/internal/Builder.scala index 3f93f9b633..8199e2f5b2 100644 --- a/core/src/main/scala/chisel3/internal/Builder.scala +++ b/core/src/main/scala/chisel3/internal/Builder.scala @@ -268,7 +268,7 @@ private[chisel3] trait HasId extends chisel3.InstanceId { private[chisel3] def setRef(parent: Node, index: Int): Unit = setRef(LitIndex(parent, index)) private[chisel3] def setRef(parent: Node, index: UInt): Unit = index.litOption match { case Some(lit) if lit.isValidInt => setRef(LitIndex(parent, lit.intValue)) - case _ => setRef(Index(parent, index.ref)) + case _ => setRef(Index(parent, index.ref(UnlocatableSourceInfo))) } private[chisel3] def getRef: Arg = _ref.get private[chisel3] def getOptionRef: Option[Arg] = _ref diff --git a/core/src/main/scala/chisel3/internal/MonoConnect.scala b/core/src/main/scala/chisel3/internal/MonoConnect.scala index 212ed379be..18024007c7 100644 --- a/core/src/main/scala/chisel3/internal/MonoConnect.scala +++ b/core/src/main/scala/chisel3/internal/MonoConnect.scala @@ -52,14 +52,10 @@ private[chisel3] object MonoConnect { MonoConnectException( s"""${formatName(sink)} cannot be written from module ${source.parentNameOpt.getOrElse("(unknown)")}.""" ) - def SourceEscapedBlockScopeException(source: Data, blockInfo: SourceInfo) = - MonoConnectException( - s"Source ${formatName(source)} has escaped the scope of the block (${blockInfo.makeMessage()}) in which it was constructed." - ) - def SinkEscapedBlockScopeException(sink: Data, blockInfo: SourceInfo) = - MonoConnectException( - s"Sink ${formatName(sink)} has escaped the scope of the block (${blockInfo.makeMessage()}) in which it was constructed." - ) + def escapedScopeError(data: Data, blockInfo: SourceInfo)(implicit lineInfo: SourceInfo): Unit = { + val msg = s"'$data' has escaped the scope of the block (${blockInfo.makeMessage()}) in which it was constructed." + Builder.error(msg) + } def UnknownRelationException = MonoConnectException("Sink or source unavailable to current module.") // These are when recursing down aggregate types @@ -177,7 +173,7 @@ private[chisel3] object MonoConnect { context_mod ) ) { - pushCommand(Connect(sourceInfo, sinkReified.get.lref(sourceInfo), sourceReified.get.ref)) + pushCommand(Connect(sourceInfo, sinkReified.get.lref(sourceInfo), sourceReified.get.ref(sourceInfo))) } else { for (idx <- 0 until sink_v.length) { try { @@ -212,7 +208,7 @@ private[chisel3] object MonoConnect { context_mod ) ) { - pushCommand(Connect(sourceInfo, sinkReified.get.lref(sourceInfo), sourceReified.get.ref)) + pushCommand(Connect(sourceInfo, sinkReified.get.lref(sourceInfo), sourceReified.get.ref(sourceInfo))) } else { // For each field, descend with right for ((field, sink_sub) <- sink_r._elements) { @@ -288,12 +284,12 @@ private[chisel3] object MonoConnect { } checkBlockVisibility(sink) match { - case Some(blockInfo) => throw SinkEscapedBlockScopeException(sink, blockInfo) + case Some(blockInfo) => escapedScopeError(sink, blockInfo) case None => () } checkBlockVisibility(source) match { - case Some(blockInfo) => throw SourceEscapedBlockScopeException(source, blockInfo) + case Some(blockInfo) => escapedScopeError(source, blockInfo) case None => () } @@ -440,6 +436,7 @@ private[chisel3] object MonoConnect { sourceProp: Property[_], context: BaseModule ): Unit = { + implicit val info: SourceInfo = sourceInfo // Reify sink and source if they're views. val (sink, writable) = reify(sinkProp) val (source, _) = reify(sourceProp) @@ -449,11 +446,11 @@ private[chisel3] object MonoConnect { context match { case rm: RawModule => writable.reportIfReadOnlyUnit { - rm.addCommand(PropAssign(sourceInfo, sink.lref(sourceInfo), source.ref)) + rm.addCommand(PropAssign(sourceInfo, sink.lref, source.ref)) }(sourceInfo) case cls: Class => writable.reportIfReadOnlyUnit { - cls.addCommand(PropAssign(sourceInfo, sink.lref(sourceInfo), source.ref)) + cls.addCommand(PropAssign(sourceInfo, sink.lref, source.ref)) }(sourceInfo) case _ => throwException("Internal Error! Property connection can only occur within RawModule or Class.") } @@ -465,7 +462,7 @@ private[chisel3] object MonoConnect { sourceProbe: Data, context: BaseModule ): Unit = { - + implicit val info: SourceInfo = sourceInfo val (sink, writable) = reifyIdentityView(sinkProbe).getOrElse( throwException( s"If a DataView contains a Probe, it must resolve to one Data. $sinkProbe does not meet this criteria." @@ -480,7 +477,7 @@ private[chisel3] object MonoConnect { context match { case rm: RawModule => writable.reportIfReadOnlyUnit { - rm.addCommand(ProbeDefine(sourceInfo, sink.lref(sourceInfo), source.ref)) + rm.addCommand(ProbeDefine(sourceInfo, sink.lref, source.ref)) }(sourceInfo) // Nothing to push if an error. case _ => throwException("Internal Error! Probe connection can only occur within RawModule.") } @@ -519,8 +516,7 @@ private[chisel3] object checkConnect { // Import helpers and exception types. import MonoConnect.{ checkBlockVisibility, - SinkEscapedBlockScopeException, - SourceEscapedBlockScopeException, + escapedScopeError, UnknownRelationException, UnreadableSourceException, UnwritableSinkException @@ -598,12 +594,12 @@ private[chisel3] object checkConnect { else throw UnknownRelationException checkBlockVisibility(sink) match { - case Some(blockInfo) => throw SinkEscapedBlockScopeException(sink, blockInfo) + case Some(blockInfo) => escapedScopeError(sink, blockInfo)(sourceInfo) case None => () } checkBlockVisibility(source) match { - case Some(blockInfo) => throw SourceEscapedBlockScopeException(source, blockInfo) + case Some(blockInfo) => escapedScopeError(source, blockInfo)(sourceInfo) case None => () } } diff --git a/core/src/main/scala/chisel3/internal/firrtl/Converter.scala b/core/src/main/scala/chisel3/internal/firrtl/Converter.scala index 0ebe910c64..07b70a80ce 100644 --- a/core/src/main/scala/chisel3/internal/firrtl/Converter.scala +++ b/core/src/main/scala/chisel3/internal/firrtl/Converter.scala @@ -15,16 +15,19 @@ import scala.collection.immutable.{Queue, VectorBuilder, VectorMap} private[chisel3] object Converter { // TODO modeled on unpack method on Printable, refactor? - def unpack(pable: Printable, ctx: Component): (String, Seq[Arg]) = pable match { - case Printables(pables) => - val (fmts, args) = pables.map(p => unpack(p, ctx)).unzip - (fmts.mkString, args.flatten.toSeq) - case PString(str) => (str.replaceAll("%", "%%"), List.empty) - case format: FirrtlFormat => - ("%" + format.specifier, List(format.bits.ref)) - case Name(data) => (data.ref.name, List.empty) - case FullName(data) => (data.ref.fullName(ctx), List.empty) - case Percent => ("%%", List.empty) + def unpack(pable: Printable, ctx: Component, sourceInfo: SourceInfo): (String, Seq[Arg]) = { + implicit val info: SourceInfo = sourceInfo + pable match { + case Printables(pables) => + val (fmts, args) = pables.map(p => unpack(p, ctx, sourceInfo)).unzip + (fmts.mkString, args.flatten.toSeq) + case PString(str) => (str.replaceAll("%", "%%"), List.empty) + case format: FirrtlFormat => + ("%" + format.specifier, List(format.bits.ref)) + case Name(data) => (data.ref.name, List.empty) + case FullName(data) => (data.ref.fullName(ctx), List.empty) + case Percent => ("%%", List.empty) + } } private def reportInternalError(msg: String): Nothing = { @@ -191,7 +194,7 @@ private[chisel3] object Converter { case e @ Stop(_, info, clock, ret) => fir.Stop(convert(info), ret, convert(clock, ctx, info), firrtl.Utils.one, e.name) case e @ Printf(_, info, clock, pable) => - val (fmt, args) = unpack(pable, ctx) + val (fmt, args) = unpack(pable, ctx, info) fir.Print( convert(info), fir.StringLit(fmt), @@ -222,7 +225,7 @@ private[chisel3] object Converter { convert(probe, ctx, sourceInfo) ) case e @ Verification(_, op, info, clk, pred, pable) => - val (fmt, args) = unpack(pable, ctx) + val (fmt, args) = unpack(pable, ctx, info) val firOp = op match { case Formal.Assert => fir.Formal.Assert case Formal.Assume => fir.Formal.Assume @@ -388,7 +391,7 @@ private[chisel3] object Converter { case StringParam(value) => fir.StringParam(name, fir.StringLit(value)) case PrintableParam(value, id) => { val ctx = id._component.get - val (fmt, _) = unpack(value, ctx) + val (fmt, _) = unpack(value, ctx, UnlocatableSourceInfo) fir.StringParam(name, fir.StringLit(fmt)) } case RawParam(value) => fir.RawStringParam(name, value) diff --git a/core/src/main/scala/chisel3/properties/Class.scala b/core/src/main/scala/chisel3/properties/Class.scala index 61284e9a97..5deaec0182 100644 --- a/core/src/main/scala/chisel3/properties/Class.scala +++ b/core/src/main/scala/chisel3/properties/Class.scala @@ -124,7 +124,7 @@ case class ClassType private[chisel3] (name: String) { self => override def convert(value: Underlying, ctx: Component, info: SourceInfo): fir.Expression = Converter.convert(value, ctx, info) type Underlying = Arg - override def convertUnderlying(value: Property[ClassType] with self.Type) = value.ref + override def convertUnderlying(value: Property[ClassType] with self.Type, info: SourceInfo) = value.ref(info) } } def copy(name: String = this.name) = new ClassType(name) @@ -147,7 +147,7 @@ object AnyClassType { override def convert(value: Underlying, ctx: Component, info: SourceInfo): fir.Expression = Converter.convert(value, ctx, info) type Underlying = Arg - override def convertUnderlying(value: Property[ClassType] with AnyClassType) = value.ref + override def convertUnderlying(value: Property[ClassType] with AnyClassType, info: SourceInfo) = value.ref(info) } } diff --git a/core/src/main/scala/chisel3/properties/Property.scala b/core/src/main/scala/chisel3/properties/Property.scala index 2bdf440246..1226892ef0 100644 --- a/core/src/main/scala/chisel3/properties/Property.scala +++ b/core/src/main/scala/chisel3/properties/Property.scala @@ -41,7 +41,7 @@ sealed trait PropertyType[T] { /** Get convert from the raw type T to this type's internal, underlying representation */ - def convertUnderlying(value: T): Underlying + def convertUnderlying(value: T, info: SourceInfo): Underlying } /** Trait for PropertyTypes that may lookup themselves up during implicit resolution @@ -63,7 +63,7 @@ private[chisel3] trait SimplePropertyType[T] extends RecursivePropertyType[T] { final type Underlying = T def convert(value: T): fir.Expression def convert(value: T, ctx: ir.Component, info: SourceInfo): fir.Expression = convert(value) - def convertUnderlying(value: T): T = value + def convertUnderlying(value: T, info: SourceInfo): T = value } private[chisel3] class SeqPropertyType[A, F[A] <: Seq[A], PT <: PropertyType[A]](val tpe: PT) @@ -75,8 +75,8 @@ private[chisel3] class SeqPropertyType[A, F[A] <: Seq[A], PT <: PropertyType[A]] type Underlying = Seq[tpe.Underlying] override def convert(value: Underlying, ctx: ir.Component, info: SourceInfo): fir.Expression = fir.SequencePropertyValue(tpe.getPropertyType(), value.map(tpe.convert(_, ctx, info))) - override def convertUnderlying(value: F[A]) = - value.map(tpe.convertUnderlying(_)) + override def convertUnderlying(value: F[A], info: SourceInfo) = + value.map(v => tpe.convertUnderlying(v, info)) } /** This contains recursive versions of Seq PropertyTypes. These instances need be lower priority to prevent ambiguous implicit errors with the non-recursive versions. @@ -142,7 +142,7 @@ private[chisel3] object PropertyType extends LowPriorityPropertyTypeInstances { // these methods should never be called type Underlying = Nothing override def convert(value: Underlying, ctx: ir.Component, info: SourceInfo): fir.Expression = ??? - override def convertUnderlying(value: T) = ??? + override def convertUnderlying(value: T, info: SourceInfo) = ??? } implicit val stringPropertyTypeInstance: SimplePropertyType[String] = @@ -159,7 +159,7 @@ private[chisel3] object PropertyType extends LowPriorityPropertyTypeInstances { override def getPropertyType(): fir.PropertyType = fir.PathPropertyType override def convert(value: Underlying, ctx: ir.Component, info: SourceInfo): fir.Expression = value.convert() type Underlying = Path - override def convertUnderlying(value: M) = Path(value) + override def convertUnderlying(value: M, info: SourceInfo) = Path(value) } private def dataPathTypeInstance[D <: Data]: RecursivePropertyType.Aux[D, Path, Path] = new RecursivePropertyType[D] { @@ -167,7 +167,7 @@ private[chisel3] object PropertyType extends LowPriorityPropertyTypeInstances { override def getPropertyType(): fir.PropertyType = fir.PathPropertyType override def convert(value: Underlying, ctx: ir.Component, info: SourceInfo): fir.Expression = value.convert() type Underlying = Path - override def convertUnderlying(value: D) = Path(value) + override def convertUnderlying(value: D, info: SourceInfo) = Path(value) } // We can't just do <: Element because Property subclasses Element @@ -184,7 +184,7 @@ private[chisel3] object PropertyType extends LowPriorityPropertyTypeInstances { override def getPropertyType(): fir.PropertyType = fir.PathPropertyType override def convert(value: Underlying, ctx: ir.Component, info: SourceInfo): fir.Expression = value.convert() type Underlying = Path - override def convertUnderlying(value: M) = Path(value) + override def convertUnderlying(value: M, info: SourceInfo) = Path(value) } implicit def propertyTypeInstance[T]( @@ -195,7 +195,7 @@ private[chisel3] object PropertyType extends LowPriorityPropertyTypeInstances { override def convert(value: Underlying, ctx: ir.Component, info: SourceInfo): fir.Expression = Converter.convert(value, ctx, info) type Underlying = ir.Arg - override def convertUnderlying(value: Property[T]) = value.ref + override def convertUnderlying(value: Property[T], info: SourceInfo) = value.ref(info) } implicit def recursiveSequencePropertyTypeInstance[A, F[A] <: Seq[A]]( @@ -224,7 +224,8 @@ sealed trait Property[T] extends Element { self => override def convert(value: Underlying, ctx: ir.Component, info: SourceInfo): fir.Expression = Converter.convert(value, ctx, info) type Underlying = ir.Arg - override def convertUnderlying(value: Property[ClassType] with self.ClassType) = value.ref + override def convertUnderlying(value: Property[ClassType] with self.ClassType, info: SourceInfo) = + value.ref(info) } } @@ -492,8 +493,8 @@ object Property { /** Create a new Property literal of type T. */ - def apply[T](lit: T)(implicit tpe: PropertyType[T]): Property[tpe.Type] = { - val literal = ir.PropertyLit[tpe.Type, tpe.Underlying](tpe, tpe.convertUnderlying(lit)) + def apply[T](lit: T)(implicit tpe: PropertyType[T], info: SourceInfo): Property[tpe.Type] = { + val literal = ir.PropertyLit[tpe.Type, tpe.Underlying](tpe, tpe.convertUnderlying(lit, info)) val result = makeWithValueOpt(tpe) literal.bindLitArg(result) } diff --git a/src/test/scala/chiselTests/WhenSpec.scala b/src/test/scala/chiselTests/WhenSpec.scala index 0197db8af4..32cb650f9b 100644 --- a/src/test/scala/chiselTests/WhenSpec.scala +++ b/src/test/scala/chiselTests/WhenSpec.scala @@ -170,38 +170,44 @@ class WhenSpec extends ChiselFlatSpec with Utils { "Using a value that has escaped from a when scope in a connection" should "give a reasonable error message" in { implicit val info: SourceInfo = SourceLine("Foo.scala", 12, 3) val e = the[ChiselException] thrownBy { - ChiselStage.emitCHIRRTL(new Module { - override def desiredName = "Top" - val foo, bar = IO(Output(UInt(8.W))) - val a = IO(Input(Bool())) - lazy val w = Wire(UInt(8.W)) - when(a) { - foo := w - } - bar := w - }) + ChiselStage.emitCHIRRTL( + new Module { + override def desiredName = "Top" + val foo, bar = IO(Output(UInt(8.W))) + val a = IO(Input(Bool())) + lazy val w = Wire(UInt(8.W)) + when(a) { + foo := w + } + bar := w + }, + args = Array("--throw-on-first-error") + ) } val msg = - "Source foo_w in Top has escaped the scope of the block (@[Foo.scala:12:3]) in which it was constructed." + "'Top.foo_w: Wire[UInt<8>]' has escaped the scope of the block (@[Foo.scala:12:3]) in which it was constructed." e.getMessage should include(msg) } "Using a value that has escaped from a when scope in an operation" should "give a reasonable error message" in { implicit val info: SourceInfo = SourceLine("Foo.scala", 12, 3) val e = the[ChiselException] thrownBy { - ChiselStage.emitCHIRRTL(new Module { - override def desiredName = "Top" - val foo, bar = IO(Output(UInt(8.W))) - val a = IO(Input(Bool())) - lazy val w = Wire(UInt(8.W)) - when(a) { - foo := w - } - bar := w + 1.U - }) + ChiselStage.emitCHIRRTL( + new Module { + override def desiredName = "Top" + val foo, bar = IO(Output(UInt(8.W))) + val a = IO(Input(Bool())) + lazy val w = Wire(UInt(8.W)) + when(a) { + foo := w + } + bar := w + 1.U + }, + args = Array("--throw-on-first-error") + ) } val msg = - "operand 'Top.foo_w: Wire[UInt<8>]' has escaped the scope of the block (@[Foo.scala:12:3]) in which it was constructed." + "'Top.foo_w: Wire[UInt<8>]' has escaped the scope of the block (@[Foo.scala:12:3]) in which it was constructed." e.getMessage should include(msg) } @@ -232,7 +238,7 @@ class WhenSpec extends ChiselFlatSpec with Utils { out := c } } - val e = the[ChiselException] thrownBy ChiselStage.emitCHIRRTL(new Foo) + val e = the[ChiselException] thrownBy ChiselStage.emitCHIRRTL(new Foo, args = Array("--throw-on-first-error")) e.getMessage should include("has escaped the scope of the block") } }