summaryrefslogtreecommitdiff
path: root/src/main/scala/Chisel/Aggregate.scala
diff options
context:
space:
mode:
authorducky2016-05-05 11:50:39 -0700
committerducky2016-05-05 11:50:39 -0700
commit9036d96bb032c19de31131f2296120e708cbc3dc (patch)
treecf17173fab309b09670ca7529680e09d61341451 /src/main/scala/Chisel/Aggregate.scala
parent623a301df1f5a1954f8e4a64ef97c99c3900da28 (diff)
Move Chisel API into separate chiselFrontend compilation unit in preparation for source locator macros
Diffstat (limited to 'src/main/scala/Chisel/Aggregate.scala')
-rw-r--r--src/main/scala/Chisel/Aggregate.scala342
1 files changed, 0 insertions, 342 deletions
diff --git a/src/main/scala/Chisel/Aggregate.scala b/src/main/scala/Chisel/Aggregate.scala
deleted file mode 100644
index 4d35e2f0..00000000
--- a/src/main/scala/Chisel/Aggregate.scala
+++ /dev/null
@@ -1,342 +0,0 @@
-// See LICENSE for license details.
-
-package Chisel
-
-import scala.collection.immutable.ListMap
-import scala.collection.mutable.{ArrayBuffer, HashSet, LinkedHashMap}
-
-import internal._
-import internal.Builder.pushCommand
-import internal.firrtl._
-
-/** An abstract class for data types that solely consist of (are an aggregate
- * of) other Data objects.
- */
-sealed abstract class Aggregate(dirArg: Direction) extends Data(dirArg) {
- private[Chisel] def cloneTypeWidth(width: Width): this.type = cloneType
- def width: Width = flatten.map(_.width).reduce(_ + _)
-}
-
-object Vec {
- /** Creates a new [[Vec]] with `n` entries of the specified data type.
- *
- * @note elements are NOT assigned by default and have no value
- */
- def apply[T <: Data](n: Int, gen: T): Vec[T] = new Vec(gen.cloneType, n)
-
- @deprecated("Vec argument order should be size, t; this will be removed by the official release", "chisel3")
- def apply[T <: Data](gen: T, n: Int): Vec[T] = new Vec(gen.cloneType, n)
-
- /** Creates a new [[Vec]] composed of elements of the input Seq of [[Data]]
- * nodes.
- *
- * @note input elements should be of the same type (this is checked at the
- * FIRRTL level, but not at the Scala / Chisel level)
- * @note the width of all output elements is the width of the largest input
- * element
- * @note output elements are connected from the input elements
- */
- def apply[T <: Data](elts: Seq[T]): 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))
- for ((v, e) <- vec zip elts)
- v := e
- vec
- }
-
- /** Creates a new [[Vec]] composed of the input [[Data]] nodes.
- *
- * @note input elements should be of the same type (this is checked at the
- * FIRRTL level, but not at the Scala / Chisel level)
- * @note the width of all output elements is the width of the largest input
- * element
- * @note output elements are connected from the input elements
- */
- def apply[T <: Data](elt0: T, elts: T*): Vec[T] =
- apply(elt0 +: elts.toSeq)
-
- /** Creates a new [[Vec]] of length `n` composed of the results of the given
- * function applied over a range of integer values starting from 0.
- *
- * @param n number of elements in the vector (the function is applied from
- * 0 to `n-1`)
- * @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] =
- apply((0 until n).map(i => gen(i)))
-
- /** Creates a new [[Vec]] of length `n` composed of the result of the given
- * function repeatedly applied.
- *
- * @param n number of elements (amd the number of times the function is
- * called)
- * @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))
-}
-
-/** A vector (array) of [[Data]] elements. Provides hardware versions of various
- * collection transformation functions found in software array implementations.
- *
- * @tparam T type of elements
- * @note when multiple conflicting assignments are performed on a Vec element,
- * the last one takes effect (unlike Mem, where the result is undefined)
- * @note Vecs, unlike classes in Scala's collection library, are propagated
- * intact to FIRRTL as a vector type, which may make debugging easier
- */
-sealed class Vec[T <: Data] private (gen: => T, val length: Int)
- extends Aggregate(gen.dir) with VecLike[T] {
- // Note: the constructor takes a gen() function instead of a Seq to enforce
- // that all elements must be the same and because it makes FIRRTL generation
- // simpler.
-
- private val self = IndexedSeq.fill(length)(gen)
-
- override def <> (that: Data): 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
-
- // 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]
-
- override def := (that: Data): Unit = that match {
- case _: Vec[_] => this connect that
- case _ => this badConnect 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 = {
- 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
-
- /** Creates a dynamically indexed read or write accessor into the array.
- */
- def apply(idx: UInt): T = {
- val x = gen
- x.setRef(this, idx)
- x
- }
-
- /** Creates a statically indexed read or write accessor into the array.
- */
- def apply(idx: Int): T = self(idx)
-
- @deprecated("Use Vec.apply instead", "chisel3")
- def read(idx: UInt): T = apply(idx)
-
- @deprecated("Use Vec.apply instead", "chisel3")
- def write(idx: UInt, data: T): Unit = apply(idx) := data
-
- override def cloneType: this.type =
- Vec(length, gen).asInstanceOf[this.type]
-
- private val t = gen
- private[Chisel] def toType: String = s"${t.toType}[$length]"
- private[Chisel] lazy val flatten: IndexedSeq[Bits] =
- (0 until length).flatMap(i => this.apply(i).flatten)
-
- for ((elt, i) <- self zipWithIndex)
- elt.setRef(this, i)
-}
-
-/** A trait for [[Vec]]s containing common hardware generators for collection
- * operations.
- */
-trait VecLike[T <: Data] extends collection.IndexedSeq[T] {
- def apply(idx: UInt): T
-
- @deprecated("Use Vec.apply instead", "chisel3")
- def read(idx: UInt): T
-
- @deprecated("Use Vec.apply instead", "chisel3")
- def write(idx: UInt, data: T): Unit
-
- /** Outputs true if p outputs true for every element.
- */
- def forall(p: T => Bool): 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))(_ || _)
-
- /** 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)
-
- /** Outputs the number of elements for which p is true.
- */
- def count(p: T => Bool): 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.
- */
- private def indexWhereHelper(p: T => Bool) = this map p zip (0 until length).map(i => UInt(i))
-
- /** Outputs the index of the first element for which p outputs true.
- */
- def indexWhere(p: T => Bool): 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)
-
- /** Outputs the index of the element for which p outputs true, assuming that
- * the there is exactly one such element.
- *
- * The implementation may be more efficient than a priority mux, but
- * incorrect results are possible if there is not exactly one true element.
- *
- * @note the assumption that there is only one element for which p outputs
- * 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))
-}
-
-/** Base class for data types defined as a bundle of other data types.
- *
- * Usage: extend this class (either as an anonymous or named class) and define
- * members variables of [[Data]] subtypes to be elements in the Bundle.
- */
-class Bundle extends Aggregate(NO_DIR) {
- private val _namespace = Builder.globalNamespace.child
-
- // TODO: replace with better defined FIRRTL weak-connect operator
- /** Connect elements in this Bundle to elements in `that` on a best-effort
- * (weak) basis, matching by type, orientation, and name.
- *
- * @note unconnected elements will NOT generate errors or warnings
- *
- * @example
- * {{{
- * // Pass through wires in this module's io to those mySubModule's io,
- * // matching by type, orientation, and name, and ignoring extra wires.
- * mySubModule.io <> io
- * }}}
- */
- override def <> (that: Data): 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
-
- lazy val elements: ListMap[String, Data] = ListMap(namedElts:_*)
-
- /** Returns a best guess at whether a field in this Bundle is a user-defined
- * Bundle element without looking at type signatures.
- */
- private def isBundleField(m: java.lang.reflect.Method) =
- m.getParameterTypes.isEmpty &&
- !java.lang.reflect.Modifier.isStatic(m.getModifiers) &&
- !(Bundle.keywords contains m.getName) && !(m.getName contains '$')
-
- /** Returns a field's contained user-defined Bundle element if it appears to
- * be one, otherwise returns None.
- */
- private def getBundleField(m: java.lang.reflect.Method): Option[Data] = {
- if (isBundleField(m) &&
- (classOf[Data].isAssignableFrom(m.getReturnType) ||
- classOf[Option[_]].isAssignableFrom(m.getReturnType))) {
- m.invoke(this) match {
- case d: Data =>
- Some(d)
- case o: Option[_] =>
- o.getOrElse(None) match {
- case d: Data =>
- Some(d)
- case _ => None
- }
- case _ => None
- }
- } else {
- None
- }
- }
-
- /** Returns a list of elements in this Bundle.
- */
- private[Chisel] lazy val namedElts = {
- val nameMap = LinkedHashMap[String, Data]()
- val seen = HashSet[Data]()
- for (m <- getClass.getMethods.sortWith(_.getName < _.getName)) {
- getBundleField(m) match {
- case Some(d) =>
- if (nameMap contains m.getName) {
- require(nameMap(m.getName) eq d)
- } else if (!seen(d)) {
- nameMap(m.getName) = d; seen += d
- }
- case None =>
- }
- }
- ArrayBuffer(nameMap.toSeq:_*) sortWith {case ((an, a), (bn, b)) => (a._id > b._id) || ((a eq b) && (an > bn))}
- }
- private[Chisel] def toType = {
- def eltPort(elt: Data): String = {
- val flipStr = if (elt.isFlip) "flip " else ""
- s"${flipStr}${elt.getRef.name} : ${elt.toType}"
- }
- s"{${namedElts.reverse.map(e => eltPort(e._2)).mkString(", ")}}"
- }
- private[Chisel] lazy val flatten = namedElts.flatMap(_._2.flatten)
- private[Chisel] def addElt(name: String, elt: Data): Unit =
- namedElts += name -> elt
- private[Chisel] override def _onModuleClose: Unit = // scalastyle:ignore method.name
- for ((name, elt) <- namedElts) { elt.setRef(this, _namespace.name(name)) }
-
- override def cloneType : this.type = {
- // If the user did not provide a cloneType method, try invoking one of
- // the following constructors, not all of which necessarily exist:
- // - A zero-parameter constructor
- // - A one-paramater constructor, with null as the argument
- // - A one-parameter constructor for a nested Bundle, with the enclosing
- // parent Module as the argument
- val constructor = this.getClass.getConstructors.head
- try {
- val args = Seq.fill(constructor.getParameterTypes.size)(null)
- constructor.newInstance(args:_*).asInstanceOf[this.type]
- } catch {
- case e: java.lang.reflect.InvocationTargetException if e.getCause.isInstanceOf[java.lang.NullPointerException] =>
- try {
- constructor.newInstance(_parent.get).asInstanceOf[this.type]
- } catch {
- case _: java.lang.reflect.InvocationTargetException | _: java.lang.IllegalArgumentException =>
- Builder.error(s"Parameterized Bundle ${this.getClass} needs cloneType method. You are probably using " +
- "an anonymous Bundle object that captures external state and hence is un-cloneTypeable")
- this
- }
- case _: java.lang.reflect.InvocationTargetException | _: java.lang.IllegalArgumentException =>
- Builder.error(s"Parameterized Bundle ${this.getClass} needs cloneType method")
- this
- }
- }
-}
-
-private[Chisel] object Bundle {
- val keywords = List("flip", "asInput", "asOutput", "cloneType", "toBits")
-}