From e92f2f69477a6ce86fc148a1a95db5797f2e3051 Mon Sep 17 00:00:00 2001 From: ducky Date: Thu, 5 May 2016 13:22:04 -0700 Subject: Implementation of source locators --- .../src/main/scala/Chisel/Aggregate.scala | 73 +++++++++++++++------- 1 file changed, 52 insertions(+), 21 deletions(-) (limited to 'chiselFrontend/src/main/scala/Chisel/Aggregate.scala') 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:_*) -- cgit v1.2.3 From fd53af8642237998e23456a3fd1648ac84607db0 Mon Sep 17 00:00:00 2001 From: Wesley W. Terpstra Date: Wed, 1 Jun 2016 16:09:20 -0700 Subject: Fix a fairly serious bug whereby Vec's could incorrectly compare as equal (#204) * chiselTests: include an example of two empty Vectors killing FIRRTL * Aggregate: fix a bug whereby Vec[T] was using equals/hashCode of Seq In Chisel, two vectors are NOT equal just if their contents are equal. For example, two empty vectors should not be considered equal. This patch makes Vec use the HasId._id for equality like other Chisel types. Without this fix, Bundle.namedElts.seen: HashSet[Data]() will eliminate one of the named vectors and emit bad IR. --- chiselFrontend/src/main/scala/Chisel/Aggregate.scala | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'chiselFrontend/src/main/scala/Chisel/Aggregate.scala') diff --git a/chiselFrontend/src/main/scala/Chisel/Aggregate.scala b/chiselFrontend/src/main/scala/Chisel/Aggregate.scala index 197135d7..1eef5d69 100644 --- a/chiselFrontend/src/main/scala/Chisel/Aggregate.scala +++ b/chiselFrontend/src/main/scala/Chisel/Aggregate.scala @@ -174,9 +174,13 @@ sealed class Vec[T <: Data] private (gen: => T, val length: Int) /** A trait for [[Vec]]s containing common hardware generators for collection * operations. */ -trait VecLike[T <: Data] extends collection.IndexedSeq[T] { +trait VecLike[T <: Data] extends collection.IndexedSeq[T] with HasId { def apply(idx: UInt): T + // IndexedSeq has its own hashCode/equals that we must not use + override def hashCode: Int = super[HasId].hashCode + override def equals(that: Any): Boolean = super[HasId].equals(that) + @deprecated("Use Vec.apply instead", "chisel3") def read(idx: UInt): T -- cgit v1.2.3