diff options
| author | Edward Wang | 2018-07-08 02:12:45 -0700 |
|---|---|---|
| committer | edwardcwang | 2018-08-22 11:55:38 -0700 |
| commit | f803eb8d8b7ef447d80710f94912f683c7a03771 (patch) | |
| tree | 7f6167a5bb9f5411119ad0452c5366e603717592 /src/main | |
| parent | b6b00a9301198275697a8309b5a083359a5b4454 (diff) | |
MixedVec implementation
Diffstat (limited to 'src/main')
| -rw-r--r-- | src/main/scala/chisel3/util/MixedVec.scala | 129 | ||||
| -rw-r--r-- | src/main/scala/chisel3/util/util.scala | 1 |
2 files changed, 129 insertions, 1 deletions
diff --git a/src/main/scala/chisel3/util/MixedVec.scala b/src/main/scala/chisel3/util/MixedVec.scala new file mode 100644 index 00000000..cd3a1115 --- /dev/null +++ b/src/main/scala/chisel3/util/MixedVec.scala @@ -0,0 +1,129 @@ +// See LICENSE for license details. + +package chisel3.util + +import chisel3._ +import chisel3.core.{Data, requireIsChiselType, requireIsHardware} +import chisel3.internal.naming.chiselName + +import scala.collection.immutable.ListMap + +object MixedVecWireInit { + /** + * Construct a new wire with the given bound values. + * This is analogous to [[chisel3.core.VecInit]]. + * @param vals Values to create a MixedVec with and assign + * @return MixedVec with given values assigned + */ + def apply[T <: Data](vals: Seq[T]): MixedVec[T] = { + // Create a wire of this type. + val hetVecWire = Wire(MixedVec(vals.map(_.cloneTypeFull))) + // Assign the given vals to this new wire. + for ((a, b) <- hetVecWire.zip(vals)) { + a := b + } + hetVecWire + } +} + +object MixedVec { + /** + * Create a MixedVec from that holds the given types. + * @param eltsIn Element types. Must be Chisel types. + * @return MixedVec with the given types. + */ + def apply[T <: Data](eltsIn: Seq[T]): MixedVec[T] = new MixedVec(eltsIn) + + /** + * Create a MixedVec from the type of the given Vec. + * For example, given a Vec(2, UInt(8.W)), this creates MixedVec(Seq.fill(2){UInt(8.W)}). + * @param vec Vec to use as template + * @return MixedVec analogous to the given Vec. + */ + def apply[T <: Data](vec: Vec[T]): MixedVec[T] = { + MixedVec(Seq.fill(vec.length)(vec.sample_element)) + } +} + +/** + * A hardware array of elements that can hold values of different types/widths, + * unlike Vec which can only hold elements of the same type/width. + * + * @param eltsIn Element types. Must be Chisel types. + * + * @example {{{ + * val v = Wire(MixedVec(Seq(UInt(8.W), UInt(16.W), UInt(32.W)))) + * v(0) := 100.U(8.W) + * v(1) := 10000.U(16.W) + * v(2) := 101.U(32.W) + * }}} + */ +@chiselName +final class MixedVec[T <: Data](private val eltsIn: Seq[T]) extends Record with collection.IndexedSeq[T] { + // We want to create MixedVec only with Chisel types. + if (compileOptions.declaredTypeMustBeUnbound) { + eltsIn.foreach(e => requireIsChiselType(e)) + } + + // Clone the inputs so that we have our own references. + private val elts: IndexedSeq[T] = eltsIn.map(_.cloneTypeFull).toIndexedSeq + + /** + * Statically (elaboration-time) retrieve the element at the given index. + * @param index Index with which to retrieve. + * @return Retrieved index. + */ + def apply(index: Int): T = elts(index) + + /** + * Dynamically (via a mux) retrieve the element at the given index. + * + * @param index Index with which to retrieve. + * @return Retrieved index. + */ + def apply(index: UInt): T = { + requireIsHardware(index, "index must be hardware") + + if (length < 1) { + throw new IndexOutOfBoundsException("Collection is empty") + } + + MuxLookup(index, elts.head, elts.zipWithIndex.map { case (el, el_index) => el_index.U -> el }) + } + + /** Strong bulk connect, assigning elements in this MixedVec from elements in a Seq. + * + * @note the lengths of this and that must match + */ + def :=(that: Seq[T]): Unit = { + require(this.length == that.length) + for ((a, b) <- this zip that) + a := b + } + + /** Strong bulk connect, assigning elements in this MixedVec from elements in a Vec. + * + * @note the lengths of this and that must match + */ + def :=(that: Vec[T]): Unit = { + require(this.length == that.length) + for ((a, b) <- this zip that) + a := b + } + + /** + * Get the length of this MixedVec. + * @return Number of elements in this MixedVec. + */ + def length: Int = elts.length + + override val elements = ListMap(elts.zipWithIndex.map { case (element, index) => (index.toString, element) }: _*) + + // Need to re-clone again since we could have been bound since object creation. + override def cloneType: this.type = MixedVec(elts.map(_.cloneTypeFull)).asInstanceOf[this.type] + + // IndexedSeq has its own hashCode/equals that we must not use + override def hashCode: Int = super[Record].hashCode + + override def equals(that: Any): Boolean = super[Record].equals(that) +} diff --git a/src/main/scala/chisel3/util/util.scala b/src/main/scala/chisel3/util/util.scala index 987678e3..164abdf8 100644 --- a/src/main/scala/chisel3/util/util.scala +++ b/src/main/scala/chisel3/util/util.scala @@ -11,5 +11,4 @@ package object util { type ValidIO[+T <: Data] = chisel3.util.Valid[T] val ValidIO = chisel3.util.Valid val DecoupledIO = chisel3.util.Decoupled - } |
