From f36524e388b060b1bb535ae21cb1bcbbea220be9 Mon Sep 17 00:00:00 2001 From: ducky Date: Fri, 20 May 2016 18:09:57 -0700 Subject: Rename packages to lowercase chisel, add compatibility layer --- .../src/main/scala/Chisel/Aggregate.scala | 377 ---------- chiselFrontend/src/main/scala/Chisel/Assert.scala | 73 -- chiselFrontend/src/main/scala/Chisel/Bits.scala | 756 --------------------- .../src/main/scala/Chisel/BlackBox.scala | 55 -- chiselFrontend/src/main/scala/Chisel/Data.scala | 161 ----- chiselFrontend/src/main/scala/Chisel/Mem.scala | 134 ---- chiselFrontend/src/main/scala/Chisel/Module.scala | 119 ---- chiselFrontend/src/main/scala/Chisel/Printf.scala | 36 - chiselFrontend/src/main/scala/Chisel/Reg.scala | 71 -- .../src/main/scala/Chisel/SeqUtils.scala | 59 -- chiselFrontend/src/main/scala/Chisel/When.scala | 59 -- .../src/main/scala/Chisel/internal/Builder.scala | 123 ---- .../src/main/scala/Chisel/internal/Error.scala | 91 --- .../main/scala/Chisel/internal/SourceInfo.scala | 51 -- .../src/main/scala/Chisel/internal/firrtl/IR.scala | 188 ----- .../src/main/scala/chisel/Aggregate.scala | 377 ++++++++++ chiselFrontend/src/main/scala/chisel/Assert.scala | 73 ++ chiselFrontend/src/main/scala/chisel/Bits.scala | 756 +++++++++++++++++++++ .../src/main/scala/chisel/BlackBox.scala | 55 ++ chiselFrontend/src/main/scala/chisel/Data.scala | 161 +++++ chiselFrontend/src/main/scala/chisel/Mem.scala | 134 ++++ chiselFrontend/src/main/scala/chisel/Module.scala | 119 ++++ chiselFrontend/src/main/scala/chisel/Printf.scala | 36 + chiselFrontend/src/main/scala/chisel/Reg.scala | 71 ++ .../src/main/scala/chisel/SeqUtils.scala | 59 ++ chiselFrontend/src/main/scala/chisel/When.scala | 59 ++ .../src/main/scala/chisel/internal/Builder.scala | 123 ++++ .../src/main/scala/chisel/internal/Error.scala | 91 +++ .../main/scala/chisel/internal/SourceInfo.scala | 51 ++ .../src/main/scala/chisel/internal/firrtl/IR.scala | 189 ++++++ .../internal/sourceinfo/SourceInfoTransform.scala | 156 ----- .../internal/sourceinfo/SourceInfoTransform.scala | 156 +++++ src/main/scala/Chisel/BitPat.scala | 4 +- src/main/scala/Chisel/Driver.scala | 132 ---- src/main/scala/Chisel/FileSystemUtilities.scala | 10 - src/main/scala/Chisel/ImplicitConversions.scala | 8 - src/main/scala/Chisel/Main.scala | 17 - .../scala/Chisel/internal/firrtl/Emitter.scala | 112 --- src/main/scala/Chisel/package.scala | 31 - src/main/scala/Chisel/testers/BasicTester.scala | 38 -- src/main/scala/Chisel/testers/TesterDriver.scala | 68 -- src/main/scala/Chisel/throwException.scala | 12 - src/main/scala/Chisel/util/Arbiter.scala | 117 ---- src/main/scala/Chisel/util/Bitwise.scala | 71 -- src/main/scala/Chisel/util/Cat.scala | 18 - src/main/scala/Chisel/util/CircuitMath.scala | 26 - src/main/scala/Chisel/util/Conditional.scala | 69 -- src/main/scala/Chisel/util/Counter.scala | 44 -- src/main/scala/Chisel/util/Decoupled.scala | 183 ----- src/main/scala/Chisel/util/Enum.scala | 21 - src/main/scala/Chisel/util/LFSR.scala | 22 - src/main/scala/Chisel/util/Lookup.scala | 17 - src/main/scala/Chisel/util/Math.scala | 42 -- src/main/scala/Chisel/util/Mux.scala | 61 -- src/main/scala/Chisel/util/OneHot.scala | 62 -- src/main/scala/Chisel/util/Reg.scala | 55 -- src/main/scala/Chisel/util/TransitName.scala | 21 - src/main/scala/Chisel/util/Valid.scala | 59 -- src/main/scala/chisel/Driver.scala | 132 ++++ src/main/scala/chisel/FileSystemUtilities.scala | 10 + src/main/scala/chisel/ImplicitConversions.scala | 8 + src/main/scala/chisel/Main.scala | 17 + src/main/scala/chisel/compatibility.scala | 139 ++++ .../scala/chisel/internal/firrtl/Emitter.scala | 112 +++ src/main/scala/chisel/package.scala | 31 + src/main/scala/chisel/testers/BasicTester.scala | 38 ++ src/main/scala/chisel/testers/TesterDriver.scala | 69 ++ src/main/scala/chisel/throwException.scala | 12 + src/main/scala/chisel/util/Arbiter.scala | 117 ++++ src/main/scala/chisel/util/Bitwise.scala | 71 ++ src/main/scala/chisel/util/Cat.scala | 18 + src/main/scala/chisel/util/CircuitMath.scala | 26 + src/main/scala/chisel/util/Conditional.scala | 71 ++ src/main/scala/chisel/util/Counter.scala | 44 ++ src/main/scala/chisel/util/Decoupled.scala | 183 +++++ src/main/scala/chisel/util/Enum.scala | 21 + src/main/scala/chisel/util/LFSR.scala | 22 + src/main/scala/chisel/util/Lookup.scala | 17 + src/main/scala/chisel/util/Math.scala | 42 ++ src/main/scala/chisel/util/Mux.scala | 61 ++ src/main/scala/chisel/util/OneHot.scala | 62 ++ src/main/scala/chisel/util/Reg.scala | 55 ++ src/main/scala/chisel/util/TransitName.scala | 21 + src/main/scala/chisel/util/Valid.scala | 59 ++ 84 files changed, 3970 insertions(+), 3827 deletions(-) delete mode 100644 chiselFrontend/src/main/scala/Chisel/Aggregate.scala delete mode 100644 chiselFrontend/src/main/scala/Chisel/Assert.scala delete mode 100644 chiselFrontend/src/main/scala/Chisel/Bits.scala delete mode 100644 chiselFrontend/src/main/scala/Chisel/BlackBox.scala delete mode 100644 chiselFrontend/src/main/scala/Chisel/Data.scala delete mode 100644 chiselFrontend/src/main/scala/Chisel/Mem.scala delete mode 100644 chiselFrontend/src/main/scala/Chisel/Module.scala delete mode 100644 chiselFrontend/src/main/scala/Chisel/Printf.scala delete mode 100644 chiselFrontend/src/main/scala/Chisel/Reg.scala delete mode 100644 chiselFrontend/src/main/scala/Chisel/SeqUtils.scala delete mode 100644 chiselFrontend/src/main/scala/Chisel/When.scala delete mode 100644 chiselFrontend/src/main/scala/Chisel/internal/Builder.scala delete mode 100644 chiselFrontend/src/main/scala/Chisel/internal/Error.scala delete mode 100644 chiselFrontend/src/main/scala/Chisel/internal/SourceInfo.scala delete mode 100644 chiselFrontend/src/main/scala/Chisel/internal/firrtl/IR.scala create mode 100644 chiselFrontend/src/main/scala/chisel/Aggregate.scala create mode 100644 chiselFrontend/src/main/scala/chisel/Assert.scala create mode 100644 chiselFrontend/src/main/scala/chisel/Bits.scala create mode 100644 chiselFrontend/src/main/scala/chisel/BlackBox.scala create mode 100644 chiselFrontend/src/main/scala/chisel/Data.scala create mode 100644 chiselFrontend/src/main/scala/chisel/Mem.scala create mode 100644 chiselFrontend/src/main/scala/chisel/Module.scala create mode 100644 chiselFrontend/src/main/scala/chisel/Printf.scala create mode 100644 chiselFrontend/src/main/scala/chisel/Reg.scala create mode 100644 chiselFrontend/src/main/scala/chisel/SeqUtils.scala create mode 100644 chiselFrontend/src/main/scala/chisel/When.scala create mode 100644 chiselFrontend/src/main/scala/chisel/internal/Builder.scala create mode 100644 chiselFrontend/src/main/scala/chisel/internal/Error.scala create mode 100644 chiselFrontend/src/main/scala/chisel/internal/SourceInfo.scala create mode 100644 chiselFrontend/src/main/scala/chisel/internal/firrtl/IR.scala delete mode 100644 coreMacros/src/main/scala/Chisel/internal/sourceinfo/SourceInfoTransform.scala create mode 100644 coreMacros/src/main/scala/chisel/internal/sourceinfo/SourceInfoTransform.scala delete mode 100644 src/main/scala/Chisel/Driver.scala delete mode 100644 src/main/scala/Chisel/FileSystemUtilities.scala delete mode 100644 src/main/scala/Chisel/ImplicitConversions.scala delete mode 100644 src/main/scala/Chisel/Main.scala delete mode 100644 src/main/scala/Chisel/internal/firrtl/Emitter.scala delete mode 100644 src/main/scala/Chisel/package.scala delete mode 100644 src/main/scala/Chisel/testers/BasicTester.scala delete mode 100644 src/main/scala/Chisel/testers/TesterDriver.scala delete mode 100644 src/main/scala/Chisel/throwException.scala delete mode 100644 src/main/scala/Chisel/util/Arbiter.scala delete mode 100644 src/main/scala/Chisel/util/Bitwise.scala delete mode 100644 src/main/scala/Chisel/util/Cat.scala delete mode 100644 src/main/scala/Chisel/util/CircuitMath.scala delete mode 100644 src/main/scala/Chisel/util/Conditional.scala delete mode 100644 src/main/scala/Chisel/util/Counter.scala delete mode 100644 src/main/scala/Chisel/util/Decoupled.scala delete mode 100644 src/main/scala/Chisel/util/Enum.scala delete mode 100644 src/main/scala/Chisel/util/LFSR.scala delete mode 100644 src/main/scala/Chisel/util/Lookup.scala delete mode 100644 src/main/scala/Chisel/util/Math.scala delete mode 100644 src/main/scala/Chisel/util/Mux.scala delete mode 100644 src/main/scala/Chisel/util/OneHot.scala delete mode 100644 src/main/scala/Chisel/util/Reg.scala delete mode 100644 src/main/scala/Chisel/util/TransitName.scala delete mode 100644 src/main/scala/Chisel/util/Valid.scala create mode 100644 src/main/scala/chisel/Driver.scala create mode 100644 src/main/scala/chisel/FileSystemUtilities.scala create mode 100644 src/main/scala/chisel/ImplicitConversions.scala create mode 100644 src/main/scala/chisel/Main.scala create mode 100644 src/main/scala/chisel/compatibility.scala create mode 100644 src/main/scala/chisel/internal/firrtl/Emitter.scala create mode 100644 src/main/scala/chisel/package.scala create mode 100644 src/main/scala/chisel/testers/BasicTester.scala create mode 100644 src/main/scala/chisel/testers/TesterDriver.scala create mode 100644 src/main/scala/chisel/throwException.scala create mode 100644 src/main/scala/chisel/util/Arbiter.scala create mode 100644 src/main/scala/chisel/util/Bitwise.scala create mode 100644 src/main/scala/chisel/util/Cat.scala create mode 100644 src/main/scala/chisel/util/CircuitMath.scala create mode 100644 src/main/scala/chisel/util/Conditional.scala create mode 100644 src/main/scala/chisel/util/Counter.scala create mode 100644 src/main/scala/chisel/util/Decoupled.scala create mode 100644 src/main/scala/chisel/util/Enum.scala create mode 100644 src/main/scala/chisel/util/LFSR.scala create mode 100644 src/main/scala/chisel/util/Lookup.scala create mode 100644 src/main/scala/chisel/util/Math.scala create mode 100644 src/main/scala/chisel/util/Mux.scala create mode 100644 src/main/scala/chisel/util/OneHot.scala create mode 100644 src/main/scala/chisel/util/Reg.scala create mode 100644 src/main/scala/chisel/util/TransitName.scala create mode 100644 src/main/scala/chisel/util/Valid.scala diff --git a/chiselFrontend/src/main/scala/Chisel/Aggregate.scala b/chiselFrontend/src/main/scala/Chisel/Aggregate.scala deleted file mode 100644 index 1eef5d69..00000000 --- a/chiselFrontend/src/main/scala/Chisel/Aggregate.scala +++ /dev/null @@ -1,377 +0,0 @@ -// See LICENSE for license details. - -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. - */ -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] = 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)) - 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] = 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 - * 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] = 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 - * 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] = 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 - * 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)(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])(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])(implicit sourceInfo: SourceInfo): Unit = this := that.asInstanceOf[Data] - - override def := (that: Data)(implicit sourceInfo: SourceInfo): 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])(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])(implicit sourceInfo: SourceInfo): 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)(DeprecatedSourceInfo) - - 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] 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 - - @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 = 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 = 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 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 = 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. - */ - 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 = 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 = 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. - * - * 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 = 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. - * - * 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)(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)(implicit sourceInfo: SourceInfo): 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") -} diff --git a/chiselFrontend/src/main/scala/Chisel/Assert.scala b/chiselFrontend/src/main/scala/Chisel/Assert.scala deleted file mode 100644 index c086f014..00000000 --- a/chiselFrontend/src/main/scala/Chisel/Assert.scala +++ /dev/null @@ -1,73 +0,0 @@ -// See LICENSE for license details. - -package Chisel - -import scala.reflect.macros.blackbox.Context -import scala.language.experimental.macros - -import internal._ -import internal.Builder.pushCommand -import internal.firrtl._ -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 - * condition evaluates to false, the circuit simulation stops with an error. - * - * 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 assert make the standard Module assumptions (single clock - * and single reset). - * - * @param cond condition, assertion fires (simulation fails) when false - * @param message optional message to print when the assertion fires - * - * @note currently cannot be used in core Chisel / libraries because macro - * defs need to be compiled first and the SBT project is not set up to do - * that - */ - // 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)(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))($sourceInfo)" - } - - 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)($sourceInfo)" - } - - 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(sourceInfo, Node(Builder.dynamicContext.currentModule.get.clock), 1)) - } - } - - /** An elaboration-time assertion, otherwise the same as the above run-time - * assertion. */ - def apply(cond: Boolean, message: => String) { - Predef.assert(cond, message) - } - - /** A workaround for default-value overloading problems in Scala, just - * 'assert(cond, "")' */ - def apply(cond: Boolean) { - Predef.assert(cond, "") - } -} diff --git a/chiselFrontend/src/main/scala/Chisel/Bits.scala b/chiselFrontend/src/main/scala/Chisel/Bits.scala deleted file mode 100644 index bc8cc8e2..00000000 --- a/chiselFrontend/src/main/scala/Chisel/Bits.scala +++ /dev/null @@ -1,756 +0,0 @@ -// See LICENSE for license details. - -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 - * uses are for representing primitive data types, like integers and bits. - */ -abstract class Element(dirArg: Direction, val width: Width) extends Data(dirArg) - -/** A data type for values represented by a single bitvector. Provides basic - * bitwise operations. - */ -sealed abstract class Bits(dirArg: Direction, width: Width, override val litArg: Option[LitArg]) - extends Element(dirArg, width) { - // TODO: perhaps make this concrete? - // Arguments for: self-checking code (can't do arithmetic on bits) - // Arguments against: generates down to a FIRRTL UInt anyways - - private[Chisel] def fromInt(x: BigInt, w: Int): this.type - - private[Chisel] def flatten: IndexedSeq[Bits] = IndexedSeq(this) - - def cloneType: this.type = cloneTypeWidth(width) - - 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 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(sourceInfo, UInt(width = w), TailOp, n) - } - - - 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(sourceInfo, UInt(width = n), HeadOp, n) - } - - /** Returns the specified bit on this wire as a [[Bool]], statically - * addressed. - */ - 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(sourceInfo, Bool(), BitsExtractOp, this.ref, ILit(x), ILit(x))) - } - } - - /** Returns the specified bit on this wire as a [[Bool]], statically - * addressed. - * - * @note convenience method allowing direct use of Ints without implicits - */ - 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 = 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. - * - * @example - * {{{ - * myBits = 0x5 = 0b101 - * myBits(1,0) => 0b01 // extracts the two least significant bits - * }}} - */ - 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)") - } - val w = x - y + 1 - if (isLit()) { - UInt((litValue >> y) & ((BigInt(1) << w) - 1), w) - } else { - 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 = 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 - */ - 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? - 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. - */ - 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. - */ - final def << (that: UInt): Bits = macro SourceInfoWhiteboxTransform.thatArg - - def do_<< (that: UInt)(implicit sourceInfo: SourceInfo): Bits - - /** Shift right operation */ - // REVIEW TODO: redundant - 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. - */ - 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. - */ - 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. - */ - 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 - */ - 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 - */ - final def asUInt(): UInt = macro SourceInfoTransform.noArg - - def do_asUInt(implicit sourceInfo: SourceInfo): UInt - - /** Reinterpret cast to Bits. */ - 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 = do_asSInt(DeprecatedSourceInfo) - @deprecated("Use asUInt, which makes the reinterpret cast more explicit", "chisel3") - final def toUInt(): UInt = do_asUInt(DeprecatedSourceInfo) - - final def toBool(): Bool = macro SourceInfoTransform.noArg - - 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. - */ - 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 = do_asUInt(DeprecatedSourceInfo) - - override def do_fromBits(that: Bits)(implicit sourceInfo: SourceInfo): this.type = { - val res = Wire(this, null).asInstanceOf[this.type] - res := that - res - } -} - -/** Provides a set of operations to create UInt types and literals. - * Identical in functionality to the UInt companion object. - */ -object Bits extends UIntFactory - -// REVIEW TODO: Further discussion needed on what Num actually is. -/** Abstract trait defining operations available on numeric-like wire data - * types. - */ -abstract trait Num[T <: Data] { - // def << (b: T): T - // def >> (b: T): T - //def unary_-(): T - - // REVIEW TODO: double check ops conventions against FIRRTL - - /** Outputs the sum of `this` and `b`. The resulting width is the max of the - * operands plus 1 (should not overflow). - */ - 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. - * - * @note can generate a single-cycle multiplier, which can result in - * significant cycle time and area costs - */ - 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 - */ - final def / (that: T): T = macro SourceInfoTransform.thatArg - - 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). - */ - final def - (that: T): T = macro SourceInfoTransform.thatArg - - def do_- (that: T)(implicit sourceInfo: SourceInfo): T - - /** Outputs true if `this` < `b`. - */ - final def < (that: T): Bool = macro SourceInfoTransform.thatArg - - def do_< (that: T)(implicit sourceInfo: SourceInfo): Bool - - /** Outputs true if `this` <= `b`. - */ - final def <= (that: T): Bool = macro SourceInfoTransform.thatArg - - def do_<= (that: T)(implicit sourceInfo: SourceInfo): Bool - - /** Outputs true if `this` > `b`. - */ - final def > (that: T): Bool = macro SourceInfoTransform.thatArg - - def do_> (that: T)(implicit sourceInfo: SourceInfo): Bool - - /** Outputs true if `this` >= `b`. - */ - 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. - */ - 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. - */ - 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. - * Defines arithmetic operations between other integer types. - */ -sealed class UInt private[Chisel] (dir: Direction, width: Width, lit: Option[ULit] = None) - extends Bits(dir, width, lit) with Num[UInt] { - private[Chisel] override def cloneTypeWidth(w: Width): this.type = - new UInt(dir, w).asInstanceOf[this.type] - private[Chisel] def toType = s"UInt$width" - - override private[Chisel] def fromInt(value: BigInt, width: Int): this.type = - UInt(value, width).asInstanceOf[this.type] - - 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 - 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 do_unary_~ (implicit sourceInfo: SourceInfo): UInt = - unop(sourceInfo, UInt(width = width), BitNotOp) - - // REVIEW TODO: Can this be defined on Bits? - 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)) - } - - /** 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. - 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). - */ - 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. -private[Chisel] sealed trait UIntFactory { - /** Create a UInt type with inferred width. */ - def apply(): UInt = apply(NO_DIR, Width()) - /** Create a UInt type or port with fixed width. */ - def apply(dir: Direction = NO_DIR, width: Int): UInt = apply(dir, Width(width)) - /** Create a UInt port with inferred width. */ - def apply(dir: Direction): UInt = apply(dir, Width()) - - /** Create a UInt literal with inferred width. */ - def apply(value: BigInt): UInt = apply(value, Width()) - /** Create a UInt literal with fixed width. */ - def apply(value: BigInt, width: Int): UInt = apply(value, Width(width)) - /** Create a UInt literal with inferred width. */ - def apply(n: String): UInt = apply(parse(n), parsedWidth(n)) - /** Create a UInt literal with fixed width. */ - def apply(n: String, width: Int): UInt = apply(parse(n), width) - - /** Create a UInt type with specified width. */ - def apply(width: Width): UInt = apply(NO_DIR, width) - /** Create a UInt port with specified width. */ - def apply(dir: Direction, width: Width): UInt = new UInt(dir, width) - /** Create a UInt literal with specified width. */ - def apply(value: BigInt, width: Width): UInt = { - val lit = ULit(value, width) - new UInt(NO_DIR, lit.width, Some(lit)) - } - - private def parse(n: String) = { - val (base, num) = n.splitAt(1) - val radix = base match { - case "x" | "h" => 16 - case "d" => 10 - case "o" => 8 - case "b" => 2 - case _ => Builder.error(s"Invalid base $base"); 2 - } - BigInt(num.filterNot(_ == '_'), radix) - } - - private def parsedWidth(n: String) = - if (n(0) == 'b') { - Width(n.length-1) - } else if (n(0) == 'h') { - Width((n.length-1) * 4) - } else { - Width() - } -} - -object UInt extends UIntFactory - -sealed class SInt private (dir: Direction, width: Width, lit: Option[SLit] = None) - extends Bits(dir, width, lit) with Num[SInt] { - private[Chisel] override def cloneTypeWidth(w: Width): this.type = - new SInt(dir, w).asInstanceOf[this.type] - private[Chisel] def toType = s"SInt$width" - - override def := (that: Data)(implicit sourceInfo: SourceInfo): Unit = that match { - case _: SInt => this connect that - case _ => this badConnect that - } - - override private[Chisel] def fromInt(value: BigInt, width: Int): this.type = - SInt(value, width).asInstanceOf[this.type] - - 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 */ - 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 */ - final def +% (that: SInt): SInt = macro SourceInfoTransform.thatArg - /** subtract (width +1) operator */ - final def -& (that: SInt): SInt = macro SourceInfoTransform.thatArg - /** subtract (no growth) operator */ - 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 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 { - /** Create an SInt type with inferred width. */ - def apply(): SInt = apply(NO_DIR, Width()) - /** Create an SInt type or port with fixed width. */ - def apply(dir: Direction = NO_DIR, width: Int): SInt = apply(dir, Width(width)) - /** Create an SInt port with inferred width. */ - def apply(dir: Direction): SInt = apply(dir, Width()) - - /** Create an SInt literal with inferred width. */ - def apply(value: BigInt): SInt = apply(value, Width()) - /** Create an SInt literal with fixed width. */ - def apply(value: BigInt, width: Int): SInt = apply(value, Width(width)) - - /** Create an SInt type with specified width. */ - def apply(width: Width): SInt = new SInt(NO_DIR, width) - /** Create an SInt port with specified width. */ - def apply(dir: Direction, width: Width): SInt = new SInt(dir, width) - /** Create an SInt literal with specified width. */ - def apply(value: BigInt, width: Width): SInt = { - val lit = SLit(value, width) - new SInt(NO_DIR, lit.width, Some(lit)) - } -} - -// REVIEW TODO: Why does this extend UInt and not Bits? Does defining airth -// operations on a Bool make sense? -/** A data type for booleans, defined as a single bit indicating true or false. - */ -sealed class Bool(dir: Direction, lit: Option[ULit] = None) extends UInt(dir, Width(1), lit) { - private[Chisel] override def cloneTypeWidth(w: Width): this.type = { - require(!w.known || w.get == 1) - new Bool(dir).asInstanceOf[this.type] - } - - override private[Chisel] def fromInt(value: BigInt, width: Int): this.type = { - require((value == 0 || value == 1) && width == 1) - Bool(value == 1).asInstanceOf[this.type] - } - - // REVIEW TODO: Why does this need to exist and have different conventions - // than Bits? - 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 do_unary_~ (implicit sourceInfo: SourceInfo): Bool = - unop(sourceInfo, Bool(), BitNotOp) - - /** Outputs the logical OR of two Bools. - */ - 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 = macro SourceInfoTransform.thatArg - - def do_&& (that: Bool)(implicit sourceInfo: SourceInfo): Bool = this & that -} - -object Bool { - /** Creates an empty Bool. - */ - def apply(dir: Direction = NO_DIR): Bool = new Bool(dir) - - /** Creates Bool literal. - */ - def apply(x: Boolean): Bool = new Bool(NO_DIR, Some(ULit(if (x) 1 else 0, Width(1)))) -} - -object Mux { - /** Creates a mux, whose output is one of the inputs depending on the - * value of the condition. - * - * @param cond condition determining the input to choose - * @param con the value chosen when `cond` is true - * @param alt the value chosen when `cond` is false - * @example - * {{{ - * val muxOut = Mux(data_in === UInt(3), UInt(3, 4), UInt(0, 4)) - * }}} - */ - 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] - case (c: Bool, a: UInt) => doMux(cond, c << 0, a).asInstanceOf[T] - case (c: Bits, a: Bits) => doMux(cond, c, a).asInstanceOf[T] - case _ => doAggregateMux(cond, con, alt) - } - - 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(sourceInfo, d, MultiplexOp, cond.ref, con.ref, alt.ref)) - } - - 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") - doMux(cond, con, alt) - } -} - diff --git a/chiselFrontend/src/main/scala/Chisel/BlackBox.scala b/chiselFrontend/src/main/scala/Chisel/BlackBox.scala deleted file mode 100644 index b634f021..00000000 --- a/chiselFrontend/src/main/scala/Chisel/BlackBox.scala +++ /dev/null @@ -1,55 +0,0 @@ -// See LICENSE for license details. - -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 - * to RTL modules defined outside Chisel. - * - * @example - * {{{ - * ... to be written once a spec is finalized ... - * }}} - */ -// REVIEW TODO: make Verilog parameters part of the constructor interface? -abstract class BlackBox extends Module { - // Don't bother taking override_clock|reset, clock/reset locked out anyway - // TODO: actually implement this. - def setVerilogParameters(s: String): Unit = {} - - // The body of a BlackBox is empty, the real logic happens in firrtl/Emitter.scala - // Bypass standard clock, reset, io port declaration by flattening io - // TODO(twigg): ? Really, overrides are bad, should extend BaseModule.... - override private[Chisel] def ports = io.elements.toSeq - - // Do not do reflective naming of internal signals, just name io - override private[Chisel] def setRefs(): this.type = { - for ((name, port) <- ports) { - port.setRef(ModuleIO(this, _namespace.name(name))) - } - // setRef is not called on the actual io. - // There is a risk of user improperly attempting to connect directly with io - // Long term solution will be to define BlackBox IO differently as part of - // it not descending from the (current) Module - this - } - - // Don't setup clock, reset - // Cann't invalide io in one bunch, must invalidate each part separately - override private[Chisel] def setupInParent(implicit sourceInfo: SourceInfo): this.type = _parent match { - case Some(p) => { - // Just init instance inputs - for((_,port) <- ports) pushCommand(DefInvalid(sourceInfo, port.ref)) - this - } - case None => this - } - - // Using null is horrible but these signals SHOULD NEVER be used: - override val clock = null - override val reset = null -} diff --git a/chiselFrontend/src/main/scala/Chisel/Data.scala b/chiselFrontend/src/main/scala/Chisel/Data.scala deleted file mode 100644 index d16843f7..00000000 --- a/chiselFrontend/src/main/scala/Chisel/Data.scala +++ /dev/null @@ -1,161 +0,0 @@ -// 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, DeprecatedSourceInfo, UnlocatableSourceInfo, WireTransform, SourceInfoTransform} - -sealed abstract class Direction(name: String) { - override def toString: String = name - def flip: Direction -} -object INPUT extends Direction("input") { override def flip: Direction = OUTPUT } -object OUTPUT extends Direction("output") { override def flip: Direction = INPUT } -object NO_DIR extends Direction("?") { override def flip: Direction = NO_DIR } - -@deprecated("debug doesn't do anything in Chisel3 as no pruning happens in the frontend", "chisel3") -object debug { // scalastyle:ignore object.name - def apply (arg: Data): Data = arg -} - -/** Mixing in this trait flips the direction of an Aggregate. */ -trait Flipped extends Data { - this.overrideDirection(_.flip, !_) -} - -/** This forms the root of the type system for wire data types. The data value - * must be representable as some number (need not be known at Chisel compile - * time) of bits, and must have methods to pack / unpack structured data to / - * from bits. - */ -abstract class Data(dirArg: Direction) extends HasId { - def dir: Direction = dirVar - - // Sucks this is mutable state, but cloneType doesn't take a Direction arg - private var isFlipVar = dirArg == INPUT - private var dirVar = dirArg - private[Chisel] def isFlip = isFlipVar - - private[Chisel] def overrideDirection(newDir: Direction => Direction, - newFlip: Boolean => Boolean): this.type = { - this.isFlipVar = newFlip(this.isFlipVar) - for (field <- this.flatten) - (field: Data).dirVar = newDir((field: Data).dirVar) - this - } - def asInput: this.type = cloneType.overrideDirection(_ => INPUT, _ => true) - def asOutput: this.type = cloneType.overrideDirection(_ => OUTPUT, _ => false) - def flip(): this.type = cloneType.overrideDirection(_.flip, !_) - - private[Chisel] def badConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit = - throwException(s"cannot connect ${this} and ${that}") - 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)(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 - def isLit(): Boolean = litArg.isDefined - - def width: Width - final def getWidth: Int = width.get - - // While this being in the Data API doesn't really make sense (should be in - // Aggregate, right?) this is because of an implementation limitation: - // cloneWithDirection, which is private and defined here, needs flatten to - // set element directionality. - // Related: directionality is mutable state. A possible solution for both is - // to define directionality relative to the container, but these parent links - // currently don't exist (while this information may be available during - // FIRRTL emission, it would break directionality querying from Chisel, which - // does get used). - private[Chisel] def flatten: IndexedSeq[Bits] - - /** Creates an new instance of this type, unpacking the input Bits into - * structured data. - * - * This performs the inverse operation of toBits. - * - * @note does NOT assign to the object this is called on, instead creates - * and returns a NEW object (useful in a clone-and-assign scenario) - * @note does NOT check bit widths, may drop bits during assignment - * @note what fromBits assigs to must have known widths - */ - 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 (that.width.known && that.width.get >= wire.width.get) { - that - } else { - Wire(that.cloneTypeWidth(wire.width), init = that) - } - for (x <- wire.flatten) { - x := bits(i + x.getWidth-1, i) - i += x.getWidth - } - wire.asInstanceOf[this.type] - } - - /** Packs the value of this object as plain Bits. - * - * This performs the inverse operation of fromBits(Bits). - */ - @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 = 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 = - 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 = - do_apply(t, init)(UnlocatableSourceInfo) - - def do_apply[T <: Data](t: T, init: T)(implicit sourceInfo: SourceInfo): T = { - val x = Reg.makeType(t, null.asInstanceOf[T], init) - pushCommand(DefWire(sourceInfo, x)) - pushCommand(DefInvalid(sourceInfo, x.ref)) - if (init != null) { - x := init - } - x - } -} - -object Clock { - def apply(dir: Direction = NO_DIR): Clock = new Clock(dir) -} - -// TODO: Document this. -sealed class Clock(dirArg: Direction) extends Element(dirArg, Width(1)) { - def cloneType: this.type = Clock(dirArg).asInstanceOf[this.type] - private[Chisel] override def flatten: IndexedSeq[Bits] = IndexedSeq() - private[Chisel] def cloneTypeWidth(width: Width): this.type = cloneType - private[Chisel] def toType = "Clock" - - 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 deleted file mode 100644 index e34d5499..00000000 --- a/chiselFrontend/src/main/scala/Chisel/Mem.scala +++ /dev/null @@ -1,134 +0,0 @@ -// 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, 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] = 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] = 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(sourceInfo, mem, mt, size)) // TODO multi-clock - mem - } -} - -sealed abstract class MemBase[T <: Data](t: T, val length: Int) extends HasId with VecLike[T] { - // REVIEW TODO: make accessors (static/dynamic, read/write) combinations consistent. - - /** Creates a read accessor into the memory with static addressing. See the - * class documentation of the memory for more detailed information. - */ - def apply(idx: Int): T = apply(UInt(idx)) - - /** 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(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(UnlocatableSourceInfo, idx, MemPortDirection.READ) - - /** Creates a write accessor into the memory. - * - * @param idx memory element index to write into - * @param data new data to write - */ - def write(idx: UInt, data: T): Unit = { - implicit val sourceInfo = UnlocatableSourceInfo - makePort(UnlocatableSourceInfo, idx, MemPortDirection.WRITE) := data - } - - /** Creates a masked write accessor into the memory. - * - * @param idx memory element index to write into - * @param data new data to write - * @param mask write mask as a Vec of Bool: a write to the Vec element in - * memory is only performed if the corresponding mask index is true. - * - * @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 = { - 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})") - } - if (accessor.length != mask.length) { - Builder.error(s"Mem write mask must contain ${accessor.length} elements (found ${mask.length})") - } - for (((cond, port), datum) <- mask zip accessor zip dataVec) - when (cond) { port := datum } - } - - 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. - * - * Writes take effect on the rising clock edge after the request. Reads are - * combinational (requests will return data on the same cycle). - * Read-after-write hazards are not an issue. - * - * @note when multiple conflicting writes are performed on a Mem element, the - * result is undefined (unlike Vec, where the last assignment wins) - */ -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] = 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] = 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(sourceInfo, mem, mt, size)) // TODO multi-clock - mem - } -} - -/** A sequential-read, sequential-write memory. - * - * Writes take effect on the rising clock edge after the request. Reads return - * data on the rising edge after the request. Read-after-write behavior (when - * a read and write to the same address are requested on the same cycle) is - * undefined. - * - * @note when multiple conflicting writes are performed on a Mem element, the - * result is undefined (unlike Vec, where the last assignment wins) - */ -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 deleted file mode 100644 index e2101538..00000000 --- a/chiselFrontend/src/main/scala/Chisel/Module.scala +++ /dev/null @@ -1,119 +0,0 @@ -// See LICENSE for license details. - -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 - * (necessary to help Chisel track internal state). - * - * @param m the Module being created - * - * @return the input module `m` with Chisel metadata properly set - */ - 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(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(sourceInfo, m, ports)) - m.setupInParent(childSourceInfo) - } -} - -/** Abstract base class for Modules, which behave much like Verilog modules. - * These may contain both logic and state which are written in the Module - * body (constructor). - * - * @note Module instantiations must be wrapped in a Module() call. - */ -abstract class Module( - override_clock: Option[Clock]=None, override_reset: Option[Bool]=None) -extends HasId { - // _clock and _reset can be clock and reset in these 2ary constructors - // once chisel2 compatibility issues are resolved - def this(_clock: Clock) = this(Option(_clock), None) - def this(_reset: Bool) = this(None, Option(_reset)) - def this(_clock: Clock, _reset: Bool) = this(Option(_clock), Option(_reset)) - - private[Chisel] val _namespace = Builder.globalNamespace.child - private[Chisel] val _commands = ArrayBuffer[Command]() - private[Chisel] val _ids = ArrayBuffer[HasId]() - dynamicContext.currentModule = Some(this) - - /** Name of the instance. */ - val name = Builder.globalNamespace.name(getClass.getName.split('.').last) - - /** IO for this Module. At the Scala level (pre-FIRRTL transformations), - * connections in and out of a Module may only go through `io` elements. - */ - def io: Bundle - val clock = Clock(INPUT) - val reset = Bool(INPUT) - - private[Chisel] def addId(d: HasId) { _ids += d } - - private[Chisel] def ports: Seq[(String,Data)] = Vector( - ("clk", clock), ("reset", reset), ("io", io) - ) - - private[Chisel] def computePorts = for((name, port) <- ports) yield { - val bundleDir = if (port.isFlip) INPUT else OUTPUT - Port(port, if (port.dir == NO_DIR) bundleDir else port.dir) - } - - 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 - } - } - - private[Chisel] def setRefs(): this.type = { - for ((name, port) <- ports) { - port.setRef(ModuleIO(this, _namespace.name(name))) - } - - // Suggest names to nodes using runtime reflection - val valNames = HashSet[String](getClass.getDeclaredFields.map(_.getName):_*) - def isPublicVal(m: java.lang.reflect.Method) = - m.getParameterTypes.isEmpty && valNames.contains(m.getName) - val methods = getClass.getMethods.sortWith(_.getName > _.getName) - for (m <- methods; if isPublicVal(m)) m.invoke(this) match { - case (id: HasId) => id.suggestName(m.getName) - case _ => - } - - // For Module instances we haven't named, suggest the name of the Module - _ids foreach { - case m: Module => m.suggestName(m.name) - case _ => - } - - // All suggestions are in, force names to every node. - _ids.foreach(_.forceName(default="T", _namespace)) - _ids.foreach(_._onModuleClose) - this - } -} diff --git a/chiselFrontend/src/main/scala/Chisel/Printf.scala b/chiselFrontend/src/main/scala/Chisel/Printf.scala deleted file mode 100644 index f068f637..00000000 --- a/chiselFrontend/src/main/scala/Chisel/Printf.scala +++ /dev/null @@ -1,36 +0,0 @@ -// 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 deleted file mode 100644 index c8faa5c9..00000000 --- a/chiselFrontend/src/main/scala/Chisel/Reg.scala +++ /dev/null @@ -1,71 +0,0 @@ -// See LICENSE for license details. - -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 = { - if (t ne null) { - t.cloneType - } else if (next ne null) { - next.cloneTypeWidth(Width()) - } else if (init ne null) { - init.litArg match { - // For e.g. Reg(init=UInt(0, k)), fix the Reg's width to k - case Some(lit) if lit.forcedWidth => init.cloneType - case _ => init.cloneTypeWidth(Width()) - } - } else { - throwException("cannot infer type") - } - } - - /** Creates a register with optional next and initialization values. - * - * @param t: data type for the register - * @param next: new value register is to be updated with every cycle (or - * empty to not update unless assigned to using the := operator) - * @param init: initialization value on reset (or empty for uninitialized, - * where the register value persists across a reset) - * - * @note this may result in a type error if called from a type parameterized - * function, since the Scala compiler isn't smart enough to know that null - * 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 = - // 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()). - // Implicit conversions to Option (or similar) types were also considered, - // but Scala's type inferencer and implicit insertion isn't smart enough - // to resolve all use cases. If the type inferencer / implicit resolution - // system improves, this may be changed. - val x = makeType(t, next, init) - val clock = Node(x._parent.get.clock) // TODO multi-clock - if (init == null) { - pushCommand(DefReg(sourceInfo, x, clock)) - } else { - pushCommand(DefRegInit(sourceInfo, x, clock, Node(x._parent.get.reset), init.ref)) - } - if (next != null) { - x := next - } - x - } -} diff --git a/chiselFrontend/src/main/scala/Chisel/SeqUtils.scala b/chiselFrontend/src/main/scala/Chisel/SeqUtils.scala deleted file mode 100644 index 9a15fd5f..00000000 --- a/chiselFrontend/src/main/scala/Chisel/SeqUtils.scala +++ /dev/null @@ -1,59 +0,0 @@ -// See LICENSE for license details. - -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 = macro SourceInfoTransform.inArg - - def do_asUInt[T <: Bits](in: Seq[T])(implicit sourceInfo: SourceInfo): UInt = { - if (in.tail.isEmpty) { - in.head.asUInt - } else { - val left = asUInt(in.slice(0, in.length/2)) - val right = asUInt(in.slice(in.length/2, in.length)) - right ## left - } - } - - /** Counts the number of true Bools in a Seq */ - 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) { - in.head - } else { - count(in.slice(0, in.size/2)) + (UInt(0) ## count(in.slice(in.size/2, in.size))) - } - } - - /** Returns data value corresponding to first true predicate */ - def priorityMux[T <: Data](in: Seq[(Bool, T)]): T = macro SourceInfoTransform.inArg - - def do_priorityMux[T <: Data](in: Seq[(Bool, T)])(implicit sourceInfo: SourceInfo): T = { - if (in.size == 1) { - in.head._2 - } else { - Mux(in.head._1, in.head._2, priorityMux(in.tail)) - } - } - - /** Returns data value corresponding to lone true predicate */ - 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 { - val masked = for ((s, i) <- in) yield Mux(s, i.toBits, Bits(0)) - val width = in.map(_._2.width).reduce(_ max _) - in.head._2.cloneTypeWidth(width).fromBits(masked.reduceLeft(_|_)) - } - } -} diff --git a/chiselFrontend/src/main/scala/Chisel/When.scala b/chiselFrontend/src/main/scala/Chisel/When.scala deleted file mode 100644 index 90b3d1a5..00000000 --- a/chiselFrontend/src/main/scala/Chisel/When.scala +++ /dev/null @@ -1,59 +0,0 @@ -// 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 when { // scalastyle:ignore object.name - /** Create a `when` condition block, where whether a block of logic is - * executed or not depends on the conditional. - * - * @param cond condition to execute upon - * @param block logic that runs only if `cond` is true - * - * @example - * {{{ - * when ( myData === UInt(3) ) { - * // Some logic to run when myData equals 3. - * } .elsewhen ( myData === UInt(1) ) { - * // Some logic to run when myData equals 1. - * } .otherwise { - * // Some logic to run when myData is neither 3 nor 1. - * } - * }}} - */ - def apply(cond: Bool)(block: => Unit)(implicit sourceInfo: SourceInfo): WhenContext = { - new WhenContext(sourceInfo, cond, !cond, block) - } -} - -/** Internal mechanism for generating a when. Because of the way FIRRTL - * commands are emitted, generating a FIRRTL elsewhen or nested whens inside - * elses would be difficult. Instead, this keeps track of the negative of the - * previous conditions, so when an elsewhen or otherwise is used, it checks - * that both the condition is true and all the previous conditions have been - * false. - */ -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)(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)(implicit sourceInfo: SourceInfo): Unit = - new WhenContext(sourceInfo, prevCond, null, block) - - pushCommand(WhenBegin(sourceInfo, cond.ref)) - block - pushCommand(WhenEnd(sourceInfo)) -} diff --git a/chiselFrontend/src/main/scala/Chisel/internal/Builder.scala b/chiselFrontend/src/main/scala/Chisel/internal/Builder.scala deleted file mode 100644 index d0e28b7c..00000000 --- a/chiselFrontend/src/main/scala/Chisel/internal/Builder.scala +++ /dev/null @@ -1,123 +0,0 @@ -// See LICENSE for license details. - -package Chisel.internal - -import scala.util.DynamicVariable -import scala.collection.mutable.{ArrayBuffer, HashMap} - -import Chisel._ -import Chisel.internal.firrtl._ - -private[Chisel] class Namespace(parent: Option[Namespace], keywords: Set[String]) { - private var i = 0L - private val names = collection.mutable.HashSet[String]() - - private def rename(n: String) = { i += 1; s"${n}_${i}" } - - def contains(elem: String): Boolean = { - keywords.contains(elem) || names.contains(elem) || - parent.map(_ contains elem).getOrElse(false) - } - - def name(elem: String): String = { - if (this contains elem) { - name(rename(elem)) - } else { - names += elem - elem - } - } - - def child(kws: Set[String]): Namespace = new Namespace(Some(this), kws) - def child: Namespace = child(Set()) -} - -private[Chisel] class IdGen { - private var counter = -1L - def next: Long = { - counter += 1 - counter - } -} - -private[Chisel] trait HasId { - private[Chisel] def _onModuleClose {} // scalastyle:ignore method.name - private[Chisel] val _parent = Builder.dynamicContext.currentModule - _parent.foreach(_.addId(this)) - - private[Chisel] val _id = Builder.idGen.next - override def hashCode: Int = _id.toInt - override def equals(that: Any): Boolean = that match { - case x: HasId => _id == x._id - case _ => false - } - - // Facilities for 'suggesting' a name to this. - // Post-name hooks called to carry the suggestion to other candidates as needed - private var suggested_name: Option[String] = None - private val postname_hooks = scala.collection.mutable.ListBuffer.empty[String=>Unit] - // Only takes the first suggestion! - def suggestName(name: =>String): this.type = { - if(suggested_name.isEmpty) suggested_name = Some(name) - for(hook <- postname_hooks) { hook(name) } - this - } - private[Chisel] def addPostnameHook(hook: String=>Unit): Unit = postname_hooks += hook - - // Uses a namespace to convert suggestion into a true name - // Will not do any naming if the reference already assigned. - // (e.g. tried to suggest a name to part of a Bundle) - private[Chisel] def forceName(default: =>String, namespace: Namespace): Unit = - if(_ref.isEmpty) { - val candidate_name = suggested_name.getOrElse(default) - val available_name = namespace.name(candidate_name) - setRef(Ref(available_name)) - } - - private var _ref: Option[Arg] = None - private[Chisel] def setRef(imm: Arg): Unit = _ref = Some(imm) - private[Chisel] def setRef(parent: HasId, name: String): Unit = setRef(Slot(Node(parent), name)) - private[Chisel] def setRef(parent: HasId, index: Int): Unit = setRef(Index(Node(parent), ILit(index))) - private[Chisel] def setRef(parent: HasId, index: UInt): Unit = setRef(Index(Node(parent), index.ref)) - private[Chisel] def getRef: Arg = _ref.get -} - -private[Chisel] class DynamicContext { - val idGen = new IdGen - val globalNamespace = new Namespace(None, Set()) - val components = ArrayBuffer[Component]() - var currentModule: Option[Module] = None - val errors = new ErrorLog -} - -private[Chisel] object Builder { - // All global mutable state must be referenced via dynamicContextVar!! - private val dynamicContextVar = new DynamicVariable[Option[DynamicContext]](None) - - def dynamicContext: DynamicContext = - dynamicContextVar.value getOrElse (new DynamicContext) - def idGen: IdGen = dynamicContext.idGen - def globalNamespace: Namespace = dynamicContext.globalNamespace - def components: ArrayBuffer[Component] = dynamicContext.components - - def pushCommand[T <: Command](c: T): T = { - dynamicContext.currentModule.foreach(_._commands += c) - c - } - def pushOp[T <: Data](cmd: DefPrim[T]): T = pushCommand(cmd).id - - def errors: ErrorLog = dynamicContext.errors - def error(m: => String): Unit = errors.error(m) - - def build[T <: Module](f: => T): Circuit = { - dynamicContextVar.withValue(Some(new DynamicContext)) { - errors.info("Elaborating design...") - val mod = f - mod.forceName(mod.name, globalNamespace) - errors.checkpoint() - errors.info("Done elaborating.") - - Circuit(components.last.name, components) - } - } -} diff --git a/chiselFrontend/src/main/scala/Chisel/internal/Error.scala b/chiselFrontend/src/main/scala/Chisel/internal/Error.scala deleted file mode 100644 index 6c4c0880..00000000 --- a/chiselFrontend/src/main/scala/Chisel/internal/Error.scala +++ /dev/null @@ -1,91 +0,0 @@ -// See LICENSE for license details. - -package Chisel.internal - -import scala.collection.mutable.ArrayBuffer - -import Chisel._ - -class ChiselException(message: String, cause: Throwable) extends Exception(message, cause) - -private[Chisel] object throwException { - def apply(s: String, t: Throwable = null): Nothing = - throw new ChiselException(s, t) -} - -/** Records and reports runtime errors and warnings. */ -private[Chisel] class ErrorLog { - def hasErrors: Boolean = errors.exists(_.isFatal) - - /** Log an error message */ - def error(m: => String): Unit = - errors += new Error(m, getUserLineNumber) - - /** Log a warning message */ - def warning(m: => String): Unit = - errors += new Warning(m, getUserLineNumber) - - /** Emit an informational message */ - def info(m: String): Unit = - println(new Info("[%2.3f] %s".format(elapsedTime/1e3, m), None)) // scalastyle:ignore regex - - /** Prints error messages generated by Chisel at runtime. */ - def report(): Unit = errors foreach println // scalastyle:ignore regex - - /** Throw an exception if any errors have yet occurred. */ - def checkpoint(): Unit = if(hasErrors) { - import Console._ - throwException(errors.map(_ + "\n").reduce(_ + _) + - UNDERLINED + "CODE HAS " + errors.filter(_.isFatal).length + RESET + - UNDERLINED + " " + RED + "ERRORS" + RESET + - UNDERLINED + " and " + errors.filterNot(_.isFatal).length + RESET + - UNDERLINED + " " + YELLOW + "WARNINGS" + RESET) - } - - private def findFirstUserFrame(stack: Array[StackTraceElement]): Option[StackTraceElement] = { - def isUserCode(ste: StackTraceElement): Boolean = { - def isUserModule(c: Class[_]): Boolean = - c != null && (c == classOf[Module] || isUserModule(c.getSuperclass)) - isUserModule(Class.forName(ste.getClassName)) - } - - stack.indexWhere(isUserCode) match { - case x if x < 0 => None - case x => Some(stack(x)) - } - } - - private def getUserLineNumber = - findFirstUserFrame(Thread.currentThread().getStackTrace) - - private val errors = ArrayBuffer[LogEntry]() - - private val startTime = System.currentTimeMillis - private def elapsedTime: Long = System.currentTimeMillis - startTime -} - -private abstract class LogEntry(msg: => String, line: Option[StackTraceElement]) { - def isFatal: Boolean = false - def format: String - - override def toString: String = line match { - case Some(l) => s"${format} ${l.getFileName}:${l.getLineNumber}: ${msg} in class ${l.getClassName}" - case None => s"${format} ${msg}" - } - - protected def tag(name: String, color: String): String = - s"[${color}${name}${Console.RESET}]" -} - -private class Error(msg: => String, line: Option[StackTraceElement]) extends LogEntry(msg, line) { - override def isFatal: Boolean = true - def format: String = tag("error", Console.RED) -} - -private class Warning(msg: => String, line: Option[StackTraceElement]) extends LogEntry(msg, line) { - def format: String = tag("warn", Console.YELLOW) -} - -private class Info(msg: => String, line: Option[StackTraceElement]) extends LogEntry(msg, line) { - def format: String = tag("info", Console.MAGENTA) -} diff --git a/chiselFrontend/src/main/scala/Chisel/internal/SourceInfo.scala b/chiselFrontend/src/main/scala/Chisel/internal/SourceInfo.scala deleted file mode 100644 index 66bfc7a4..00000000 --- a/chiselFrontend/src/main/scala/Chisel/internal/SourceInfo.scala +++ /dev/null @@ -1,51 +0,0 @@ -// 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/IR.scala b/chiselFrontend/src/main/scala/Chisel/internal/firrtl/IR.scala deleted file mode 100644 index 62784cee..00000000 --- a/chiselFrontend/src/main/scala/Chisel/internal/firrtl/IR.scala +++ /dev/null @@ -1,188 +0,0 @@ -// See LICENSE for license details. - -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 -} - -object PrimOp { - val AddOp = PrimOp("add") - val SubOp = PrimOp("sub") - val TailOp = PrimOp("tail") - val HeadOp = PrimOp("head") - val TimesOp = PrimOp("mul") - val DivideOp = PrimOp("div") - val RemOp = PrimOp("rem") - val ShiftLeftOp = PrimOp("shl") - val ShiftRightOp = PrimOp("shr") - val DynamicShiftLeftOp = PrimOp("dshl") - val DynamicShiftRightOp = PrimOp("dshr") - val BitAndOp = PrimOp("and") - val BitOrOp = PrimOp("or") - val BitXorOp = PrimOp("xor") - val BitNotOp = PrimOp("not") - val ConcatOp = PrimOp("cat") - val BitsExtractOp = PrimOp("bits") - val LessOp = PrimOp("lt") - val LessEqOp = PrimOp("leq") - val GreaterOp = PrimOp("gt") - val GreaterEqOp = PrimOp("geq") - val EqualOp = PrimOp("eq") - val PadOp = PrimOp("pad") - val NotEqualOp = PrimOp("neq") - val NegOp = PrimOp("neg") - val MultiplexOp = PrimOp("mux") - val XorReduceOp = PrimOp("xorr") - val ConvertOp = PrimOp("cvt") - val AsUIntOp = PrimOp("asUInt") - val AsSIntOp = PrimOp("asSInt") -} - -abstract class Arg { - def fullName(ctx: Component): String = name - def name: String -} - -case class Node(id: HasId) extends Arg { - override def fullName(ctx: Component): String = id.getRef.fullName(ctx) - def name: String = id.getRef.name -} - -abstract class LitArg(val num: BigInt, widthArg: Width) extends Arg { - private[Chisel] def forcedWidth = widthArg.known - private[Chisel] def width: Width = if (forcedWidth) widthArg else Width(minWidth) - - protected def minWidth: Int - if (forcedWidth) { - require(widthArg.get >= minWidth, - s"The literal value ${num} was elaborated with a specificed width of ${widthArg.get} bits, but at least ${minWidth} bits are required.") - } -} - -case class ILit(n: BigInt) extends Arg { - def name: String = n.toString -} - -case class ULit(n: BigInt, w: Width) extends LitArg(n, w) { - def name: String = "UInt" + width + "(\"h0" + num.toString(16) + "\")" - def minWidth: Int = 1 max n.bitLength - - require(n >= 0, s"UInt literal ${n} is negative") -} - -case class SLit(n: BigInt, w: Width) extends LitArg(n, w) { - def name: String = { - val unsigned = if (n < 0) (BigInt(1) << width.get) + n else n - s"asSInt(${ULit(unsigned, width).name})" - } - def minWidth: Int = 1 + n.bitLength -} - -case class Ref(name: String) extends Arg -case class ModuleIO(mod: Module, name: String) extends Arg { - override def fullName(ctx: Component): String = - if (mod eq ctx.id) name else s"${mod.getRef.name}.$name" -} -case class Slot(imm: Node, name: String) extends Arg { - override def fullName(ctx: Component): String = - if (imm.fullName(ctx).isEmpty) name else s"${imm.fullName(ctx)}.${name}" -} -case class Index(imm: Arg, value: Arg) extends Arg { - def name: String = s"[$value]" - override def fullName(ctx: Component): String = s"${imm.fullName(ctx)}[${value.fullName(ctx)}]" -} - -object Width { - def apply(x: Int): Width = KnownWidth(x) - def apply(): Width = UnknownWidth() -} - -sealed abstract class Width { - type W = Int - def max(that: Width): Width = this.op(that, _ max _) - def + (that: Width): Width = this.op(that, _ + _) - def + (that: Int): Width = this.op(this, (a, b) => a + that) - def shiftRight(that: Int): Width = this.op(this, (a, b) => 0 max (a - that)) - def dynamicShiftLeft(that: Width): Width = - this.op(that, (a, b) => a + (1 << b) - 1) - - def known: Boolean - def get: W - protected def op(that: Width, f: (W, W) => W): Width -} - -sealed case class UnknownWidth() extends Width { - def known: Boolean = false - def get: Int = None.get - def op(that: Width, f: (W, W) => W): Width = this - override def toString: String = "" -} - -sealed case class KnownWidth(value: Int) extends Width { - require(value >= 0) - def known: Boolean = true - def get: Int = value - def op(that: Width, f: (W, W) => W): Width = that match { - case KnownWidth(x) => KnownWidth(f(value, x)) - case _ => that - } - override def toString: String = s"<${value.toString}>" -} - -sealed abstract class MemPortDirection(name: String) { - override def toString: String = name -} -object MemPortDirection { - object READ extends MemPortDirection("read") - object WRITE extends MemPortDirection("write") - object RDWR extends MemPortDirection("rdwr") - object INFER extends MemPortDirection("infer") -} - -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](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(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) = { - require(x.toInt >= 0) - if (x == '"' || x == '\\') { - s"\\${x}" - } else if (x == '\n') { - "\\n" - } else { - require(x.toInt >= 32) // TODO \xNN once FIRRTL issue #59 is resolved - x - } - } - formatIn.map(escaped _).mkString - } -} - -case class Circuit(name: String, components: Seq[Component]) diff --git a/chiselFrontend/src/main/scala/chisel/Aggregate.scala b/chiselFrontend/src/main/scala/chisel/Aggregate.scala new file mode 100644 index 00000000..4f3f3de0 --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel/Aggregate.scala @@ -0,0 +1,377 @@ +// See LICENSE for license details. + +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. + */ +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] = 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)) + 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] = 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 + * 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] = 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 + * 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] = 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 + * 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)(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])(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])(implicit sourceInfo: SourceInfo): Unit = this := that.asInstanceOf[Data] + + override def := (that: Data)(implicit sourceInfo: SourceInfo): 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])(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])(implicit sourceInfo: SourceInfo): 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)(DeprecatedSourceInfo) + + 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] 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 + + @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 = 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 = 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 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 = 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. + */ + 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 = 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 = 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. + * + * 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 = 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. + * + * 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)(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)(implicit sourceInfo: SourceInfo): 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") +} diff --git a/chiselFrontend/src/main/scala/chisel/Assert.scala b/chiselFrontend/src/main/scala/chisel/Assert.scala new file mode 100644 index 00000000..0d660bc3 --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel/Assert.scala @@ -0,0 +1,73 @@ +// See LICENSE for license details. + +package chisel + +import scala.reflect.macros.blackbox.Context +import scala.language.experimental.macros + +import internal._ +import internal.Builder.pushCommand +import internal.firrtl._ +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 + * condition evaluates to false, the circuit simulation stops with an error. + * + * 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 assert make the standard Module assumptions (single clock + * and single reset). + * + * @param cond condition, assertion fires (simulation fails) when false + * @param message optional message to print when the assertion fires + * + * @note currently cannot be used in core Chisel / libraries because macro + * defs need to be compiled first and the SBT project is not set up to do + * that + */ + // 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)(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))($sourceInfo)" + } + + 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)($sourceInfo)" + } + + 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(sourceInfo, Node(Builder.dynamicContext.currentModule.get.clock), 1)) + } + } + + /** An elaboration-time assertion, otherwise the same as the above run-time + * assertion. */ + def apply(cond: Boolean, message: => String) { + Predef.assert(cond, message) + } + + /** A workaround for default-value overloading problems in Scala, just + * 'assert(cond, "")' */ + def apply(cond: Boolean) { + Predef.assert(cond, "") + } +} diff --git a/chiselFrontend/src/main/scala/chisel/Bits.scala b/chiselFrontend/src/main/scala/chisel/Bits.scala new file mode 100644 index 00000000..8ec7c1b9 --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel/Bits.scala @@ -0,0 +1,756 @@ +// See LICENSE for license details. + +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 + * uses are for representing primitive data types, like integers and bits. + */ +abstract class Element(dirArg: Direction, val width: Width) extends Data(dirArg) + +/** A data type for values represented by a single bitvector. Provides basic + * bitwise operations. + */ +sealed abstract class Bits(dirArg: Direction, width: Width, override val litArg: Option[LitArg]) + extends Element(dirArg, width) { + // TODO: perhaps make this concrete? + // Arguments for: self-checking code (can't do arithmetic on bits) + // Arguments against: generates down to a FIRRTL UInt anyways + + private[chisel] def fromInt(x: BigInt, w: Int): this.type + + private[chisel] def flatten: IndexedSeq[Bits] = IndexedSeq(this) + + def cloneType: this.type = cloneTypeWidth(width) + + 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 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(sourceInfo, UInt(width = w), TailOp, n) + } + + + 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(sourceInfo, UInt(width = n), HeadOp, n) + } + + /** Returns the specified bit on this wire as a [[Bool]], statically + * addressed. + */ + 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(sourceInfo, Bool(), BitsExtractOp, this.ref, ILit(x), ILit(x))) + } + } + + /** Returns the specified bit on this wire as a [[Bool]], statically + * addressed. + * + * @note convenience method allowing direct use of Ints without implicits + */ + 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 = 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. + * + * @example + * {{{ + * myBits = 0x5 = 0b101 + * myBits(1,0) => 0b01 // extracts the two least significant bits + * }}} + */ + 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)") + } + val w = x - y + 1 + if (isLit()) { + UInt((litValue >> y) & ((BigInt(1) << w) - 1), w) + } else { + 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 = 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 + */ + 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? + 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. + */ + 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. + */ + final def << (that: UInt): Bits = macro SourceInfoWhiteboxTransform.thatArg + + def do_<< (that: UInt)(implicit sourceInfo: SourceInfo): Bits + + /** Shift right operation */ + // REVIEW TODO: redundant + 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. + */ + 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. + */ + 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. + */ + 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 + */ + 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 + */ + final def asUInt(): UInt = macro SourceInfoTransform.noArg + + def do_asUInt(implicit sourceInfo: SourceInfo): UInt + + /** Reinterpret cast to Bits. */ + 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 = do_asSInt(DeprecatedSourceInfo) + @deprecated("Use asUInt, which makes the reinterpret cast more explicit", "chisel3") + final def toUInt(): UInt = do_asUInt(DeprecatedSourceInfo) + + final def toBool(): Bool = macro SourceInfoTransform.noArg + + 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. + */ + 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 = do_asUInt(DeprecatedSourceInfo) + + override def do_fromBits(that: Bits)(implicit sourceInfo: SourceInfo): this.type = { + val res = Wire(this, null).asInstanceOf[this.type] + res := that + res + } +} + +/** Provides a set of operations to create UInt types and literals. + * Identical in functionality to the UInt companion object. + */ +object Bits extends UIntFactory + +// REVIEW TODO: Further discussion needed on what Num actually is. +/** Abstract trait defining operations available on numeric-like wire data + * types. + */ +abstract trait Num[T <: Data] { + // def << (b: T): T + // def >> (b: T): T + //def unary_-(): T + + // REVIEW TODO: double check ops conventions against FIRRTL + + /** Outputs the sum of `this` and `b`. The resulting width is the max of the + * operands plus 1 (should not overflow). + */ + 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. + * + * @note can generate a single-cycle multiplier, which can result in + * significant cycle time and area costs + */ + 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 + */ + final def / (that: T): T = macro SourceInfoTransform.thatArg + + 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). + */ + final def - (that: T): T = macro SourceInfoTransform.thatArg + + def do_- (that: T)(implicit sourceInfo: SourceInfo): T + + /** Outputs true if `this` < `b`. + */ + final def < (that: T): Bool = macro SourceInfoTransform.thatArg + + def do_< (that: T)(implicit sourceInfo: SourceInfo): Bool + + /** Outputs true if `this` <= `b`. + */ + final def <= (that: T): Bool = macro SourceInfoTransform.thatArg + + def do_<= (that: T)(implicit sourceInfo: SourceInfo): Bool + + /** Outputs true if `this` > `b`. + */ + final def > (that: T): Bool = macro SourceInfoTransform.thatArg + + def do_> (that: T)(implicit sourceInfo: SourceInfo): Bool + + /** Outputs true if `this` >= `b`. + */ + 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. + */ + 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. + */ + 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. + * Defines arithmetic operations between other integer types. + */ +sealed class UInt private[chisel] (dir: Direction, width: Width, lit: Option[ULit] = None) + extends Bits(dir, width, lit) with Num[UInt] { + private[chisel] override def cloneTypeWidth(w: Width): this.type = + new UInt(dir, w).asInstanceOf[this.type] + private[chisel] def toType = s"UInt$width" + + override private[chisel] def fromInt(value: BigInt, width: Int): this.type = + UInt(value, width).asInstanceOf[this.type] + + 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 + 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 do_unary_~ (implicit sourceInfo: SourceInfo): UInt = + unop(sourceInfo, UInt(width = width), BitNotOp) + + // REVIEW TODO: Can this be defined on Bits? + 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)) + } + + /** 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. + 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). + */ + 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. +private[chisel] sealed trait UIntFactory { + /** Create a UInt type with inferred width. */ + def apply(): UInt = apply(NO_DIR, Width()) + /** Create a UInt type or port with fixed width. */ + def apply(dir: Direction = NO_DIR, width: Int): UInt = apply(dir, Width(width)) + /** Create a UInt port with inferred width. */ + def apply(dir: Direction): UInt = apply(dir, Width()) + + /** Create a UInt literal with inferred width. */ + def apply(value: BigInt): UInt = apply(value, Width()) + /** Create a UInt literal with fixed width. */ + def apply(value: BigInt, width: Int): UInt = apply(value, Width(width)) + /** Create a UInt literal with inferred width. */ + def apply(n: String): UInt = apply(parse(n), parsedWidth(n)) + /** Create a UInt literal with fixed width. */ + def apply(n: String, width: Int): UInt = apply(parse(n), width) + + /** Create a UInt type with specified width. */ + def apply(width: Width): UInt = apply(NO_DIR, width) + /** Create a UInt port with specified width. */ + def apply(dir: Direction, width: Width): UInt = new UInt(dir, width) + /** Create a UInt literal with specified width. */ + def apply(value: BigInt, width: Width): UInt = { + val lit = ULit(value, width) + new UInt(NO_DIR, lit.width, Some(lit)) + } + + private def parse(n: String) = { + val (base, num) = n.splitAt(1) + val radix = base match { + case "x" | "h" => 16 + case "d" => 10 + case "o" => 8 + case "b" => 2 + case _ => Builder.error(s"Invalid base $base"); 2 + } + BigInt(num.filterNot(_ == '_'), radix) + } + + private def parsedWidth(n: String) = + if (n(0) == 'b') { + Width(n.length-1) + } else if (n(0) == 'h') { + Width((n.length-1) * 4) + } else { + Width() + } +} + +object UInt extends UIntFactory + +sealed class SInt private (dir: Direction, width: Width, lit: Option[SLit] = None) + extends Bits(dir, width, lit) with Num[SInt] { + private[chisel] override def cloneTypeWidth(w: Width): this.type = + new SInt(dir, w).asInstanceOf[this.type] + private[chisel] def toType = s"SInt$width" + + override def := (that: Data)(implicit sourceInfo: SourceInfo): Unit = that match { + case _: SInt => this connect that + case _ => this badConnect that + } + + override private[chisel] def fromInt(value: BigInt, width: Int): this.type = + SInt(value, width).asInstanceOf[this.type] + + 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 */ + 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 */ + final def +% (that: SInt): SInt = macro SourceInfoTransform.thatArg + /** subtract (width +1) operator */ + final def -& (that: SInt): SInt = macro SourceInfoTransform.thatArg + /** subtract (no growth) operator */ + 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 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 { + /** Create an SInt type with inferred width. */ + def apply(): SInt = apply(NO_DIR, Width()) + /** Create an SInt type or port with fixed width. */ + def apply(dir: Direction = NO_DIR, width: Int): SInt = apply(dir, Width(width)) + /** Create an SInt port with inferred width. */ + def apply(dir: Direction): SInt = apply(dir, Width()) + + /** Create an SInt literal with inferred width. */ + def apply(value: BigInt): SInt = apply(value, Width()) + /** Create an SInt literal with fixed width. */ + def apply(value: BigInt, width: Int): SInt = apply(value, Width(width)) + + /** Create an SInt type with specified width. */ + def apply(width: Width): SInt = new SInt(NO_DIR, width) + /** Create an SInt port with specified width. */ + def apply(dir: Direction, width: Width): SInt = new SInt(dir, width) + /** Create an SInt literal with specified width. */ + def apply(value: BigInt, width: Width): SInt = { + val lit = SLit(value, width) + new SInt(NO_DIR, lit.width, Some(lit)) + } +} + +// REVIEW TODO: Why does this extend UInt and not Bits? Does defining airth +// operations on a Bool make sense? +/** A data type for booleans, defined as a single bit indicating true or false. + */ +sealed class Bool(dir: Direction, lit: Option[ULit] = None) extends UInt(dir, Width(1), lit) { + private[chisel] override def cloneTypeWidth(w: Width): this.type = { + require(!w.known || w.get == 1) + new Bool(dir).asInstanceOf[this.type] + } + + override private[chisel] def fromInt(value: BigInt, width: Int): this.type = { + require((value == 0 || value == 1) && width == 1) + Bool(value == 1).asInstanceOf[this.type] + } + + // REVIEW TODO: Why does this need to exist and have different conventions + // than Bits? + 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 do_unary_~ (implicit sourceInfo: SourceInfo): Bool = + unop(sourceInfo, Bool(), BitNotOp) + + /** Outputs the logical OR of two Bools. + */ + 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 = macro SourceInfoTransform.thatArg + + def do_&& (that: Bool)(implicit sourceInfo: SourceInfo): Bool = this & that +} + +object Bool { + /** Creates an empty Bool. + */ + def apply(dir: Direction = NO_DIR): Bool = new Bool(dir) + + /** Creates Bool literal. + */ + def apply(x: Boolean): Bool = new Bool(NO_DIR, Some(ULit(if (x) 1 else 0, Width(1)))) +} + +object Mux { + /** Creates a mux, whose output is one of the inputs depending on the + * value of the condition. + * + * @param cond condition determining the input to choose + * @param con the value chosen when `cond` is true + * @param alt the value chosen when `cond` is false + * @example + * {{{ + * val muxOut = Mux(data_in === UInt(3), UInt(3, 4), UInt(0, 4)) + * }}} + */ + 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] + case (c: Bool, a: UInt) => doMux(cond, c << 0, a).asInstanceOf[T] + case (c: Bits, a: Bits) => doMux(cond, c, a).asInstanceOf[T] + case _ => doAggregateMux(cond, con, alt) + } + + 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(sourceInfo, d, MultiplexOp, cond.ref, con.ref, alt.ref)) + } + + 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") + doMux(cond, con, alt) + } +} + diff --git a/chiselFrontend/src/main/scala/chisel/BlackBox.scala b/chiselFrontend/src/main/scala/chisel/BlackBox.scala new file mode 100644 index 00000000..1dabc18f --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel/BlackBox.scala @@ -0,0 +1,55 @@ +// See LICENSE for license details. + +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 + * to RTL modules defined outside Chisel. + * + * @example + * {{{ + * ... to be written once a spec is finalized ... + * }}} + */ +// REVIEW TODO: make Verilog parameters part of the constructor interface? +abstract class BlackBox extends Module { + // Don't bother taking override_clock|reset, clock/reset locked out anyway + // TODO: actually implement this. + def setVerilogParameters(s: String): Unit = {} + + // The body of a BlackBox is empty, the real logic happens in firrtl/Emitter.scala + // Bypass standard clock, reset, io port declaration by flattening io + // TODO(twigg): ? Really, overrides are bad, should extend BaseModule.... + override private[chisel] def ports = io.elements.toSeq + + // Do not do reflective naming of internal signals, just name io + override private[chisel] def setRefs(): this.type = { + for ((name, port) <- ports) { + port.setRef(ModuleIO(this, _namespace.name(name))) + } + // setRef is not called on the actual io. + // There is a risk of user improperly attempting to connect directly with io + // Long term solution will be to define BlackBox IO differently as part of + // it not descending from the (current) Module + this + } + + // Don't setup clock, reset + // Cann't invalide io in one bunch, must invalidate each part separately + override private[chisel] def setupInParent(implicit sourceInfo: SourceInfo): this.type = _parent match { + case Some(p) => { + // Just init instance inputs + for((_,port) <- ports) pushCommand(DefInvalid(sourceInfo, port.ref)) + this + } + case None => this + } + + // Using null is horrible but these signals SHOULD NEVER be used: + override val clock = null + override val reset = null +} diff --git a/chiselFrontend/src/main/scala/chisel/Data.scala b/chiselFrontend/src/main/scala/chisel/Data.scala new file mode 100644 index 00000000..c08adf9d --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel/Data.scala @@ -0,0 +1,161 @@ +// 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, DeprecatedSourceInfo, UnlocatableSourceInfo, WireTransform, SourceInfoTransform} + +sealed abstract class Direction(name: String) { + override def toString: String = name + def flip: Direction +} +object INPUT extends Direction("input") { override def flip: Direction = OUTPUT } +object OUTPUT extends Direction("output") { override def flip: Direction = INPUT } +object NO_DIR extends Direction("?") { override def flip: Direction = NO_DIR } + +@deprecated("debug doesn't do anything in Chisel3 as no pruning happens in the frontend", "chisel3") +object debug { // scalastyle:ignore object.name + def apply (arg: Data): Data = arg +} + +/** Mixing in this trait flips the direction of an Aggregate. */ +trait Flipped extends Data { + this.overrideDirection(_.flip, !_) +} + +/** This forms the root of the type system for wire data types. The data value + * must be representable as some number (need not be known at Chisel compile + * time) of bits, and must have methods to pack / unpack structured data to / + * from bits. + */ +abstract class Data(dirArg: Direction) extends HasId { + def dir: Direction = dirVar + + // Sucks this is mutable state, but cloneType doesn't take a Direction arg + private var isFlipVar = dirArg == INPUT + private var dirVar = dirArg + private[chisel] def isFlip = isFlipVar + + private[chisel] def overrideDirection(newDir: Direction => Direction, + newFlip: Boolean => Boolean): this.type = { + this.isFlipVar = newFlip(this.isFlipVar) + for (field <- this.flatten) + (field: Data).dirVar = newDir((field: Data).dirVar) + this + } + def asInput: this.type = cloneType.overrideDirection(_ => INPUT, _ => true) + def asOutput: this.type = cloneType.overrideDirection(_ => OUTPUT, _ => false) + def flip(): this.type = cloneType.overrideDirection(_.flip, !_) + + private[chisel] def badConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit = + throwException(s"cannot connect ${this} and ${that}") + 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)(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 + def isLit(): Boolean = litArg.isDefined + + def width: Width + final def getWidth: Int = width.get + + // While this being in the Data API doesn't really make sense (should be in + // Aggregate, right?) this is because of an implementation limitation: + // cloneWithDirection, which is private and defined here, needs flatten to + // set element directionality. + // Related: directionality is mutable state. A possible solution for both is + // to define directionality relative to the container, but these parent links + // currently don't exist (while this information may be available during + // FIRRTL emission, it would break directionality querying from Chisel, which + // does get used). + private[chisel] def flatten: IndexedSeq[Bits] + + /** Creates an new instance of this type, unpacking the input Bits into + * structured data. + * + * This performs the inverse operation of toBits. + * + * @note does NOT assign to the object this is called on, instead creates + * and returns a NEW object (useful in a clone-and-assign scenario) + * @note does NOT check bit widths, may drop bits during assignment + * @note what fromBits assigs to must have known widths + */ + 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 (that.width.known && that.width.get >= wire.width.get) { + that + } else { + Wire(that.cloneTypeWidth(wire.width), init = that) + } + for (x <- wire.flatten) { + x := bits(i + x.getWidth-1, i) + i += x.getWidth + } + wire.asInstanceOf[this.type] + } + + /** Packs the value of this object as plain Bits. + * + * This performs the inverse operation of fromBits(Bits). + */ + @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 = 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 = + 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 = + do_apply(t, init)(UnlocatableSourceInfo) + + def do_apply[T <: Data](t: T, init: T)(implicit sourceInfo: SourceInfo): T = { + val x = Reg.makeType(t, null.asInstanceOf[T], init) + pushCommand(DefWire(sourceInfo, x)) + pushCommand(DefInvalid(sourceInfo, x.ref)) + if (init != null) { + x := init + } + x + } +} + +object Clock { + def apply(dir: Direction = NO_DIR): Clock = new Clock(dir) +} + +// TODO: Document this. +sealed class Clock(dirArg: Direction) extends Element(dirArg, Width(1)) { + def cloneType: this.type = Clock(dirArg).asInstanceOf[this.type] + private[chisel] override def flatten: IndexedSeq[Bits] = IndexedSeq() + private[chisel] def cloneTypeWidth(width: Width): this.type = cloneType + private[chisel] def toType = "Clock" + + 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 new file mode 100644 index 00000000..5fd8b81e --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel/Mem.scala @@ -0,0 +1,134 @@ +// 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, 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] = 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] = 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(sourceInfo, mem, mt, size)) // TODO multi-clock + mem + } +} + +sealed abstract class MemBase[T <: Data](t: T, val length: Int) extends HasId with VecLike[T] { + // REVIEW TODO: make accessors (static/dynamic, read/write) combinations consistent. + + /** Creates a read accessor into the memory with static addressing. See the + * class documentation of the memory for more detailed information. + */ + def apply(idx: Int): T = apply(UInt(idx)) + + /** 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(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(UnlocatableSourceInfo, idx, MemPortDirection.READ) + + /** Creates a write accessor into the memory. + * + * @param idx memory element index to write into + * @param data new data to write + */ + def write(idx: UInt, data: T): Unit = { + implicit val sourceInfo = UnlocatableSourceInfo + makePort(UnlocatableSourceInfo, idx, MemPortDirection.WRITE) := data + } + + /** Creates a masked write accessor into the memory. + * + * @param idx memory element index to write into + * @param data new data to write + * @param mask write mask as a Vec of Bool: a write to the Vec element in + * memory is only performed if the corresponding mask index is true. + * + * @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 = { + 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})") + } + if (accessor.length != mask.length) { + Builder.error(s"Mem write mask must contain ${accessor.length} elements (found ${mask.length})") + } + for (((cond, port), datum) <- mask zip accessor zip dataVec) + when (cond) { port := datum } + } + + 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. + * + * Writes take effect on the rising clock edge after the request. Reads are + * combinational (requests will return data on the same cycle). + * Read-after-write hazards are not an issue. + * + * @note when multiple conflicting writes are performed on a Mem element, the + * result is undefined (unlike Vec, where the last assignment wins) + */ +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] = 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] = 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(sourceInfo, mem, mt, size)) // TODO multi-clock + mem + } +} + +/** A sequential-read, sequential-write memory. + * + * Writes take effect on the rising clock edge after the request. Reads return + * data on the rising edge after the request. Read-after-write behavior (when + * a read and write to the same address are requested on the same cycle) is + * undefined. + * + * @note when multiple conflicting writes are performed on a Mem element, the + * result is undefined (unlike Vec, where the last assignment wins) + */ +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 new file mode 100644 index 00000000..f7f8c0b5 --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel/Module.scala @@ -0,0 +1,119 @@ +// See LICENSE for license details. + +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 + * (necessary to help Chisel track internal state). + * + * @param m the Module being created + * + * @return the input module `m` with Chisel metadata properly set + */ + 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(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(sourceInfo, m, ports)) + m.setupInParent(childSourceInfo) + } +} + +/** Abstract base class for Modules, which behave much like Verilog modules. + * These may contain both logic and state which are written in the Module + * body (constructor). + * + * @note Module instantiations must be wrapped in a Module() call. + */ +abstract class Module( + override_clock: Option[Clock]=None, override_reset: Option[Bool]=None) +extends HasId { + // _clock and _reset can be clock and reset in these 2ary constructors + // once chisel2 compatibility issues are resolved + def this(_clock: Clock) = this(Option(_clock), None) + def this(_reset: Bool) = this(None, Option(_reset)) + def this(_clock: Clock, _reset: Bool) = this(Option(_clock), Option(_reset)) + + private[chisel] val _namespace = Builder.globalNamespace.child + private[chisel] val _commands = ArrayBuffer[Command]() + private[chisel] val _ids = ArrayBuffer[HasId]() + dynamicContext.currentModule = Some(this) + + /** Name of the instance. */ + val name = Builder.globalNamespace.name(getClass.getName.split('.').last) + + /** IO for this Module. At the Scala level (pre-FIRRTL transformations), + * connections in and out of a Module may only go through `io` elements. + */ + def io: Bundle + val clock = Clock(INPUT) + val reset = Bool(INPUT) + + private[chisel] def addId(d: HasId) { _ids += d } + + private[chisel] def ports: Seq[(String,Data)] = Vector( + ("clk", clock), ("reset", reset), ("io", io) + ) + + private[chisel] def computePorts = for((name, port) <- ports) yield { + val bundleDir = if (port.isFlip) INPUT else OUTPUT + Port(port, if (port.dir == NO_DIR) bundleDir else port.dir) + } + + 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 + } + } + + private[chisel] def setRefs(): this.type = { + for ((name, port) <- ports) { + port.setRef(ModuleIO(this, _namespace.name(name))) + } + + // Suggest names to nodes using runtime reflection + val valNames = HashSet[String](getClass.getDeclaredFields.map(_.getName):_*) + def isPublicVal(m: java.lang.reflect.Method) = + m.getParameterTypes.isEmpty && valNames.contains(m.getName) + val methods = getClass.getMethods.sortWith(_.getName > _.getName) + for (m <- methods; if isPublicVal(m)) m.invoke(this) match { + case (id: HasId) => id.suggestName(m.getName) + case _ => + } + + // For Module instances we haven't named, suggest the name of the Module + _ids foreach { + case m: Module => m.suggestName(m.name) + case _ => + } + + // All suggestions are in, force names to every node. + _ids.foreach(_.forceName(default="T", _namespace)) + _ids.foreach(_._onModuleClose) + this + } +} diff --git a/chiselFrontend/src/main/scala/chisel/Printf.scala b/chiselFrontend/src/main/scala/chisel/Printf.scala new file mode 100644 index 00000000..27b72815 --- /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 new file mode 100644 index 00000000..0ed320d7 --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel/Reg.scala @@ -0,0 +1,71 @@ +// See LICENSE for license details. + +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 = { + if (t ne null) { + t.cloneType + } else if (next ne null) { + next.cloneTypeWidth(Width()) + } else if (init ne null) { + init.litArg match { + // For e.g. Reg(init=UInt(0, k)), fix the Reg's width to k + case Some(lit) if lit.forcedWidth => init.cloneType + case _ => init.cloneTypeWidth(Width()) + } + } else { + throwException("cannot infer type") + } + } + + /** Creates a register with optional next and initialization values. + * + * @param t: data type for the register + * @param next: new value register is to be updated with every cycle (or + * empty to not update unless assigned to using the := operator) + * @param init: initialization value on reset (or empty for uninitialized, + * where the register value persists across a reset) + * + * @note this may result in a type error if called from a type parameterized + * function, since the Scala compiler isn't smart enough to know that null + * 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 = + // 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()). + // Implicit conversions to Option (or similar) types were also considered, + // but Scala's type inferencer and implicit insertion isn't smart enough + // to resolve all use cases. If the type inferencer / implicit resolution + // system improves, this may be changed. + val x = makeType(t, next, init) + val clock = Node(x._parent.get.clock) // TODO multi-clock + if (init == null) { + pushCommand(DefReg(sourceInfo, x, clock)) + } else { + pushCommand(DefRegInit(sourceInfo, x, clock, Node(x._parent.get.reset), init.ref)) + } + if (next != null) { + x := next + } + x + } +} diff --git a/chiselFrontend/src/main/scala/chisel/SeqUtils.scala b/chiselFrontend/src/main/scala/chisel/SeqUtils.scala new file mode 100644 index 00000000..da75edae --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel/SeqUtils.scala @@ -0,0 +1,59 @@ +// See LICENSE for license details. + +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 = macro SourceInfoTransform.inArg + + def do_asUInt[T <: Bits](in: Seq[T])(implicit sourceInfo: SourceInfo): UInt = { + if (in.tail.isEmpty) { + in.head.asUInt + } else { + val left = asUInt(in.slice(0, in.length/2)) + val right = asUInt(in.slice(in.length/2, in.length)) + right ## left + } + } + + /** Counts the number of true Bools in a Seq */ + 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) { + in.head + } else { + count(in.slice(0, in.size/2)) + (UInt(0) ## count(in.slice(in.size/2, in.size))) + } + } + + /** Returns data value corresponding to first true predicate */ + def priorityMux[T <: Data](in: Seq[(Bool, T)]): T = macro SourceInfoTransform.inArg + + def do_priorityMux[T <: Data](in: Seq[(Bool, T)])(implicit sourceInfo: SourceInfo): T = { + if (in.size == 1) { + in.head._2 + } else { + Mux(in.head._1, in.head._2, priorityMux(in.tail)) + } + } + + /** Returns data value corresponding to lone true predicate */ + 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 { + val masked = for ((s, i) <- in) yield Mux(s, i.toBits, Bits(0)) + val width = in.map(_._2.width).reduce(_ max _) + in.head._2.cloneTypeWidth(width).fromBits(masked.reduceLeft(_|_)) + } + } +} diff --git a/chiselFrontend/src/main/scala/chisel/When.scala b/chiselFrontend/src/main/scala/chisel/When.scala new file mode 100644 index 00000000..37c59f24 --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel/When.scala @@ -0,0 +1,59 @@ +// 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 when { // scalastyle:ignore object.name + /** Create a `when` condition block, where whether a block of logic is + * executed or not depends on the conditional. + * + * @param cond condition to execute upon + * @param block logic that runs only if `cond` is true + * + * @example + * {{{ + * when ( myData === UInt(3) ) { + * // Some logic to run when myData equals 3. + * } .elsewhen ( myData === UInt(1) ) { + * // Some logic to run when myData equals 1. + * } .otherwise { + * // Some logic to run when myData is neither 3 nor 1. + * } + * }}} + */ + def apply(cond: Bool)(block: => Unit)(implicit sourceInfo: SourceInfo): WhenContext = { + new WhenContext(sourceInfo, cond, !cond, block) + } +} + +/** Internal mechanism for generating a when. Because of the way FIRRTL + * commands are emitted, generating a FIRRTL elsewhen or nested whens inside + * elses would be difficult. Instead, this keeps track of the negative of the + * previous conditions, so when an elsewhen or otherwise is used, it checks + * that both the condition is true and all the previous conditions have been + * false. + */ +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)(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)(implicit sourceInfo: SourceInfo): Unit = + new WhenContext(sourceInfo, prevCond, null, block) + + pushCommand(WhenBegin(sourceInfo, cond.ref)) + block + pushCommand(WhenEnd(sourceInfo)) +} diff --git a/chiselFrontend/src/main/scala/chisel/internal/Builder.scala b/chiselFrontend/src/main/scala/chisel/internal/Builder.scala new file mode 100644 index 00000000..bacde365 --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel/internal/Builder.scala @@ -0,0 +1,123 @@ +// See LICENSE for license details. + +package chisel.internal + +import scala.util.DynamicVariable +import scala.collection.mutable.{ArrayBuffer, HashMap} + +import chisel._ +import firrtl._ + +private[chisel] class Namespace(parent: Option[Namespace], keywords: Set[String]) { + private var i = 0L + private val names = collection.mutable.HashSet[String]() + + private def rename(n: String) = { i += 1; s"${n}_${i}" } + + def contains(elem: String): Boolean = { + keywords.contains(elem) || names.contains(elem) || + parent.map(_ contains elem).getOrElse(false) + } + + def name(elem: String): String = { + if (this contains elem) { + name(rename(elem)) + } else { + names += elem + elem + } + } + + def child(kws: Set[String]): Namespace = new Namespace(Some(this), kws) + def child: Namespace = child(Set()) +} + +private[chisel] class IdGen { + private var counter = -1L + def next: Long = { + counter += 1 + counter + } +} + +private[chisel] trait HasId { + private[chisel] def _onModuleClose {} // scalastyle:ignore method.name + private[chisel] val _parent = Builder.dynamicContext.currentModule + _parent.foreach(_.addId(this)) + + private[chisel] val _id = Builder.idGen.next + override def hashCode: Int = _id.toInt + override def equals(that: Any): Boolean = that match { + case x: HasId => _id == x._id + case _ => false + } + + // Facilities for 'suggesting' a name to this. + // Post-name hooks called to carry the suggestion to other candidates as needed + private var suggested_name: Option[String] = None + private val postname_hooks = scala.collection.mutable.ListBuffer.empty[String=>Unit] + // Only takes the first suggestion! + def suggestName(name: =>String): this.type = { + if(suggested_name.isEmpty) suggested_name = Some(name) + for(hook <- postname_hooks) { hook(name) } + this + } + private[chisel] def addPostnameHook(hook: String=>Unit): Unit = postname_hooks += hook + + // Uses a namespace to convert suggestion into a true name + // Will not do any naming if the reference already assigned. + // (e.g. tried to suggest a name to part of a Bundle) + private[chisel] def forceName(default: =>String, namespace: Namespace): Unit = + if(_ref.isEmpty) { + val candidate_name = suggested_name.getOrElse(default) + val available_name = namespace.name(candidate_name) + setRef(Ref(available_name)) + } + + private var _ref: Option[Arg] = None + private[chisel] def setRef(imm: Arg): Unit = _ref = Some(imm) + private[chisel] def setRef(parent: HasId, name: String): Unit = setRef(Slot(Node(parent), name)) + private[chisel] def setRef(parent: HasId, index: Int): Unit = setRef(Index(Node(parent), ILit(index))) + private[chisel] def setRef(parent: HasId, index: UInt): Unit = setRef(Index(Node(parent), index.ref)) + private[chisel] def getRef: Arg = _ref.get +} + +private[chisel] class DynamicContext { + val idGen = new IdGen + val globalNamespace = new Namespace(None, Set()) + val components = ArrayBuffer[Component]() + var currentModule: Option[Module] = None + val errors = new ErrorLog +} + +private[chisel] object Builder { + // All global mutable state must be referenced via dynamicContextVar!! + private val dynamicContextVar = new DynamicVariable[Option[DynamicContext]](None) + + def dynamicContext: DynamicContext = + dynamicContextVar.value getOrElse (new DynamicContext) + def idGen: IdGen = dynamicContext.idGen + def globalNamespace: Namespace = dynamicContext.globalNamespace + def components: ArrayBuffer[Component] = dynamicContext.components + + def pushCommand[T <: Command](c: T): T = { + dynamicContext.currentModule.foreach(_._commands += c) + c + } + def pushOp[T <: Data](cmd: DefPrim[T]): T = pushCommand(cmd).id + + def errors: ErrorLog = dynamicContext.errors + def error(m: => String): Unit = errors.error(m) + + def build[T <: Module](f: => T): Circuit = { + dynamicContextVar.withValue(Some(new DynamicContext)) { + errors.info("Elaborating design...") + val mod = f + mod.forceName(mod.name, globalNamespace) + errors.checkpoint() + errors.info("Done elaborating.") + + Circuit(components.last.name, components) + } + } +} diff --git a/chiselFrontend/src/main/scala/chisel/internal/Error.scala b/chiselFrontend/src/main/scala/chisel/internal/Error.scala new file mode 100644 index 00000000..256a6d7f --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel/internal/Error.scala @@ -0,0 +1,91 @@ +// See LICENSE for license details. + +package chisel.internal + +import scala.collection.mutable.ArrayBuffer + +import chisel._ + +class ChiselException(message: String, cause: Throwable) extends Exception(message, cause) + +private[chisel] object throwException { + def apply(s: String, t: Throwable = null): Nothing = + throw new ChiselException(s, t) +} + +/** Records and reports runtime errors and warnings. */ +private[chisel] class ErrorLog { + def hasErrors: Boolean = errors.exists(_.isFatal) + + /** Log an error message */ + def error(m: => String): Unit = + errors += new Error(m, getUserLineNumber) + + /** Log a warning message */ + def warning(m: => String): Unit = + errors += new Warning(m, getUserLineNumber) + + /** Emit an informational message */ + def info(m: String): Unit = + println(new Info("[%2.3f] %s".format(elapsedTime/1e3, m), None)) // scalastyle:ignore regex + + /** Prints error messages generated by Chisel at runtime. */ + def report(): Unit = errors foreach println // scalastyle:ignore regex + + /** Throw an exception if any errors have yet occurred. */ + def checkpoint(): Unit = if(hasErrors) { + import Console._ + throwException(errors.map(_ + "\n").reduce(_ + _) + + UNDERLINED + "CODE HAS " + errors.filter(_.isFatal).length + RESET + + UNDERLINED + " " + RED + "ERRORS" + RESET + + UNDERLINED + " and " + errors.filterNot(_.isFatal).length + RESET + + UNDERLINED + " " + YELLOW + "WARNINGS" + RESET) + } + + private def findFirstUserFrame(stack: Array[StackTraceElement]): Option[StackTraceElement] = { + def isUserCode(ste: StackTraceElement): Boolean = { + def isUserModule(c: Class[_]): Boolean = + c != null && (c == classOf[Module] || isUserModule(c.getSuperclass)) + isUserModule(Class.forName(ste.getClassName)) + } + + stack.indexWhere(isUserCode) match { + case x if x < 0 => None + case x => Some(stack(x)) + } + } + + private def getUserLineNumber = + findFirstUserFrame(Thread.currentThread().getStackTrace) + + private val errors = ArrayBuffer[LogEntry]() + + private val startTime = System.currentTimeMillis + private def elapsedTime: Long = System.currentTimeMillis - startTime +} + +private abstract class LogEntry(msg: => String, line: Option[StackTraceElement]) { + def isFatal: Boolean = false + def format: String + + override def toString: String = line match { + case Some(l) => s"${format} ${l.getFileName}:${l.getLineNumber}: ${msg} in class ${l.getClassName}" + case None => s"${format} ${msg}" + } + + protected def tag(name: String, color: String): String = + s"[${color}${name}${Console.RESET}]" +} + +private class Error(msg: => String, line: Option[StackTraceElement]) extends LogEntry(msg, line) { + override def isFatal: Boolean = true + def format: String = tag("error", Console.RED) +} + +private class Warning(msg: => String, line: Option[StackTraceElement]) extends LogEntry(msg, line) { + def format: String = tag("warn", Console.YELLOW) +} + +private class Info(msg: => String, line: Option[StackTraceElement]) extends LogEntry(msg, line) { + def format: String = tag("info", Console.MAGENTA) +} 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..c20bd130 --- /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/IR.scala b/chiselFrontend/src/main/scala/chisel/internal/firrtl/IR.scala new file mode 100644 index 00000000..9c1ce98e --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel/internal/firrtl/IR.scala @@ -0,0 +1,189 @@ +// See LICENSE for license details. + +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 +} + +object PrimOp { + val AddOp = PrimOp("add") + val SubOp = PrimOp("sub") + val TailOp = PrimOp("tail") + val HeadOp = PrimOp("head") + val TimesOp = PrimOp("mul") + val DivideOp = PrimOp("div") + val RemOp = PrimOp("rem") + val ShiftLeftOp = PrimOp("shl") + val ShiftRightOp = PrimOp("shr") + val DynamicShiftLeftOp = PrimOp("dshl") + val DynamicShiftRightOp = PrimOp("dshr") + val BitAndOp = PrimOp("and") + val BitOrOp = PrimOp("or") + val BitXorOp = PrimOp("xor") + val BitNotOp = PrimOp("not") + val ConcatOp = PrimOp("cat") + val BitsExtractOp = PrimOp("bits") + val LessOp = PrimOp("lt") + val LessEqOp = PrimOp("leq") + val GreaterOp = PrimOp("gt") + val GreaterEqOp = PrimOp("geq") + val EqualOp = PrimOp("eq") + val PadOp = PrimOp("pad") + val NotEqualOp = PrimOp("neq") + val NegOp = PrimOp("neg") + val MultiplexOp = PrimOp("mux") + val XorReduceOp = PrimOp("xorr") + val ConvertOp = PrimOp("cvt") + val AsUIntOp = PrimOp("asUInt") + val AsSIntOp = PrimOp("asSInt") +} + +abstract class Arg { + def fullName(ctx: Component): String = name + def name: String +} + +case class Node(id: HasId) extends Arg { + override def fullName(ctx: Component): String = id.getRef.fullName(ctx) + def name: String = id.getRef.name +} + +abstract class LitArg(val num: BigInt, widthArg: Width) extends Arg { + private[chisel] def forcedWidth = widthArg.known + private[chisel] def width: Width = if (forcedWidth) widthArg else Width(minWidth) + + protected def minWidth: Int + if (forcedWidth) { + require(widthArg.get >= minWidth, + s"The literal value ${num} was elaborated with a specificed width of ${widthArg.get} bits, but at least ${minWidth} bits are required.") + } +} + +case class ILit(n: BigInt) extends Arg { + def name: String = n.toString +} + +case class ULit(n: BigInt, w: Width) extends LitArg(n, w) { + def name: String = "UInt" + width + "(\"h0" + num.toString(16) + "\")" + def minWidth: Int = 1 max n.bitLength + + require(n >= 0, s"UInt literal ${n} is negative") +} + +case class SLit(n: BigInt, w: Width) extends LitArg(n, w) { + def name: String = { + val unsigned = if (n < 0) (BigInt(1) << width.get) + n else n + s"asSInt(${ULit(unsigned, width).name})" + } + def minWidth: Int = 1 + n.bitLength +} + +case class Ref(name: String) extends Arg +case class ModuleIO(mod: Module, name: String) extends Arg { + override def fullName(ctx: Component): String = + if (mod eq ctx.id) name else s"${mod.getRef.name}.$name" +} +case class Slot(imm: Node, name: String) extends Arg { + override def fullName(ctx: Component): String = + if (imm.fullName(ctx).isEmpty) name else s"${imm.fullName(ctx)}.${name}" +} +case class Index(imm: Arg, value: Arg) extends Arg { + def name: String = s"[$value]" + override def fullName(ctx: Component): String = s"${imm.fullName(ctx)}[${value.fullName(ctx)}]" +} + +object Width { + def apply(x: Int): Width = KnownWidth(x) + def apply(): Width = UnknownWidth() +} + +sealed abstract class Width { + type W = Int + def max(that: Width): Width = this.op(that, _ max _) + def + (that: Width): Width = this.op(that, _ + _) + def + (that: Int): Width = this.op(this, (a, b) => a + that) + def shiftRight(that: Int): Width = this.op(this, (a, b) => 0 max (a - that)) + def dynamicShiftLeft(that: Width): Width = + this.op(that, (a, b) => a + (1 << b) - 1) + + def known: Boolean + def get: W + protected def op(that: Width, f: (W, W) => W): Width +} + +sealed case class UnknownWidth() extends Width { + def known: Boolean = false + def get: Int = None.get + def op(that: Width, f: (W, W) => W): Width = this + override def toString: String = "" +} + +sealed case class KnownWidth(value: Int) extends Width { + require(value >= 0) + def known: Boolean = true + def get: Int = value + def op(that: Width, f: (W, W) => W): Width = that match { + case KnownWidth(x) => KnownWidth(f(value, x)) + case _ => that + } + override def toString: String = s"<${value.toString}>" +} + +sealed abstract class MemPortDirection(name: String) { + override def toString: String = name +} +object MemPortDirection { + object READ extends MemPortDirection("read") + object WRITE extends MemPortDirection("write") + object RDWR extends MemPortDirection("rdwr") + object INFER extends MemPortDirection("infer") +} + +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](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(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) = { + require(x.toInt >= 0) + if (x == '"' || x == '\\') { + s"\\${x}" + } else if (x == '\n') { + "\\n" + } else { + require(x.toInt >= 32) // TODO \xNN once FIRRTL issue #59 is resolved + x + } + } + formatIn.map(escaped _).mkString + } +} + +case class Circuit(name: String, components: Seq[Component]) diff --git a/coreMacros/src/main/scala/Chisel/internal/sourceinfo/SourceInfoTransform.scala b/coreMacros/src/main/scala/Chisel/internal/sourceinfo/SourceInfoTransform.scala deleted file mode 100644 index 82ad5b9e..00000000 --- a/coreMacros/src/main/scala/Chisel/internal/sourceinfo/SourceInfoTransform.scala +++ /dev/null @@ -1,156 +0,0 @@ -// See LICENSE for license details. - -// This file transform macro definitions to explicitly add implicit source info to Chisel method -// calls. - -package Chisel.internal.sourceinfo - -import scala.language.experimental.macros -import scala.reflect.macros.blackbox.Context -import scala.reflect.macros.whitebox - - -/** Transforms a function call so that it can both provide implicit-style source information and - * have a chained apply call. Without macros, only one is possible, since having a implicit - * argument in the definition will cause the compiler to interpret a chained apply as an - * explicit implicit argument and give type errors. - * - * Instead of an implicit argument, the public-facing function no longer takes a SourceInfo at all. - * The macro transforms the public-facing function into a call to an internal function that takes - * an explicit SourceInfo by inserting an implicitly[SourceInfo] as the explicit argument. - */ -trait SourceInfoTransformMacro { - val c: Context - import c.universe._ - def thisObj = c.prefix.tree - def implicitSourceInfo = q"implicitly[_root_.Chisel.internal.sourceinfo.SourceInfo]" -} - -class WireTransform(val c: Context) extends SourceInfoTransformMacro { - import c.universe._ - def apply[T: c.WeakTypeTag](t: c.Tree): c.Tree = { - val tpe = weakTypeOf[T] - q"$thisObj.do_apply($t, null.asInstanceOf[$tpe])($implicitSourceInfo)" - } -} - -class UIntTransform(val c: Context) extends SourceInfoTransformMacro { - import c.universe._ - def bitset(off: c.Tree, dat: c.Tree): c.Tree = { - q"$thisObj.do_bitSet($off, $dat)($implicitSourceInfo)" - } -} - -// Module instantiation transform -class InstTransform(val c: Context) extends SourceInfoTransformMacro { - import c.universe._ - def apply[T: c.WeakTypeTag](bc: c.Tree): c.Tree = { - q"$thisObj.do_apply($bc)($implicitSourceInfo)" - } -} - -class MemTransform(val c: Context) extends SourceInfoTransformMacro { - import c.universe._ - def apply[T: c.WeakTypeTag](size: c.Tree, t: c.Tree): c.Tree = { - q"$thisObj.do_apply($size, $t)($implicitSourceInfo)" - } -} - -class RegTransform(val c: Context) extends SourceInfoTransformMacro { - import c.universe._ - def apply[T: c.WeakTypeTag](t: c.Tree): c.Tree = { - val tpe = weakTypeOf[T] - q"$thisObj.do_apply($t, null.asInstanceOf[$tpe], null.asInstanceOf[$tpe])($implicitSourceInfo)" - } -} - -class MuxTransform(val c: Context) extends SourceInfoTransformMacro { - import c.universe._ - def apply[T: c.WeakTypeTag](cond: c.Tree, con: c.Tree, alt: c.Tree): c.Tree = { - val tpe = weakTypeOf[T] - q"$thisObj.do_apply[$tpe]($cond, $con, $alt)($implicitSourceInfo)" - } -} - -class VecTransform(val c: Context) extends SourceInfoTransformMacro { - import c.universe._ - def apply_elts(elts: c.Tree): c.Tree = { - q"$thisObj.do_apply($elts)($implicitSourceInfo)" - } - def apply_elt0(elt0: c.Tree, elts: c.Tree*): c.Tree = { - q"$thisObj.do_apply($elt0, ..$elts)($implicitSourceInfo)" - } - def tabulate(n: c.Tree)(gen: c.Tree): c.Tree = { - q"$thisObj.do_tabulate($n)($gen)($implicitSourceInfo)" - } - def fill(n: c.Tree)(gen: c.Tree): c.Tree = { - q"$thisObj.do_fill($n)($gen)($implicitSourceInfo)" - } - def contains(x: c.Tree)(ev: c.Tree): c.Tree = { - q"$thisObj.do_contains($x)($implicitSourceInfo, $ev)" - } -} - -/** "Automatic" source information transform / insertion macros, which generate the function name - * based on the macro invocation (instead of explicitly writing out every transform). - */ -abstract class AutoSourceTransform extends SourceInfoTransformMacro { - import c.universe._ - /** Returns the TermName of the transformed function, which is the applied function name with do_ - * prepended. - */ - def doFuncTerm = { - val funcName = c.macroApplication match { - case q"$_.$funcName[..$_](...$_)" => funcName - case _ => throw new Exception(s"Chisel Internal Error: Could not resolve function name from macro application: ${showCode(c.macroApplication)}") - } - TermName("do_" + funcName) - } -} - -class SourceInfoTransform(val c: Context) extends AutoSourceTransform { - import c.universe._ - - def noArg(): c.Tree = { - q"$thisObj.$doFuncTerm($implicitSourceInfo)" - } - - def thatArg(that: c.Tree): c.Tree = { - q"$thisObj.$doFuncTerm($that)($implicitSourceInfo)" - } - - def nArg(n: c.Tree): c.Tree = { - q"$thisObj.$doFuncTerm($n)($implicitSourceInfo)" - } - - def pArg(p: c.Tree): c.Tree = { - q"$thisObj.$doFuncTerm($p)($implicitSourceInfo)" - } - - def inArg(in: c.Tree): c.Tree = { - q"$thisObj.$doFuncTerm($in)($implicitSourceInfo)" - } - - def xArg(x: c.Tree): c.Tree = { - q"$thisObj.$doFuncTerm($x)($implicitSourceInfo)" - } - - def xyArg(x: c.Tree, y: c.Tree): c.Tree = { - q"$thisObj.$doFuncTerm($x, $y)($implicitSourceInfo)" - } -} - -/** Special whitebox version of the blackbox SourceInfoTransform, used when fun things need to happen to satisfy the - * type system while preventing the use of macro overrides. - */ -class SourceInfoWhiteboxTransform(val c: whitebox.Context) extends AutoSourceTransform { - import c.universe._ - - def noArg(): c.Tree = { - q"$thisObj.$doFuncTerm($implicitSourceInfo)" - } - - def thatArg(that: c.Tree): c.Tree = { - q"$thisObj.$doFuncTerm($that)($implicitSourceInfo)" - } -} diff --git a/coreMacros/src/main/scala/chisel/internal/sourceinfo/SourceInfoTransform.scala b/coreMacros/src/main/scala/chisel/internal/sourceinfo/SourceInfoTransform.scala new file mode 100644 index 00000000..10b677b6 --- /dev/null +++ b/coreMacros/src/main/scala/chisel/internal/sourceinfo/SourceInfoTransform.scala @@ -0,0 +1,156 @@ +// See LICENSE for license details. + +// This file transform macro definitions to explicitly add implicit source info to Chisel method +// calls. + +package chisel.internal.sourceinfo + +import scala.language.experimental.macros +import scala.reflect.macros.blackbox.Context +import scala.reflect.macros.whitebox + + +/** Transforms a function call so that it can both provide implicit-style source information and + * have a chained apply call. Without macros, only one is possible, since having a implicit + * argument in the definition will cause the compiler to interpret a chained apply as an + * explicit implicit argument and give type errors. + * + * Instead of an implicit argument, the public-facing function no longer takes a SourceInfo at all. + * The macro transforms the public-facing function into a call to an internal function that takes + * an explicit SourceInfo by inserting an implicitly[SourceInfo] as the explicit argument. + */ +trait SourceInfoTransformMacro { + val c: Context + import c.universe._ + def thisObj = c.prefix.tree + def implicitSourceInfo = q"implicitly[_root_.chisel.internal.sourceinfo.SourceInfo]" +} + +class WireTransform(val c: Context) extends SourceInfoTransformMacro { + import c.universe._ + def apply[T: c.WeakTypeTag](t: c.Tree): c.Tree = { + val tpe = weakTypeOf[T] + q"$thisObj.do_apply($t, null.asInstanceOf[$tpe])($implicitSourceInfo)" + } +} + +class UIntTransform(val c: Context) extends SourceInfoTransformMacro { + import c.universe._ + def bitset(off: c.Tree, dat: c.Tree): c.Tree = { + q"$thisObj.do_bitSet($off, $dat)($implicitSourceInfo)" + } +} + +// Module instantiation transform +class InstTransform(val c: Context) extends SourceInfoTransformMacro { + import c.universe._ + def apply[T: c.WeakTypeTag](bc: c.Tree): c.Tree = { + q"$thisObj.do_apply($bc)($implicitSourceInfo)" + } +} + +class MemTransform(val c: Context) extends SourceInfoTransformMacro { + import c.universe._ + def apply[T: c.WeakTypeTag](size: c.Tree, t: c.Tree): c.Tree = { + q"$thisObj.do_apply($size, $t)($implicitSourceInfo)" + } +} + +class RegTransform(val c: Context) extends SourceInfoTransformMacro { + import c.universe._ + def apply[T: c.WeakTypeTag](t: c.Tree): c.Tree = { + val tpe = weakTypeOf[T] + q"$thisObj.do_apply($t, null.asInstanceOf[$tpe], null.asInstanceOf[$tpe])($implicitSourceInfo)" + } +} + +class MuxTransform(val c: Context) extends SourceInfoTransformMacro { + import c.universe._ + def apply[T: c.WeakTypeTag](cond: c.Tree, con: c.Tree, alt: c.Tree): c.Tree = { + val tpe = weakTypeOf[T] + q"$thisObj.do_apply[$tpe]($cond, $con, $alt)($implicitSourceInfo)" + } +} + +class VecTransform(val c: Context) extends SourceInfoTransformMacro { + import c.universe._ + def apply_elts(elts: c.Tree): c.Tree = { + q"$thisObj.do_apply($elts)($implicitSourceInfo)" + } + def apply_elt0(elt0: c.Tree, elts: c.Tree*): c.Tree = { + q"$thisObj.do_apply($elt0, ..$elts)($implicitSourceInfo)" + } + def tabulate(n: c.Tree)(gen: c.Tree): c.Tree = { + q"$thisObj.do_tabulate($n)($gen)($implicitSourceInfo)" + } + def fill(n: c.Tree)(gen: c.Tree): c.Tree = { + q"$thisObj.do_fill($n)($gen)($implicitSourceInfo)" + } + def contains(x: c.Tree)(ev: c.Tree): c.Tree = { + q"$thisObj.do_contains($x)($implicitSourceInfo, $ev)" + } +} + +/** "Automatic" source information transform / insertion macros, which generate the function name + * based on the macro invocation (instead of explicitly writing out every transform). + */ +abstract class AutoSourceTransform extends SourceInfoTransformMacro { + import c.universe._ + /** Returns the TermName of the transformed function, which is the applied function name with do_ + * prepended. + */ + def doFuncTerm = { + val funcName = c.macroApplication match { + case q"$_.$funcName[..$_](...$_)" => funcName + case _ => throw new Exception(s"Chisel Internal Error: Could not resolve function name from macro application: ${showCode(c.macroApplication)}") + } + TermName("do_" + funcName) + } +} + +class SourceInfoTransform(val c: Context) extends AutoSourceTransform { + import c.universe._ + + def noArg(): c.Tree = { + q"$thisObj.$doFuncTerm($implicitSourceInfo)" + } + + def thatArg(that: c.Tree): c.Tree = { + q"$thisObj.$doFuncTerm($that)($implicitSourceInfo)" + } + + def nArg(n: c.Tree): c.Tree = { + q"$thisObj.$doFuncTerm($n)($implicitSourceInfo)" + } + + def pArg(p: c.Tree): c.Tree = { + q"$thisObj.$doFuncTerm($p)($implicitSourceInfo)" + } + + def inArg(in: c.Tree): c.Tree = { + q"$thisObj.$doFuncTerm($in)($implicitSourceInfo)" + } + + def xArg(x: c.Tree): c.Tree = { + q"$thisObj.$doFuncTerm($x)($implicitSourceInfo)" + } + + def xyArg(x: c.Tree, y: c.Tree): c.Tree = { + q"$thisObj.$doFuncTerm($x, $y)($implicitSourceInfo)" + } +} + +/** Special whitebox version of the blackbox SourceInfoTransform, used when fun things need to happen to satisfy the + * type system while preventing the use of macro overrides. + */ +class SourceInfoWhiteboxTransform(val c: whitebox.Context) extends AutoSourceTransform { + import c.universe._ + + def noArg(): c.Tree = { + q"$thisObj.$doFuncTerm($implicitSourceInfo)" + } + + def thatArg(that: c.Tree): c.Tree = { + q"$thisObj.$doFuncTerm($that)($implicitSourceInfo)" + } +} diff --git a/src/main/scala/Chisel/BitPat.scala b/src/main/scala/Chisel/BitPat.scala index 96206f63..a6833ed2 100644 --- a/src/main/scala/Chisel/BitPat.scala +++ b/src/main/scala/Chisel/BitPat.scala @@ -1,10 +1,10 @@ // See LICENSE for license details. -package Chisel +package chisel import scala.language.experimental.macros -import Chisel.internal.sourceinfo.{SourceInfo, SourceInfoTransform} +import chisel.internal.sourceinfo.{SourceInfo, SourceInfoTransform} object BitPat { /** Parses a bit pattern string into (bits, mask, width). diff --git a/src/main/scala/Chisel/Driver.scala b/src/main/scala/Chisel/Driver.scala deleted file mode 100644 index 02204684..00000000 --- a/src/main/scala/Chisel/Driver.scala +++ /dev/null @@ -1,132 +0,0 @@ -// See LICENSE for license details. - -package Chisel - -import scala.sys.process._ -import java.io._ - -import internal._ -import internal.firrtl._ - -trait BackendCompilationUtilities { - /** Create a temporary directory with the prefix name. Exists here because it doesn't in Java 6. - */ - def createTempDirectory(prefix: String): File = { - val temp = File.createTempFile(prefix, "") - if (!temp.delete()) { - throw new IOException(s"Unable to delete temp file '$temp'") - } - if (!temp.mkdir()) { - throw new IOException(s"Unable to create temp directory '$temp'") - } - temp - } - - def makeHarness(template: String => String, post: String)(f: File): File = { - val prefix = f.toString.split("/").last - val vf = new File(f.toString + post) - val w = new FileWriter(vf) - w.write(template(prefix)) - w.close() - vf - } - - def firrtlToVerilog(prefix: String, dir: File): ProcessBuilder = { - Process( - Seq("firrtl", - "-i", s"$prefix.fir", - "-o", s"$prefix.v", - "-X", "verilog"), - dir) - } - - /** Generates a Verilator invocation to convert Verilog sources to C++ - * simulation sources. - * - * The Verilator prefix will be V$dutFile, and running this will generate - * C++ sources and headers as well as a makefile to compile them. - * - * @param dutFile name of the DUT .v without the .v extension - * @param name of the top-level module in the design - * @param dir output directory - * @param vSources list of additional Verilog sources to compile - * @param cppHarness C++ testharness to compile/link against - */ - def verilogToCpp( - dutFile: String, - topModule: String, - dir: File, - vSources: Seq[File], - cppHarness: File - ): ProcessBuilder = { - val command = Seq("verilator", - "--cc", s"$dutFile.v") ++ - vSources.map(file => Seq("-v", file.toString)).flatten ++ - Seq("--assert", - "-Wno-fatal", - "-Wno-WIDTH", - "-Wno-STMTDLY", - "--trace", - "-O2", - "--top-module", topModule, - "+define+TOP_TYPE=V" + dutFile, - s"+define+PRINTF_COND=!$topModule.reset", - "-CFLAGS", - s"""-Wno-undefined-bool-conversion -O2 -DTOP_TYPE=V$dutFile -include V$dutFile.h""", - "-Mdir", dir.toString, - "--exe", cppHarness.toString) - System.out.println(s"${command.mkString(" ")}") // scalastyle:ignore regex - command - } - - def cppToExe(prefix: String, dir: File): ProcessBuilder = - Seq("make", "-C", dir.toString, "-j", "-f", s"V${prefix}.mk", s"V${prefix}") - - def executeExpectingFailure( - prefix: String, - dir: File, - assertionMsg: String = "Assertion failed"): Boolean = { - var triggered = false - val e = Process(s"./V${prefix}", dir) ! - ProcessLogger(line => { - triggered = triggered || line.contains(assertionMsg) - System.out.println(line) // scalastyle:ignore regex - }) - triggered - } - - def executeExpectingSuccess(prefix: String, dir: File): Boolean = { - !executeExpectingFailure(prefix, dir) - } -} - -object Driver extends BackendCompilationUtilities { - - /** Elaborates the Module specified in the gen function into a Circuit - * - * @param gen a function that creates a Module hierarchy - * @return the resulting Chisel IR in the form of a Circuit (TODO: Should be FIRRTL IR) - */ - def elaborate[T <: Module](gen: () => T): Circuit = Builder.build(Module(gen())) - - def emit[T <: Module](gen: () => T): String = Emitter.emit(elaborate(gen)) - - def dumpFirrtl(ir: Circuit, optName: Option[File]): File = { - val f = optName.getOrElse(new File(ir.name + ".fir")) - val w = new FileWriter(f) - w.write(Emitter.emit(ir)) - w.close() - f - } - - private var target_dir: Option[String] = None - def parseArgs(args: Array[String]): Unit = { - for (i <- 0 until args.size) { - if (args(i) == "--targetDir") { - target_dir = Some(args(i + 1)) - } - } - } - - def targetDir(): String = { target_dir getOrElse new File(".").getCanonicalPath } -} diff --git a/src/main/scala/Chisel/FileSystemUtilities.scala b/src/main/scala/Chisel/FileSystemUtilities.scala deleted file mode 100644 index 575ae138..00000000 --- a/src/main/scala/Chisel/FileSystemUtilities.scala +++ /dev/null @@ -1,10 +0,0 @@ -// See LICENSE for license details. - -package Chisel - -@deprecated("FileSystemUtilities doesn't exist in chisel3", "3.0.0") -trait FileSystemUtilities { - def createOutputFile(name: String): java.io.FileWriter = { - new java.io.FileWriter(Driver.targetDir + "/" + name) - } -} diff --git a/src/main/scala/Chisel/ImplicitConversions.scala b/src/main/scala/Chisel/ImplicitConversions.scala deleted file mode 100644 index 6a230022..00000000 --- a/src/main/scala/Chisel/ImplicitConversions.scala +++ /dev/null @@ -1,8 +0,0 @@ -// See LICENSE for license details. - -package Chisel - -object ImplicitConversions { - implicit def intToUInt(x: Int): UInt = UInt(x) - implicit def booleanToBool(x: Boolean): Bool = Bool(x) -} diff --git a/src/main/scala/Chisel/Main.scala b/src/main/scala/Chisel/Main.scala deleted file mode 100644 index a72debc3..00000000 --- a/src/main/scala/Chisel/Main.scala +++ /dev/null @@ -1,17 +0,0 @@ -// See LICENSE for license details. - -package Chisel - -import java.io.File - -@deprecated("chiselMain doesn't exist in Chisel3", "3.0") object chiselMain { - def apply[T <: Module](args: Array[String], gen: () => T): Unit = - Predef.assert(false, "No more chiselMain in Chisel3") - - def run[T <: Module] (args: Array[String], gen: () => T): Unit = { - val circuit = Driver.elaborate(gen) - Driver.parseArgs(args) - val output_file = new File(Driver.targetDir + "/" + circuit.name + ".fir") - Driver.dumpFirrtl(circuit, Option(output_file)) - } -} diff --git a/src/main/scala/Chisel/internal/firrtl/Emitter.scala b/src/main/scala/Chisel/internal/firrtl/Emitter.scala deleted file mode 100644 index 7ca3268a..00000000 --- a/src/main/scala/Chisel/internal/firrtl/Emitter.scala +++ /dev/null @@ -1,112 +0,0 @@ -// See LICENSE for license details. - -package Chisel.internal.firrtl -import Chisel._ -import Chisel.internal.sourceinfo.{NoSourceInfo, SourceLine} - -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 = { - val firrtlLine = 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() - s"skip" - } - e.sourceInfo match { - case SourceLine(filename, line, col) => s"${firrtlLine} @[${filename} ${line}:${col}] " - case _: NoSourceInfo => firrtlLine - } - } - - // 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/src/main/scala/Chisel/package.scala b/src/main/scala/Chisel/package.scala deleted file mode 100644 index f05e8b5d..00000000 --- a/src/main/scala/Chisel/package.scala +++ /dev/null @@ -1,31 +0,0 @@ -package object Chisel { - import scala.language.experimental.macros - - import internal.firrtl.Width - import internal.sourceinfo.{SourceInfo, SourceInfoTransform} - - implicit class fromBigIntToLiteral(val x: BigInt) extends AnyVal { - def U: UInt = UInt(x, Width()) - def S: SInt = SInt(x, Width()) - } - implicit class fromIntToLiteral(val x: Int) extends AnyVal { - def U: UInt = UInt(BigInt(x), Width()) - def S: SInt = SInt(BigInt(x), Width()) - } - implicit class fromStringToLiteral(val x: String) extends AnyVal { - def U: UInt = UInt(x) - } - implicit class fromBooleanToLiteral(val x: Boolean) extends AnyVal { - def B: Bool = Bool(x) - } - - implicit class fromUIntToBitPatComparable(val x: UInt) extends AnyVal { - 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 === x - def do_!= (that: BitPat)(implicit sourceInfo: SourceInfo): Bool = that != x - def do_=/= (that: BitPat)(implicit sourceInfo: SourceInfo): Bool = that =/= x - } -} diff --git a/src/main/scala/Chisel/testers/BasicTester.scala b/src/main/scala/Chisel/testers/BasicTester.scala deleted file mode 100644 index b8c1494a..00000000 --- a/src/main/scala/Chisel/testers/BasicTester.scala +++ /dev/null @@ -1,38 +0,0 @@ -// See LICENSE for license details. - -package Chisel.testers -import Chisel._ - -import scala.language.experimental.macros - -import internal._ -import internal.Builder.pushCommand -import internal.firrtl._ -import internal.sourceinfo.SourceInfo - -class BasicTester extends Module { - // The testbench has no IOs, rather it should communicate using printf, assert, and stop. - val io = new Bundle() - - def popCount(n: Long): Int = n.toBinaryString.count(_=='1') - - /** Ends the test reporting success. - * - * 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. - */ - def stop()(implicit sourceInfo: SourceInfo) { - // TODO: rewrite this using library-style SourceInfo passing. - when (!reset) { - pushCommand(Stop(sourceInfo, Node(clock), 0)) - } - } - - /** The finish method provides a hook that subclasses of BasicTester can use to - * alter a circuit after their constructor has been called. - * For example, a specialized tester subclassing BasicTester could override finish in order to - * add flow control logic for a decoupled io port of a device under test - */ - def finish(): Unit = {} -} diff --git a/src/main/scala/Chisel/testers/TesterDriver.scala b/src/main/scala/Chisel/testers/TesterDriver.scala deleted file mode 100644 index a56bb8b7..00000000 --- a/src/main/scala/Chisel/testers/TesterDriver.scala +++ /dev/null @@ -1,68 +0,0 @@ -// See LICENSE for license details. - -package Chisel.testers -import Chisel._ -import scala.io.Source -import scala.sys.process._ -import java.io._ - -object TesterDriver extends BackendCompilationUtilities { - /** Copy the contents of a resource to a destination file. - */ - def copyResourceToFile(name: String, file: File) { - val in = getClass().getResourceAsStream(name) - if (in == null) { - throw new FileNotFoundException(s"Resource '$name'") - } - val out = new FileOutputStream(file) - Iterator.continually(in.read).takeWhile(-1 !=).foreach(out.write) - out.close() - } - - /** For use with modules that should successfully be elaborated by the - * frontend, and which can be turned into executables with assertions. */ - def execute(t: () => BasicTester, additionalVResources: Seq[String] = Seq()): Boolean = { - // Invoke the chisel compiler to get the circuit's IR - val circuit = Driver.elaborate(finishWrapper(t)) - - // Set up a bunch of file handlers based on a random temp filename, - // plus the quirks of Verilator's naming conventions - val target = circuit.name - - val path = createTempDirectory(target) - val fname = new File(path, target) - - // For now, dump the IR out to a file - Driver.dumpFirrtl(circuit, Some(new File(fname.toString + ".fir"))) - - // Copy CPP harness and other Verilog sources from resources into files - val cppHarness = new File(path, "top.cpp") - copyResourceToFile("/top.cpp", cppHarness) - val additionalVFiles = additionalVResources.map((name: String) => { - val mangledResourceName = name.replace("/", "_") - val out = new File(path, mangledResourceName) - copyResourceToFile(name, out) - out - }) - - // Use sys.Process to invoke a bunch of backend stuff, then run the resulting exe - if ((firrtlToVerilog(target, path) #&& - verilogToCpp(target, target, path, additionalVFiles, cppHarness) #&& - cppToExe(target, path)).! == 0) { - executeExpectingSuccess(target, path) - } else { - false - } - } - /** - * Calls the finish method of an BasicTester or a class that extends it. - * The finish method is a hook for code that augments the circuit built in the constructor. - */ - def finishWrapper(test: () => BasicTester): () => BasicTester = { - () => { - val tester = test() - tester.finish() - tester - } - } -} diff --git a/src/main/scala/Chisel/throwException.scala b/src/main/scala/Chisel/throwException.scala deleted file mode 100644 index 702884aa..00000000 --- a/src/main/scala/Chisel/throwException.scala +++ /dev/null @@ -1,12 +0,0 @@ -// See LICENSE for license details. - -package Chisel - -@deprecated("throwException doesn't exist in Chisel3", "3.0.0") -@throws(classOf[Exception]) -object throwException { - def apply(s: String, t: Throwable = null) = { - val xcpt = new Exception(s, t) - throw xcpt - } -} diff --git a/src/main/scala/Chisel/util/Arbiter.scala b/src/main/scala/Chisel/util/Arbiter.scala deleted file mode 100644 index 16ae9be5..00000000 --- a/src/main/scala/Chisel/util/Arbiter.scala +++ /dev/null @@ -1,117 +0,0 @@ -// See LICENSE for license details. - -/** Arbiters in all shapes and sizes. - */ - -package Chisel - -/** An I/O bundle for the Arbiter */ -class ArbiterIO[T <: Data](gen: T, n: Int) extends Bundle { - val in = Vec(n, Decoupled(gen)).flip - val out = Decoupled(gen) - val chosen = UInt(OUTPUT, log2Up(n)) -} - -/** Arbiter Control determining which producer has access */ -private object ArbiterCtrl -{ - def apply(request: Seq[Bool]): Seq[Bool] = request.length match { - case 0 => Seq() - case 1 => Seq(Bool(true)) - case _ => Bool(true) +: request.tail.init.scanLeft(request.head)(_ || _).map(!_) - } -} - -abstract class LockingArbiterLike[T <: Data](gen: T, n: Int, count: Int, needsLock: Option[T => Bool]) extends Module { - def grant: Seq[Bool] - def choice: UInt - val io = new ArbiterIO(gen, n) - - io.chosen := choice - io.out.valid := io.in(io.chosen).valid - io.out.bits := io.in(io.chosen).bits - - if (count > 1) { - val lockCount = Counter(count) - val lockIdx = Reg(UInt()) - val locked = lockCount.value =/= UInt(0) - val wantsLock = needsLock.map(_(io.out.bits)).getOrElse(Bool(true)) - - when (io.out.fire() && wantsLock) { - lockIdx := io.chosen - lockCount.inc() - } - - when (locked) { io.chosen := lockIdx } - for ((in, (g, i)) <- io.in zip grant.zipWithIndex) - in.ready := Mux(locked, lockIdx === UInt(i), g) && io.out.ready - } else { - for ((in, g) <- io.in zip grant) - in.ready := g && io.out.ready - } -} - -class LockingRRArbiter[T <: Data](gen: T, n: Int, count: Int, needsLock: Option[T => Bool] = None) - extends LockingArbiterLike[T](gen, n, count, needsLock) { - lazy val lastGrant = RegEnable(io.chosen, io.out.fire()) - lazy val grantMask = (0 until n).map(UInt(_) > lastGrant) - lazy val validMask = io.in zip grantMask map { case (in, g) => in.valid && g } - - override def grant: Seq[Bool] = { - val ctrl = ArbiterCtrl((0 until n).map(i => validMask(i)) ++ io.in.map(_.valid)) - (0 until n).map(i => ctrl(i) && grantMask(i) || ctrl(i + n)) - } - - override lazy val choice = Wire(init=UInt(n-1)) - for (i <- n-2 to 0 by -1) - when (io.in(i).valid) { choice := UInt(i) } - for (i <- n-1 to 1 by -1) - when (validMask(i)) { choice := UInt(i) } -} - -class LockingArbiter[T <: Data](gen: T, n: Int, count: Int, needsLock: Option[T => Bool] = None) - extends LockingArbiterLike[T](gen, n, count, needsLock) { - def grant: Seq[Bool] = ArbiterCtrl(io.in.map(_.valid)) - - override lazy val choice = Wire(init=UInt(n-1)) - for (i <- n-2 to 0 by -1) - when (io.in(i).valid) { choice := UInt(i) } -} - -/** Hardware module that is used to sequence n producers into 1 consumer. - Producers are chosen in round robin order. - - Example usage: - val arb = new RRArbiter(2, UInt()) - arb.io.in(0) <> producer0.io.out - arb.io.in(1) <> producer1.io.out - consumer.io.in <> arb.io.out - */ -class RRArbiter[T <: Data](gen:T, n: Int) extends LockingRRArbiter[T](gen, n, 1) - -/** Hardware module that is used to sequence n producers into 1 consumer. - Priority is given to lower producer - - Example usage: - val arb = Module(new Arbiter(2, UInt())) - arb.io.in(0) <> producer0.io.out - arb.io.in(1) <> producer1.io.out - consumer.io.in <> arb.io.out - */ -class Arbiter[T <: Data](gen: T, n: Int) extends Module { - val io = new ArbiterIO(gen, n) - - io.chosen := UInt(n-1) - io.out.bits := io.in(n-1).bits - for (i <- n-2 to 0 by -1) { - when (io.in(i).valid) { - io.chosen := UInt(i) - io.out.bits := io.in(i).bits - } - } - - val grant = ArbiterCtrl(io.in.map(_.valid)) - for ((in, g) <- io.in zip grant) - in.ready := g && io.out.ready - io.out.valid := !grant.last || io.in.last.valid -} diff --git a/src/main/scala/Chisel/util/Bitwise.scala b/src/main/scala/Chisel/util/Bitwise.scala deleted file mode 100644 index 239a295e..00000000 --- a/src/main/scala/Chisel/util/Bitwise.scala +++ /dev/null @@ -1,71 +0,0 @@ -// See LICENSE for license details. - -/** Miscellaneous circuit generators operating on bits. - */ - -package Chisel - -object FillInterleaved -{ - def apply(n: Int, in: UInt): UInt = apply(n, in.toBools) - def apply(n: Int, in: Seq[Bool]): UInt = Vec(in.map(Fill(n, _))).toBits -} - -/** Returns the number of bits set (i.e value is 1) in the input signal. - */ -object PopCount -{ - def apply(in: Iterable[Bool]): UInt = SeqUtils.count(in.toSeq) - def apply(in: Bits): UInt = apply((0 until in.getWidth).map(in(_))) -} - -/** Fill fans out a UInt to multiple copies */ -object Fill { - /** Fan out x n times */ - def apply(n: Int, x: UInt): UInt = { - n match { - case 0 => UInt(width=0) - case 1 => x - case y if n > 1 => - val p2 = Array.ofDim[UInt](log2Up(n + 1)) - p2(0) = x - for (i <- 1 until p2.length) - p2(i) = Cat(p2(i-1), p2(i-1)) - Cat((0 until log2Up(y + 1)).filter(i => (y & (1 << i)) != 0).map(p2(_))) - case _ => throw new IllegalArgumentException(s"n (=$n) must be nonnegative integer.") - } - } - /** Fan out x n times */ - def apply(n: Int, x: Bool): UInt = - if (n > 1) { - UInt(0,n) - x - } else { - apply(n, x: UInt) - } -} - -/** Litte/big bit endian convertion: reverse the order of the bits in a UInt. -*/ -object Reverse -{ - private def doit(in: UInt, length: Int): UInt = { - if (length == 1) { - in - } else if (isPow2(length) && length >= 8 && length <= 64) { - // This esoterica improves simulation performance - var res = in - var shift = length >> 1 - var mask = UInt((BigInt(1) << length) - 1, length) - do { - mask = mask ^ (mask(length-shift-1,0) << shift) - res = ((res >> shift) & mask) | ((res(length-shift-1,0) << shift) & ~mask) - shift = shift >> 1 - } while (shift > 0) - res - } else { - val half = (1 << log2Up(length))/2 - Cat(doit(in(half-1,0), half), doit(in(length-1,half), length-half)) - } - } - def apply(in: UInt): UInt = doit(in, in.getWidth) -} diff --git a/src/main/scala/Chisel/util/Cat.scala b/src/main/scala/Chisel/util/Cat.scala deleted file mode 100644 index dd706e62..00000000 --- a/src/main/scala/Chisel/util/Cat.scala +++ /dev/null @@ -1,18 +0,0 @@ -// See LICENSE for license details. - -package Chisel - -object Cat { - /** Combine data elements together - * @param a Data to combine with - * @param r any number of other Data elements to be combined in order - * @return A UInt which is all of the bits combined together - */ - def apply[T <: Bits](a: T, r: T*): UInt = apply(a :: r.toList) - - /** Combine data elements together - * @param r any number of other Data elements to be combined in order - * @return A UInt which is all of the bits combined together - */ - def apply[T <: Bits](r: Seq[T]): UInt = SeqUtils.asUInt(r.reverse) -} diff --git a/src/main/scala/Chisel/util/CircuitMath.scala b/src/main/scala/Chisel/util/CircuitMath.scala deleted file mode 100644 index 06cab903..00000000 --- a/src/main/scala/Chisel/util/CircuitMath.scala +++ /dev/null @@ -1,26 +0,0 @@ -// See LICENSE for license details. - -/** Circuit-land math operations. - */ - -package Chisel - -/** Compute Log2 with truncation of a UInt in hardware using a Mux Tree - * An alternative interpretation is it computes the minimum number of bits needed to represent x - * @example - * {{{ data_out := Log2(data_in) }}} - * @note Truncation is used so Log2(UInt(12412)) = 13*/ -object Log2 { - /** Compute the Log2 on the least significant n bits of x */ - def apply(x: Bits, width: Int): UInt = { - if (width < 2) { - UInt(0) - } else if (width == 2) { - x(1) - } else { - Mux(x(width-1), UInt(width-1), apply(x, width-1)) - } - } - - def apply(x: Bits): UInt = apply(x, x.getWidth) -} diff --git a/src/main/scala/Chisel/util/Conditional.scala b/src/main/scala/Chisel/util/Conditional.scala deleted file mode 100644 index 9cab25ef..00000000 --- a/src/main/scala/Chisel/util/Conditional.scala +++ /dev/null @@ -1,69 +0,0 @@ -// See LICENSE for license details. - -/** Conditional blocks. - */ - -package Chisel - -import scala.language.reflectiveCalls -import scala.language.experimental.macros -import scala.reflect.runtime.universe._ -import scala.reflect.macros.blackbox._ - -/** This is identical to [[Chisel.when when]] with the condition inverted */ -object unless { // scalastyle:ignore object.name - def apply(c: Bool)(block: => Unit) { - when (!c) { block } - } -} - -class SwitchContext[T <: Bits](cond: T) { - def is(v: Iterable[T])(block: => Unit) { - if (!v.isEmpty) when (v.map(_.asUInt === cond.asUInt).reduce(_||_)) { block } - } - def is(v: T)(block: => Unit) { is(Seq(v))(block) } - def is(v: T, vr: T*)(block: => Unit) { is(v :: vr.toList)(block) } -} - -/** An object for separate cases in [[Chisel.switch switch]] - * It is equivalent to a [[Chisel.when$ when]] block comparing to the condition - * Use outside of a switch statement is illegal */ -object is { // scalastyle:ignore object.name - // Begin deprecation of non-type-parameterized is statements. - def apply(v: Iterable[Bits])(block: => Unit) { - require(false, "The 'is' keyword may not be used outside of a switch.") - } - - def apply(v: Bits)(block: => Unit) { - require(false, "The 'is' keyword may not be used outside of a switch.") - } - - def apply(v: Bits, vr: Bits*)(block: => Unit) { - require(false, "The 'is' keyword may not be used outside of a switch.") - } -} - -/** Conditional logic to form a switch block - * @example - * {{{ ... // default values here - * switch ( myState ) { - * is( state1 ) { - * ... // some logic here - * } - * is( state2 ) { - * ... // some logic here - * } - * } }}}*/ -object switch { // scalastyle:ignore object.name - def apply[T <: Bits](cond: T)(x: => Unit): Unit = macro impl - def impl(c: Context)(cond: c.Tree)(x: c.Tree): c.Tree = { import c.universe._ - val sc = c.universe.internal.reificationSupport.freshTermName("sc") - def extractIsStatement(tree: Tree): List[c.universe.Tree] = tree match { - case q"Chisel.is.apply( ..$params )( ..$body )" => List(q"$sc.is( ..$params )( ..$body )") - case b => throw new Exception(s"Cannot include blocks that do not begin with is() in switch.") - } - val q"..$body" = x - val ises = body.flatMap(extractIsStatement(_)) - q"""{ val $sc = new SwitchContext($cond); ..$ises }""" - } -} diff --git a/src/main/scala/Chisel/util/Counter.scala b/src/main/scala/Chisel/util/Counter.scala deleted file mode 100644 index 872e830a..00000000 --- a/src/main/scala/Chisel/util/Counter.scala +++ /dev/null @@ -1,44 +0,0 @@ -// See LICENSE for license details. - -package Chisel - -/** A counter module - * @param n number of counts before the counter resets (or one more than the - * maximum output value of the counter), need not be a power of two - */ -class Counter(val n: Int) { - require(n >= 0) - val value = if (n > 1) Reg(init=UInt(0, log2Up(n))) else UInt(0) - /** Increment the counter, returning whether the counter currently is at the - * maximum and will wrap. The incremented value is registered and will be - * visible on the next cycle. - */ - def inc(): Bool = { - if (n > 1) { - val wrap = value === UInt(n-1) - value := value + UInt(1) - if (!isPow2(n)) { - when (wrap) { value := UInt(0) } - } - wrap - } else { - Bool(true) - } - } -} - -/** Counter Object - * Example Usage: - * {{{ val countOn = Bool(true) // increment counter every clock cycle - * val myCounter = Counter(countOn, n) - * when ( myCounter.value === UInt(3) ) { ... } }}}*/ -object Counter -{ - def apply(n: Int): Counter = new Counter(n) - def apply(cond: Bool, n: Int): (UInt, Bool) = { - val c = new Counter(n) - var wrap: Bool = null - when (cond) { wrap = c.inc() } - (c.value, cond && wrap) - } -} diff --git a/src/main/scala/Chisel/util/Decoupled.scala b/src/main/scala/Chisel/util/Decoupled.scala deleted file mode 100644 index 8e045855..00000000 --- a/src/main/scala/Chisel/util/Decoupled.scala +++ /dev/null @@ -1,183 +0,0 @@ -// See LICENSE for license details. - -/** Wrappers for ready-valid (Decoupled) interfaces and associated circuit generators using them. - */ - -package Chisel - -/** An I/O Bundle with simple handshaking using valid and ready signals for data 'bits'*/ -class DecoupledIO[+T <: Data](gen: T) extends Bundle -{ - val ready = Bool(INPUT) - val valid = Bool(OUTPUT) - val bits = gen.cloneType.asOutput - def fire(dummy: Int = 0): Bool = ready && valid - override def cloneType: this.type = new DecoupledIO(gen).asInstanceOf[this.type] -} - -/** Adds a ready-valid handshaking protocol to any interface. - * The standard used is that the consumer uses the flipped interface. - */ -object Decoupled { - def apply[T <: Data](gen: T): DecoupledIO[T] = new DecoupledIO(gen) -} - -/** An I/O bundle for enqueuing data with valid/ready handshaking - * Initialization must be handled, if necessary, by the parent circuit - */ -class EnqIO[T <: Data](gen: T) extends DecoupledIO(gen) -{ - /** push dat onto the output bits of this interface to let the consumer know it has happened. - * @param dat the values to assign to bits. - * @return dat. - */ - def enq(dat: T): T = { valid := Bool(true); bits := dat; dat } - - /** Initialize this Bundle. Valid is set to false, and all bits are set to zero. - * NOTE: This method of initialization is still being discussed and could change in the - * future. - */ - def init(): Unit = { - valid := Bool(false) - for (io <- bits.flatten) - io := UInt(0) - } - override def cloneType: this.type = { new EnqIO(gen).asInstanceOf[this.type]; } -} - -/** An I/O bundle for dequeuing data with valid/ready handshaking. - * Initialization must be handled, if necessary, by the parent circuit - */ -class DeqIO[T <: Data](gen: T) extends DecoupledIO(gen) with Flipped -{ - /** Assert ready on this port and return the associated data bits. - * This is typically used when valid has been asserted by the producer side. - * @param b ignored - * @return the data for this device, - */ - def deq(b: Boolean = false): T = { ready := Bool(true); bits } - - /** Initialize this Bundle. - * NOTE: This method of initialization is still being discussed and could change in the - * future. - */ - def init(): Unit = { - ready := Bool(false) - } - override def cloneType: this.type = { new DeqIO(gen).asInstanceOf[this.type]; } -} - -/** An I/O bundle for dequeuing data with valid/ready handshaking */ -class DecoupledIOC[+T <: Data](gen: T) extends Bundle -{ - val ready = Bool(INPUT) - val valid = Bool(OUTPUT) - val bits = gen.cloneType.asOutput -} - -/** An I/O Bundle for Queues - * @param gen The type of data to queue - * @param entries The max number of entries in the queue */ -class QueueIO[T <: Data](gen: T, entries: Int) extends Bundle -{ - /** I/O to enqueue data, is [[Chisel.DecoupledIO]] flipped */ - val enq = Decoupled(gen.cloneType).flip() - /** I/O to enqueue data, is [[Chisel.DecoupledIO]]*/ - val deq = Decoupled(gen.cloneType) - /** The current amount of data in the queue */ - val count = UInt(OUTPUT, log2Up(entries + 1)) -} - -/** A hardware module implementing a Queue - * @param gen The type of data to queue - * @param entries The max number of entries in the queue - * @param pipe True if a single entry queue can run at full throughput (like a pipeline). The ''ready'' signals are - * combinationally coupled. - * @param flow True if the inputs can be consumed on the same cycle (the inputs "flow" through the queue immediately). - * The ''valid'' signals are coupled. - * - * Example usage: - * {{{ val q = new Queue(UInt(), 16) - * q.io.enq <> producer.io.out - * consumer.io.in <> q.io.deq }}} - */ -class Queue[T <: Data](gen: T, val entries: Int, - pipe: Boolean = false, - flow: Boolean = false, - override_reset: Option[Bool] = None) -extends Module(override_reset=override_reset) { - def this(gen: T, entries: Int, pipe: Boolean, flow: Boolean, _reset: Bool) = - this(gen, entries, pipe, flow, Some(_reset)) - - val io = new QueueIO(gen, entries) - - val ram = Mem(entries, gen) - val enq_ptr = Counter(entries) - val deq_ptr = Counter(entries) - val maybe_full = Reg(init=Bool(false)) - - val ptr_match = enq_ptr.value === deq_ptr.value - val empty = ptr_match && !maybe_full - val full = ptr_match && maybe_full - val do_enq = Wire(init=io.enq.fire()) - val do_deq = Wire(init=io.deq.fire()) - - when (do_enq) { - ram(enq_ptr.value) := io.enq.bits - enq_ptr.inc() - } - when (do_deq) { - deq_ptr.inc() - } - when (do_enq != do_deq) { - maybe_full := do_enq - } - - io.deq.valid := !empty - io.enq.ready := !full - io.deq.bits := ram(deq_ptr.value) - - if (flow) { - when (io.enq.valid) { io.deq.valid := Bool(true) } - when (empty) { - io.deq.bits := io.enq.bits - do_deq := Bool(false) - when (io.deq.ready) { do_enq := Bool(false) } - } - } - - if (pipe) { - when (io.deq.ready) { io.enq.ready := Bool(true) } - } - - val ptr_diff = enq_ptr.value - deq_ptr.value - if (isPow2(entries)) { - io.count := Cat(maybe_full && ptr_match, ptr_diff) - } else { - io.count := Mux(ptr_match, - Mux(maybe_full, - UInt(entries), UInt(0)), - Mux(deq_ptr.value > enq_ptr.value, - UInt(entries) + ptr_diff, ptr_diff)) - } -} - -/** Generic hardware queue. Required parameter entries controls - the depth of the queues. The width of the queue is determined - from the inputs. - - Example usage: - {{{ val q = Queue(Decoupled(UInt()), 16) - q.io.enq <> producer.io.out - consumer.io.in <> q.io.deq }}} - */ -object Queue -{ - def apply[T <: Data](enq: DecoupledIO[T], entries: Int = 2, pipe: Boolean = false): DecoupledIO[T] = { - val q = Module(new Queue(enq.bits.cloneType, entries, pipe)) - q.io.enq.valid := enq.valid // not using <> so that override is allowed - q.io.enq.bits := enq.bits - enq.ready := q.io.enq.ready - TransitName(q.io.deq, q) - } -} diff --git a/src/main/scala/Chisel/util/Enum.scala b/src/main/scala/Chisel/util/Enum.scala deleted file mode 100644 index 20057197..00000000 --- a/src/main/scala/Chisel/util/Enum.scala +++ /dev/null @@ -1,21 +0,0 @@ -// See LICENSE for license details. - -/** Enum generators, allowing circuit constants to have more meaningful names. - */ - -package Chisel - -object Enum { - /** Returns a sequence of Bits subtypes with values from 0 until n. Helper method. */ - private def createValues[T <: Bits](nodeType: T, n: Int): Seq[T] = - (0 until n).map(x => nodeType.fromInt(x, log2Up(n))) - - /** create n enum values of given type */ - def apply[T <: Bits](nodeType: T, n: Int): List[T] = createValues(nodeType, n).toList - - /** create enum values of given type and names */ - def apply[T <: Bits](nodeType: T, l: Symbol *): Map[Symbol, T] = (l zip createValues(nodeType, l.length)).toMap - - /** create enum values of given type and names */ - def apply[T <: Bits](nodeType: T, l: List[Symbol]): Map[Symbol, T] = (l zip createValues(nodeType, l.length)).toMap -} diff --git a/src/main/scala/Chisel/util/LFSR.scala b/src/main/scala/Chisel/util/LFSR.scala deleted file mode 100644 index 839b1d1f..00000000 --- a/src/main/scala/Chisel/util/LFSR.scala +++ /dev/null @@ -1,22 +0,0 @@ -// See LICENSE for license details. - -/** LFSRs in all shapes and sizes. - */ - -package Chisel - -// scalastyle:off magic.number -/** linear feedback shift register - */ -object LFSR16 -{ - def apply(increment: Bool = Bool(true)): UInt = - { - val width = 16 - val lfsr = Reg(init=UInt(1, width)) - when (increment) { lfsr := Cat(lfsr(0)^lfsr(2)^lfsr(3)^lfsr(5), lfsr(width-1,1)) } - lfsr - } -} -// scalastyle:on magic.number - diff --git a/src/main/scala/Chisel/util/Lookup.scala b/src/main/scala/Chisel/util/Lookup.scala deleted file mode 100644 index 54922fc4..00000000 --- a/src/main/scala/Chisel/util/Lookup.scala +++ /dev/null @@ -1,17 +0,0 @@ -// See LICENSE for license details. - -package Chisel - -object ListLookup { - def apply[T <: Data](addr: UInt, default: List[T], mapping: Array[(BitPat, List[T])]): List[T] = { - val map = mapping.map(m => (m._1 === addr, m._2)) - default.zipWithIndex map { case (d, i) => - map.foldRight(d)((m, n) => Mux(m._1, m._2(i), n)) - } - } -} - -object Lookup { - def apply[T <: Bits](addr: UInt, default: T, mapping: Seq[(BitPat, T)]): T = - ListLookup(addr, List(default), mapping.map(m => (m._1, List(m._2))).toArray).head -} diff --git a/src/main/scala/Chisel/util/Math.scala b/src/main/scala/Chisel/util/Math.scala deleted file mode 100644 index 5f8212d8..00000000 --- a/src/main/scala/Chisel/util/Math.scala +++ /dev/null @@ -1,42 +0,0 @@ -// See LICENSE for license details. - -/** Scala-land math helper functions, like logs. - */ - -package Chisel - -/** Compute the log2 rounded up with min value of 1 */ -object log2Up { - def apply(in: BigInt): Int = { - require(in >= 0) - 1 max (in-1).bitLength - } - def apply(in: Int): Int = apply(BigInt(in)) -} - -/** Compute the log2 rounded up */ -object log2Ceil { - def apply(in: BigInt): Int = { - require(in > 0) - (in-1).bitLength - } - def apply(in: Int): Int = apply(BigInt(in)) -} - -/** Compute the log2 rounded down with min value of 1 */ -object log2Down { - def apply(in: BigInt): Int = log2Up(in) - (if (isPow2(in)) 0 else 1) - def apply(in: Int): Int = apply(BigInt(in)) -} - -/** Compute the log2 rounded down */ -object log2Floor { - def apply(in: BigInt): Int = log2Ceil(in) - (if (isPow2(in)) 0 else 1) - def apply(in: Int): Int = apply(BigInt(in)) -} - -/** Check if an Integer is a power of 2 */ -object isPow2 { - def apply(in: BigInt): Boolean = in > 0 && ((in & (in-1)) == 0) - def apply(in: Int): Boolean = apply(BigInt(in)) -} diff --git a/src/main/scala/Chisel/util/Mux.scala b/src/main/scala/Chisel/util/Mux.scala deleted file mode 100644 index 9d92321a..00000000 --- a/src/main/scala/Chisel/util/Mux.scala +++ /dev/null @@ -1,61 +0,0 @@ -// See LICENSE for license details. - -/** Mux circuit generators. - */ - -package Chisel - -/** Builds a Mux tree out of the input signal vector using a one hot encoded - select signal. Returns the output of the Mux tree. - */ -object Mux1H -{ - def apply[T <: Data](sel: Seq[Bool], in: Seq[T]): T = - apply(sel zip in) - def apply[T <: Data](in: Iterable[(Bool, T)]): T = SeqUtils.oneHotMux(in) - def apply[T <: Data](sel: UInt, in: Seq[T]): T = - apply((0 until in.size).map(sel(_)), in) - def apply(sel: UInt, in: UInt): Bool = (sel & in).orR -} - -/** Builds a Mux tree under the assumption that multiple select signals - can be enabled. Priority is given to the first select signal. - - Returns the output of the Mux tree. - */ -object PriorityMux -{ - def apply[T <: Data](in: Seq[(Bool, T)]): T = SeqUtils.priorityMux(in) - def apply[T <: Data](sel: Seq[Bool], in: Seq[T]): T = apply(sel zip in) - def apply[T <: Data](sel: Bits, in: Seq[T]): T = apply((0 until in.size).map(sel(_)), in) -} - -/** MuxLookup creates a cascade of n Muxs to search for a key value */ -object MuxLookup { - /** @param key a key to search for - * @param default a default value if nothing is found - * @param mapping a sequence to search of keys and values - * @return the value found or the default if not - */ - def apply[S <: UInt, T <: Bits] (key: S, default: T, mapping: Seq[(S, T)]): T = { - var res = default - for ((k, v) <- mapping.reverse) - res = Mux(k === key, v, res) - res - } - -} - -/** MuxCase returns the first value that is enabled in a map of values */ -object MuxCase { - /** @param default the default value if none are enabled - * @param mapping a set of data values with associated enables - * @return the first value in mapping that is enabled */ - def apply[T <: Bits] (default: T, mapping: Seq[(Bool, T)]): T = { - var res = default - for ((t, v) <- mapping.reverse){ - res = Mux(t, v, res) - } - res - } -} diff --git a/src/main/scala/Chisel/util/OneHot.scala b/src/main/scala/Chisel/util/OneHot.scala deleted file mode 100644 index 73f27403..00000000 --- a/src/main/scala/Chisel/util/OneHot.scala +++ /dev/null @@ -1,62 +0,0 @@ -// See LICENSE for license details. - -/** Circuit generators for working with one-hot representations. - */ - -package Chisel - -/** Converts from One Hot Encoding to a UInt indicating which bit is active - * This is the inverse of [[Chisel.UIntToOH UIntToOH]]*/ -object OHToUInt { - def apply(in: Seq[Bool]): UInt = apply(Vec(in)) - def apply(in: Vec[Bool]): UInt = apply(in.toBits, in.size) - def apply(in: Bits): UInt = apply(in, in.getWidth) - - def apply(in: Bits, width: Int): UInt = { - if (width <= 2) { - Log2(in, width) - } else { - val mid = 1 << (log2Up(width)-1) - val hi = in(width-1, mid) - val lo = in(mid-1, 0) - Cat(hi.orR, apply(hi | lo, mid)) - } - } -} - -/** @return the bit position of the trailing 1 in the input vector - * with the assumption that multiple bits of the input bit vector can be set - * @example {{{ data_out := PriorityEncoder(data_in) }}} - */ -object PriorityEncoder { - def apply(in: Seq[Bool]): UInt = PriorityMux(in, (0 until in.size).map(UInt(_))) - def apply(in: Bits): UInt = apply(in.toBools) -} - -/** Returns the one hot encoding of the input UInt. - */ -object UIntToOH -{ - def apply(in: UInt, width: Int = -1): UInt = - if (width == -1) { - UInt(1) << in - } else { - (UInt(1) << in(log2Up(width)-1,0))(width-1,0) - } -} - -/** Returns a bit vector in which only the least-significant 1 bit in - the input vector, if any, is set. - */ -object PriorityEncoderOH -{ - private def encode(in: Seq[Bool]): UInt = { - val outs = Seq.tabulate(in.size)(i => UInt(BigInt(1) << i, in.size)) - PriorityMux(in :+ Bool(true), outs :+ UInt(0, in.size)) - } - def apply(in: Seq[Bool]): Seq[Bool] = { - val enc = encode(in) - Seq.tabulate(in.size)(enc(_)) - } - def apply(in: Bits): UInt = encode((0 until in.getWidth).map(i => in(i))) -} diff --git a/src/main/scala/Chisel/util/Reg.scala b/src/main/scala/Chisel/util/Reg.scala deleted file mode 100644 index 6584a4bf..00000000 --- a/src/main/scala/Chisel/util/Reg.scala +++ /dev/null @@ -1,55 +0,0 @@ -// See LICENSE for license details. - -/** Variations and helpers for registers. - */ - -package Chisel - -object RegNext { - - def apply[T <: Data](next: T): T = Reg[T](null.asInstanceOf[T], next, null.asInstanceOf[T]) - - def apply[T <: Data](next: T, init: T): T = Reg[T](null.asInstanceOf[T], next, init) - -} - -object RegInit { - - def apply[T <: Data](init: T): T = Reg[T](null.asInstanceOf[T], null.asInstanceOf[T], init) - -} - -/** A register with an Enable signal */ -object RegEnable -{ - def apply[T <: Data](updateData: T, enable: Bool): T = { - val r = Reg(updateData) - when (enable) { r := updateData } - r - } - def apply[T <: Data](updateData: T, resetData: T, enable: Bool): T = { - val r = RegInit(resetData) - when (enable) { r := updateData } - r - } -} - -/** Returns the n-cycle delayed version of the input signal. - */ -object ShiftRegister -{ - /** @param in input to delay - * @param n number of cycles to delay - * @param en enable the shift */ - def apply[T <: Data](in: T, n: Int, en: Bool = Bool(true)): T = - { - // The order of tests reflects the expected use cases. - if (n == 1) { - RegEnable(in, en) - } else if (n != 0) { - RegNext(apply(in, n-1, en)) - } else { - in - } - } -} diff --git a/src/main/scala/Chisel/util/TransitName.scala b/src/main/scala/Chisel/util/TransitName.scala deleted file mode 100644 index ec5a11cc..00000000 --- a/src/main/scala/Chisel/util/TransitName.scala +++ /dev/null @@ -1,21 +0,0 @@ -package Chisel - -import internal.HasId - -object TransitName { - // The purpose of this is to allow a library to 'move' a name call to a more - // appropriate place. - // For example, a library factory function may create a module and return - // the io. The only user-exposed field is that given IO, which can't use - // any name supplied by the user. This can add a hook so that the supplied - // name then names the Module. - // See Queue companion object for working example - def apply[T<:HasId](from: T, to: HasId): T = { - from.addPostnameHook((given_name: String) => {to.suggestName(given_name)}) - from - } - def withSuffix[T<:HasId](suffix: String)(from: T, to: HasId): T = { - from.addPostnameHook((given_name: String) => {to.suggestName(given_name+suffix)}) - from - } -} diff --git a/src/main/scala/Chisel/util/Valid.scala b/src/main/scala/Chisel/util/Valid.scala deleted file mode 100644 index 9e2202bb..00000000 --- a/src/main/scala/Chisel/util/Valid.scala +++ /dev/null @@ -1,59 +0,0 @@ -// See LICENSE for license details. - -/** Wrappers for valid interfaces and associated circuit generators using them. - */ - -package Chisel - -/** An I/O Bundle containing data and a signal determining if it is valid */ -class ValidIO[+T <: Data](gen2: T) extends Bundle -{ - val valid = Bool(OUTPUT) - val bits = gen2.cloneType.asOutput - def fire(dummy: Int = 0): Bool = valid - override def cloneType: this.type = new ValidIO(gen2).asInstanceOf[this.type] -} - -/** Adds a valid protocol to any interface. The standard used is - that the consumer uses the flipped interface. -*/ -object Valid { - def apply[T <: Data](gen: T): ValidIO[T] = new ValidIO(gen) -} - -/** A hardware module that delays data coming down the pipeline - by the number of cycles set by the latency parameter. Functionality - is similar to ShiftRegister but this exposes a Pipe interface. - - Example usage: - val pipe = new Pipe(UInt()) - pipe.io.enq <> produce.io.out - consumer.io.in <> pipe.io.deq - */ -object Pipe -{ - def apply[T <: Data](enqValid: Bool, enqBits: T, latency: Int): ValidIO[T] = { - if (latency == 0) { - val out = Wire(Valid(enqBits)) - out.valid <> enqValid - out.bits <> enqBits - out - } else { - val v = Reg(Bool(), next=enqValid, init=Bool(false)) - val b = RegEnable(enqBits, enqValid) - apply(v, b, latency-1) - } - } - def apply[T <: Data](enqValid: Bool, enqBits: T): ValidIO[T] = apply(enqValid, enqBits, 1) - def apply[T <: Data](enq: ValidIO[T], latency: Int = 1): ValidIO[T] = apply(enq.valid, enq.bits, latency) -} - -class Pipe[T <: Data](gen: T, latency: Int = 1) extends Module -{ - val io = new Bundle { - val enq = Valid(gen).flip - val deq = Valid(gen) - } - - io.deq <> Pipe(io.enq, latency) -} diff --git a/src/main/scala/chisel/Driver.scala b/src/main/scala/chisel/Driver.scala new file mode 100644 index 00000000..ba2b1389 --- /dev/null +++ b/src/main/scala/chisel/Driver.scala @@ -0,0 +1,132 @@ +// See LICENSE for license details. + +package chisel + +import scala.sys.process._ +import java.io._ + +import internal._ +import internal.firrtl._ + +trait BackendCompilationUtilities { + /** Create a temporary directory with the prefix name. Exists here because it doesn't in Java 6. + */ + def createTempDirectory(prefix: String): File = { + val temp = File.createTempFile(prefix, "") + if (!temp.delete()) { + throw new IOException(s"Unable to delete temp file '$temp'") + } + if (!temp.mkdir()) { + throw new IOException(s"Unable to create temp directory '$temp'") + } + temp + } + + def makeHarness(template: String => String, post: String)(f: File): File = { + val prefix = f.toString.split("/").last + val vf = new File(f.toString + post) + val w = new FileWriter(vf) + w.write(template(prefix)) + w.close() + vf + } + + def firrtlToVerilog(prefix: String, dir: File): ProcessBuilder = { + Process( + Seq("firrtl", + "-i", s"$prefix.fir", + "-o", s"$prefix.v", + "-X", "verilog"), + dir) + } + + /** Generates a Verilator invocation to convert Verilog sources to C++ + * simulation sources. + * + * The Verilator prefix will be V$dutFile, and running this will generate + * C++ sources and headers as well as a makefile to compile them. + * + * @param dutFile name of the DUT .v without the .v extension + * @param name of the top-level module in the design + * @param dir output directory + * @param vSources list of additional Verilog sources to compile + * @param cppHarness C++ testharness to compile/link against + */ + def verilogToCpp( + dutFile: String, + topModule: String, + dir: File, + vSources: Seq[File], + cppHarness: File + ): ProcessBuilder = { + val command = Seq("verilator", + "--cc", s"$dutFile.v") ++ + vSources.map(file => Seq("-v", file.toString)).flatten ++ + Seq("--assert", + "-Wno-fatal", + "-Wno-WIDTH", + "-Wno-STMTDLY", + "--trace", + "-O2", + "--top-module", topModule, + "+define+TOP_TYPE=V" + dutFile, + s"+define+PRINTF_COND=!$topModule.reset", + "-CFLAGS", + s"""-Wno-undefined-bool-conversion -O2 -DTOP_TYPE=V$dutFile -include V$dutFile.h""", + "-Mdir", dir.toString, + "--exe", cppHarness.toString) + System.out.println(s"${command.mkString(" ")}") // scalastyle:ignore regex + command + } + + def cppToExe(prefix: String, dir: File): ProcessBuilder = + Seq("make", "-C", dir.toString, "-j", "-f", s"V${prefix}.mk", s"V${prefix}") + + def executeExpectingFailure( + prefix: String, + dir: File, + assertionMsg: String = "Assertion failed"): Boolean = { + var triggered = false + val e = Process(s"./V${prefix}", dir) ! + ProcessLogger(line => { + triggered = triggered || line.contains(assertionMsg) + System.out.println(line) // scalastyle:ignore regex + }) + triggered + } + + def executeExpectingSuccess(prefix: String, dir: File): Boolean = { + !executeExpectingFailure(prefix, dir) + } +} + +object Driver extends BackendCompilationUtilities { + + /** Elaborates the Module specified in the gen function into a Circuit + * + * @param gen a function that creates a Module hierarchy + * @return the resulting Chisel IR in the form of a Circuit (TODO: Should be FIRRTL IR) + */ + def elaborate[T <: Module](gen: () => T): Circuit = Builder.build(Module(gen())) + + def emit[T <: Module](gen: () => T): String = Emitter.emit(elaborate(gen)) + + def dumpFirrtl(ir: Circuit, optName: Option[File]): File = { + val f = optName.getOrElse(new File(ir.name + ".fir")) + val w = new FileWriter(f) + w.write(Emitter.emit(ir)) + w.close() + f + } + + private var target_dir: Option[String] = None + def parseArgs(args: Array[String]): Unit = { + for (i <- 0 until args.size) { + if (args(i) == "--targetDir") { + target_dir = Some(args(i + 1)) + } + } + } + + def targetDir(): String = { target_dir getOrElse new File(".").getCanonicalPath } +} diff --git a/src/main/scala/chisel/FileSystemUtilities.scala b/src/main/scala/chisel/FileSystemUtilities.scala new file mode 100644 index 00000000..f100eaf6 --- /dev/null +++ b/src/main/scala/chisel/FileSystemUtilities.scala @@ -0,0 +1,10 @@ +// See LICENSE for license details. + +package chisel + +@deprecated("FileSystemUtilities doesn't exist in chisel3", "3.0.0") +trait FileSystemUtilities { + def createOutputFile(name: String): java.io.FileWriter = { + new java.io.FileWriter(Driver.targetDir + "/" + name) + } +} diff --git a/src/main/scala/chisel/ImplicitConversions.scala b/src/main/scala/chisel/ImplicitConversions.scala new file mode 100644 index 00000000..f786d4f1 --- /dev/null +++ b/src/main/scala/chisel/ImplicitConversions.scala @@ -0,0 +1,8 @@ +// See LICENSE for license details. + +package chisel + +object ImplicitConversions { + implicit def intToUInt(x: Int): UInt = UInt(x) + implicit def booleanToBool(x: Boolean): Bool = Bool(x) +} diff --git a/src/main/scala/chisel/Main.scala b/src/main/scala/chisel/Main.scala new file mode 100644 index 00000000..79e5c9ca --- /dev/null +++ b/src/main/scala/chisel/Main.scala @@ -0,0 +1,17 @@ +// See LICENSE for license details. + +package chisel + +import java.io.File + +@deprecated("chiselMain doesn't exist in Chisel3", "3.0") object chiselMain { + def apply[T <: Module](args: Array[String], gen: () => T): Unit = + Predef.assert(false, "No more chiselMain in Chisel3") + + def run[T <: Module] (args: Array[String], gen: () => T): Unit = { + val circuit = Driver.elaborate(gen) + Driver.parseArgs(args) + val output_file = new File(Driver.targetDir + "/" + circuit.name + ".fir") + Driver.dumpFirrtl(circuit, Option(output_file)) + } +} diff --git a/src/main/scala/chisel/compatibility.scala b/src/main/scala/chisel/compatibility.scala new file mode 100644 index 00000000..80936a42 --- /dev/null +++ b/src/main/scala/chisel/compatibility.scala @@ -0,0 +1,139 @@ +// See LICENSE for license details. + +// Allows legacy users to continue using Chisel (capital C) package name while +// moving to the more standard package naming convention chisel (lowercase c). + +package object Chisel { + type Direction = chisel.Direction + val INPUT = chisel.INPUT + val OUTPUT = chisel.OUTPUT + val NO_DIR = chisel.NO_DIR + val debug = chisel.debug + type Flipped = chisel.Flipped + type Data = chisel.Data + val Wire = chisel.Wire + val Clock = chisel.Clock + type Clock = chisel.Clock + + type Aggregate = chisel.Aggregate + val Vec = chisel.Vec + type Vec[T <: Data] = chisel.Vec[T] + type VecLike[T <: Data] = chisel.VecLike[T] + type Bundle = chisel.Bundle + + val assert = chisel.assert + + val BitPat = chisel.BitPat + type BitPat = chisel.BitPat + + type Bits = chisel.Bits + val Bits = chisel.Bits + type Num[T <: Data] = chisel.Num[T] + type UInt = chisel.UInt + val UInt = chisel.UInt + type SInt = chisel.SInt + val SInt = chisel.SInt + type Bool = chisel.Bool + val Bool = chisel.Bool + val Mux = chisel.Mux + + type BlackBox = chisel.BlackBox + + val Mem = chisel.Mem + type MemBase[T <: Data] = chisel.MemBase[T] + type Mem[T <: Data] = chisel.Mem[T] + val SeqMem = chisel.SeqMem + type SeqMem[T <: Data] = chisel.SeqMem[T] + + val Module = chisel.Module + type Module = chisel.Module + + val printf = chisel.printf + + val Reg = chisel.Reg + + val when = chisel.when + type WhenContext = chisel.WhenContext + + + type BackendCompilationUtilities = chisel.BackendCompilationUtilities + val Driver = chisel.Driver + type FileSystemUtilities = chisel.FileSystemUtilities + val ImplicitConversions = chisel.ImplicitConversions + val chiselMain = chisel.chiselMain + val throwException = chisel.throwException + + + val log2Up = chisel.log2Up + val log2Ceil = chisel.log2Ceil + val log2Down = chisel.log2Down + val log2Floor = chisel.log2Floor + val isPow2 = chisel.isPow2 + + type ArbiterIO[T <: Data] = chisel.ArbiterIO[T] + type LockingArbiterLike[T <: Data] = chisel.LockingArbiterLike[T] + type LockingRRArbiter[T <: Data] = chisel.LockingRRArbiter[T] + type LockingArbiter[T <: Data] = chisel.LockingArbiter[T] + type RRArbiter[T <: Data] = chisel.RRArbiter[T] + type Arbiter[T <: Data] = chisel.Arbiter[T] + + val FillInterleaved = chisel.FillInterleaved + val PopCount = chisel.PopCount + val Fill = chisel.Fill + val Reverse = chisel.Reverse + + val Cat = chisel.Cat + + val Log2 = chisel.Log2 + + val unless = chisel.unless + type SwitchContext[T <: Bits] = chisel.SwitchContext[T] + val is = chisel.is + val switch = chisel.switch + + type Counter = chisel.Counter + val Counter = chisel.Counter + + type DecoupledIO[+T <: Data] = chisel.DecoupledIO[T] + val Decoupled = chisel.Decoupled + type EnqIO[T <: Data] = chisel.EnqIO[T] + type DeqIO[T <: Data] = chisel.DeqIO[T] + type DecoupledIOC[+T <: Data] = chisel.DecoupledIOC[T] + type QueueIO[T <: Data] = chisel.QueueIO[T] + type Queue[T <: Data] = chisel.Queue[T] + val Queue = chisel.Queue + + val Enum = chisel.Enum + + val LFSR16 = chisel.LFSR16 + + val ListLookup = chisel.ListLookup + val Lookup = chisel.Lookup + + val Mux1H = chisel.Mux1H + val PriorityMux = chisel.PriorityMux + val MuxLookup = chisel.MuxLookup + val MuxCase = chisel.MuxCase + + val OHToUInt = chisel.OHToUInt + val PriorityEncoder = chisel.PriorityEncoder + val UIntToOH = chisel.UIntToOH + val PriorityEncoderOH = chisel.PriorityEncoderOH + + val RegNext = chisel.RegNext + val RegInit = chisel.RegInit + val RegEnable = chisel.RegEnable + val ShiftRegister = chisel.ShiftRegister + + type ValidIO[+T <: Data] = chisel.ValidIO[T] + val Valid = chisel.Valid + val Pipe = chisel.Pipe + type Pipe[T <: Data] = chisel.Pipe[T] +} + +package Chisel { + package object testers { + type BasicTester = chisel.testers.BasicTester + val TesterDriver = chisel.testers.TesterDriver + } +} diff --git a/src/main/scala/chisel/internal/firrtl/Emitter.scala b/src/main/scala/chisel/internal/firrtl/Emitter.scala new file mode 100644 index 00000000..e48eb226 --- /dev/null +++ b/src/main/scala/chisel/internal/firrtl/Emitter.scala @@ -0,0 +1,112 @@ +// See LICENSE for license details. + +package chisel.internal.firrtl +import chisel._ +import chisel.internal.sourceinfo.{NoSourceInfo, SourceLine} + +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 = { + val firrtlLine = 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() + s"skip" + } + e.sourceInfo match { + case SourceLine(filename, line, col) => s"${firrtlLine} @[${filename} ${line}:${col}] " + case _: NoSourceInfo => firrtlLine + } + } + + // 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/src/main/scala/chisel/package.scala b/src/main/scala/chisel/package.scala new file mode 100644 index 00000000..1abbc74f --- /dev/null +++ b/src/main/scala/chisel/package.scala @@ -0,0 +1,31 @@ +package object chisel { + import scala.language.experimental.macros + + import internal.firrtl.Width + import internal.sourceinfo.{SourceInfo, SourceInfoTransform} + + implicit class fromBigIntToLiteral(val x: BigInt) extends AnyVal { + def U: UInt = UInt(x, Width()) + def S: SInt = SInt(x, Width()) + } + implicit class fromIntToLiteral(val x: Int) extends AnyVal { + def U: UInt = UInt(BigInt(x), Width()) + def S: SInt = SInt(BigInt(x), Width()) + } + implicit class fromStringToLiteral(val x: String) extends AnyVal { + def U: UInt = UInt(x) + } + implicit class fromBooleanToLiteral(val x: Boolean) extends AnyVal { + def B: Bool = Bool(x) + } + + implicit class fromUIntToBitPatComparable(val x: UInt) extends AnyVal { + 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 === x + def do_!= (that: BitPat)(implicit sourceInfo: SourceInfo): Bool = that != x + def do_=/= (that: BitPat)(implicit sourceInfo: SourceInfo): Bool = that =/= x + } +} diff --git a/src/main/scala/chisel/testers/BasicTester.scala b/src/main/scala/chisel/testers/BasicTester.scala new file mode 100644 index 00000000..36ff7c52 --- /dev/null +++ b/src/main/scala/chisel/testers/BasicTester.scala @@ -0,0 +1,38 @@ +// See LICENSE for license details. + +package chisel.testers +import chisel._ + +import scala.language.experimental.macros + +import internal._ +import internal.Builder.pushCommand +import internal.firrtl._ +import internal.sourceinfo.SourceInfo + +class BasicTester extends Module { + // The testbench has no IOs, rather it should communicate using printf, assert, and stop. + val io = new Bundle() + + def popCount(n: Long): Int = n.toBinaryString.count(_=='1') + + /** Ends the test reporting success. + * + * 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. + */ + def stop()(implicit sourceInfo: SourceInfo) { + // TODO: rewrite this using library-style SourceInfo passing. + when (!reset) { + pushCommand(Stop(sourceInfo, Node(clock), 0)) + } + } + + /** The finish method provides a hook that subclasses of BasicTester can use to + * alter a circuit after their constructor has been called. + * For example, a specialized tester subclassing BasicTester could override finish in order to + * add flow control logic for a decoupled io port of a device under test + */ + def finish(): Unit = {} +} diff --git a/src/main/scala/chisel/testers/TesterDriver.scala b/src/main/scala/chisel/testers/TesterDriver.scala new file mode 100644 index 00000000..5c0275e0 --- /dev/null +++ b/src/main/scala/chisel/testers/TesterDriver.scala @@ -0,0 +1,69 @@ +// See LICENSE for license details. + +package chisel.testers + +import chisel._ +import scala.io.Source +import scala.sys.process._ +import java.io._ + +object TesterDriver extends BackendCompilationUtilities { + /** Copy the contents of a resource to a destination file. + */ + def copyResourceToFile(name: String, file: File) { + val in = getClass().getResourceAsStream(name) + if (in == null) { + throw new FileNotFoundException(s"Resource '$name'") + } + val out = new FileOutputStream(file) + Iterator.continually(in.read).takeWhile(-1 !=).foreach(out.write) + out.close() + } + + /** For use with modules that should successfully be elaborated by the + * frontend, and which can be turned into executables with assertions. */ + def execute(t: () => BasicTester, additionalVResources: Seq[String] = Seq()): Boolean = { + // Invoke the chisel compiler to get the circuit's IR + val circuit = Driver.elaborate(finishWrapper(t)) + + // Set up a bunch of file handlers based on a random temp filename, + // plus the quirks of Verilator's naming conventions + val target = circuit.name + + val path = createTempDirectory(target) + val fname = new File(path, target) + + // For now, dump the IR out to a file + Driver.dumpFirrtl(circuit, Some(new File(fname.toString + ".fir"))) + + // Copy CPP harness and other Verilog sources from resources into files + val cppHarness = new File(path, "top.cpp") + copyResourceToFile("/top.cpp", cppHarness) + val additionalVFiles = additionalVResources.map((name: String) => { + val mangledResourceName = name.replace("/", "_") + val out = new File(path, mangledResourceName) + copyResourceToFile(name, out) + out + }) + + // Use sys.Process to invoke a bunch of backend stuff, then run the resulting exe + if ((firrtlToVerilog(target, path) #&& + verilogToCpp(target, target, path, additionalVFiles, cppHarness) #&& + cppToExe(target, path)).! == 0) { + executeExpectingSuccess(target, path) + } else { + false + } + } + /** + * Calls the finish method of an BasicTester or a class that extends it. + * The finish method is a hook for code that augments the circuit built in the constructor. + */ + def finishWrapper(test: () => BasicTester): () => BasicTester = { + () => { + val tester = test() + tester.finish() + tester + } + } +} diff --git a/src/main/scala/chisel/throwException.scala b/src/main/scala/chisel/throwException.scala new file mode 100644 index 00000000..fdd62c7e --- /dev/null +++ b/src/main/scala/chisel/throwException.scala @@ -0,0 +1,12 @@ +// See LICENSE for license details. + +package chisel + +@deprecated("throwException doesn't exist in Chisel3", "3.0.0") +@throws(classOf[Exception]) +object throwException { + def apply(s: String, t: Throwable = null) = { + val xcpt = new Exception(s, t) + throw xcpt + } +} diff --git a/src/main/scala/chisel/util/Arbiter.scala b/src/main/scala/chisel/util/Arbiter.scala new file mode 100644 index 00000000..afe48963 --- /dev/null +++ b/src/main/scala/chisel/util/Arbiter.scala @@ -0,0 +1,117 @@ +// See LICENSE for license details. + +/** Arbiters in all shapes and sizes. + */ + +package chisel + +/** An I/O bundle for the Arbiter */ +class ArbiterIO[T <: Data](gen: T, n: Int) extends Bundle { + val in = Vec(n, Decoupled(gen)).flip + val out = Decoupled(gen) + val chosen = UInt(OUTPUT, log2Up(n)) +} + +/** Arbiter Control determining which producer has access */ +private object ArbiterCtrl +{ + def apply(request: Seq[Bool]): Seq[Bool] = request.length match { + case 0 => Seq() + case 1 => Seq(Bool(true)) + case _ => Bool(true) +: request.tail.init.scanLeft(request.head)(_ || _).map(!_) + } +} + +abstract class LockingArbiterLike[T <: Data](gen: T, n: Int, count: Int, needsLock: Option[T => Bool]) extends Module { + def grant: Seq[Bool] + def choice: UInt + val io = new ArbiterIO(gen, n) + + io.chosen := choice + io.out.valid := io.in(io.chosen).valid + io.out.bits := io.in(io.chosen).bits + + if (count > 1) { + val lockCount = Counter(count) + val lockIdx = Reg(UInt()) + val locked = lockCount.value =/= UInt(0) + val wantsLock = needsLock.map(_(io.out.bits)).getOrElse(Bool(true)) + + when (io.out.fire() && wantsLock) { + lockIdx := io.chosen + lockCount.inc() + } + + when (locked) { io.chosen := lockIdx } + for ((in, (g, i)) <- io.in zip grant.zipWithIndex) + in.ready := Mux(locked, lockIdx === UInt(i), g) && io.out.ready + } else { + for ((in, g) <- io.in zip grant) + in.ready := g && io.out.ready + } +} + +class LockingRRArbiter[T <: Data](gen: T, n: Int, count: Int, needsLock: Option[T => Bool] = None) + extends LockingArbiterLike[T](gen, n, count, needsLock) { + lazy val lastGrant = RegEnable(io.chosen, io.out.fire()) + lazy val grantMask = (0 until n).map(UInt(_) > lastGrant) + lazy val validMask = io.in zip grantMask map { case (in, g) => in.valid && g } + + override def grant: Seq[Bool] = { + val ctrl = ArbiterCtrl((0 until n).map(i => validMask(i)) ++ io.in.map(_.valid)) + (0 until n).map(i => ctrl(i) && grantMask(i) || ctrl(i + n)) + } + + override lazy val choice = Wire(init=UInt(n-1)) + for (i <- n-2 to 0 by -1) + when (io.in(i).valid) { choice := UInt(i) } + for (i <- n-1 to 1 by -1) + when (validMask(i)) { choice := UInt(i) } +} + +class LockingArbiter[T <: Data](gen: T, n: Int, count: Int, needsLock: Option[T => Bool] = None) + extends LockingArbiterLike[T](gen, n, count, needsLock) { + def grant: Seq[Bool] = ArbiterCtrl(io.in.map(_.valid)) + + override lazy val choice = Wire(init=UInt(n-1)) + for (i <- n-2 to 0 by -1) + when (io.in(i).valid) { choice := UInt(i) } +} + +/** Hardware module that is used to sequence n producers into 1 consumer. + Producers are chosen in round robin order. + + Example usage: + val arb = new RRArbiter(2, UInt()) + arb.io.in(0) <> producer0.io.out + arb.io.in(1) <> producer1.io.out + consumer.io.in <> arb.io.out + */ +class RRArbiter[T <: Data](gen:T, n: Int) extends LockingRRArbiter[T](gen, n, 1) + +/** Hardware module that is used to sequence n producers into 1 consumer. + Priority is given to lower producer + + Example usage: + val arb = Module(new Arbiter(2, UInt())) + arb.io.in(0) <> producer0.io.out + arb.io.in(1) <> producer1.io.out + consumer.io.in <> arb.io.out + */ +class Arbiter[T <: Data](gen: T, n: Int) extends Module { + val io = new ArbiterIO(gen, n) + + io.chosen := UInt(n-1) + io.out.bits := io.in(n-1).bits + for (i <- n-2 to 0 by -1) { + when (io.in(i).valid) { + io.chosen := UInt(i) + io.out.bits := io.in(i).bits + } + } + + val grant = ArbiterCtrl(io.in.map(_.valid)) + for ((in, g) <- io.in zip grant) + in.ready := g && io.out.ready + io.out.valid := !grant.last || io.in.last.valid +} diff --git a/src/main/scala/chisel/util/Bitwise.scala b/src/main/scala/chisel/util/Bitwise.scala new file mode 100644 index 00000000..27064059 --- /dev/null +++ b/src/main/scala/chisel/util/Bitwise.scala @@ -0,0 +1,71 @@ +// See LICENSE for license details. + +/** Miscellaneous circuit generators operating on bits. + */ + +package chisel + +object FillInterleaved +{ + def apply(n: Int, in: UInt): UInt = apply(n, in.toBools) + def apply(n: Int, in: Seq[Bool]): UInt = Vec(in.map(Fill(n, _))).toBits +} + +/** Returns the number of bits set (i.e value is 1) in the input signal. + */ +object PopCount +{ + def apply(in: Iterable[Bool]): UInt = SeqUtils.count(in.toSeq) + def apply(in: Bits): UInt = apply((0 until in.getWidth).map(in(_))) +} + +/** Fill fans out a UInt to multiple copies */ +object Fill { + /** Fan out x n times */ + def apply(n: Int, x: UInt): UInt = { + n match { + case 0 => UInt(width=0) + case 1 => x + case y if n > 1 => + val p2 = Array.ofDim[UInt](log2Up(n + 1)) + p2(0) = x + for (i <- 1 until p2.length) + p2(i) = Cat(p2(i-1), p2(i-1)) + Cat((0 until log2Up(y + 1)).filter(i => (y & (1 << i)) != 0).map(p2(_))) + case _ => throw new IllegalArgumentException(s"n (=$n) must be nonnegative integer.") + } + } + /** Fan out x n times */ + def apply(n: Int, x: Bool): UInt = + if (n > 1) { + UInt(0,n) - x + } else { + apply(n, x: UInt) + } +} + +/** Litte/big bit endian convertion: reverse the order of the bits in a UInt. +*/ +object Reverse +{ + private def doit(in: UInt, length: Int): UInt = { + if (length == 1) { + in + } else if (isPow2(length) && length >= 8 && length <= 64) { + // This esoterica improves simulation performance + var res = in + var shift = length >> 1 + var mask = UInt((BigInt(1) << length) - 1, length) + do { + mask = mask ^ (mask(length-shift-1,0) << shift) + res = ((res >> shift) & mask) | ((res(length-shift-1,0) << shift) & ~mask) + shift = shift >> 1 + } while (shift > 0) + res + } else { + val half = (1 << log2Up(length))/2 + Cat(doit(in(half-1,0), half), doit(in(length-1,half), length-half)) + } + } + def apply(in: UInt): UInt = doit(in, in.getWidth) +} diff --git a/src/main/scala/chisel/util/Cat.scala b/src/main/scala/chisel/util/Cat.scala new file mode 100644 index 00000000..a35619df --- /dev/null +++ b/src/main/scala/chisel/util/Cat.scala @@ -0,0 +1,18 @@ +// See LICENSE for license details. + +package chisel + +object Cat { + /** Combine data elements together + * @param a Data to combine with + * @param r any number of other Data elements to be combined in order + * @return A UInt which is all of the bits combined together + */ + def apply[T <: Bits](a: T, r: T*): UInt = apply(a :: r.toList) + + /** Combine data elements together + * @param r any number of other Data elements to be combined in order + * @return A UInt which is all of the bits combined together + */ + def apply[T <: Bits](r: Seq[T]): UInt = SeqUtils.asUInt(r.reverse) +} diff --git a/src/main/scala/chisel/util/CircuitMath.scala b/src/main/scala/chisel/util/CircuitMath.scala new file mode 100644 index 00000000..001be802 --- /dev/null +++ b/src/main/scala/chisel/util/CircuitMath.scala @@ -0,0 +1,26 @@ +// See LICENSE for license details. + +/** Circuit-land math operations. + */ + +package chisel + +/** Compute Log2 with truncation of a UInt in hardware using a Mux Tree + * An alternative interpretation is it computes the minimum number of bits needed to represent x + * @example + * {{{ data_out := Log2(data_in) }}} + * @note Truncation is used so Log2(UInt(12412)) = 13*/ +object Log2 { + /** Compute the Log2 on the least significant n bits of x */ + def apply(x: Bits, width: Int): UInt = { + if (width < 2) { + UInt(0) + } else if (width == 2) { + x(1) + } else { + Mux(x(width-1), UInt(width-1), apply(x, width-1)) + } + } + + def apply(x: Bits): UInt = apply(x, x.getWidth) +} diff --git a/src/main/scala/chisel/util/Conditional.scala b/src/main/scala/chisel/util/Conditional.scala new file mode 100644 index 00000000..94f00080 --- /dev/null +++ b/src/main/scala/chisel/util/Conditional.scala @@ -0,0 +1,71 @@ +// See LICENSE for license details. + +/** Conditional blocks. + */ + +package chisel + +import scala.language.reflectiveCalls +import scala.language.experimental.macros +import scala.reflect.runtime.universe._ +import scala.reflect.macros.blackbox._ + +/** This is identical to [[Chisel.when when]] with the condition inverted */ +object unless { // scalastyle:ignore object.name + def apply(c: Bool)(block: => Unit) { + when (!c) { block } + } +} + +class SwitchContext[T <: Bits](cond: T) { + def is(v: Iterable[T])(block: => Unit) { + if (!v.isEmpty) when (v.map(_.asUInt === cond.asUInt).reduce(_||_)) { block } + } + def is(v: T)(block: => Unit) { is(Seq(v))(block) } + def is(v: T, vr: T*)(block: => Unit) { is(v :: vr.toList)(block) } +} + +/** An object for separate cases in [[Chisel.switch switch]] + * It is equivalent to a [[Chisel.when$ when]] block comparing to the condition + * Use outside of a switch statement is illegal */ +object is { // scalastyle:ignore object.name + // Begin deprecation of non-type-parameterized is statements. + def apply(v: Iterable[Bits])(block: => Unit) { + require(false, "The 'is' keyword may not be used outside of a switch.") + } + + def apply(v: Bits)(block: => Unit) { + require(false, "The 'is' keyword may not be used outside of a switch.") + } + + def apply(v: Bits, vr: Bits*)(block: => Unit) { + require(false, "The 'is' keyword may not be used outside of a switch.") + } +} + +/** Conditional logic to form a switch block + * @example + * {{{ ... // default values here + * switch ( myState ) { + * is( state1 ) { + * ... // some logic here + * } + * is( state2 ) { + * ... // some logic here + * } + * } }}}*/ +object switch { // scalastyle:ignore object.name + def apply[T <: Bits](cond: T)(x: => Unit): Unit = macro impl + def impl(c: Context)(cond: c.Tree)(x: c.Tree): c.Tree = { import c.universe._ + val sc = c.universe.internal.reificationSupport.freshTermName("sc") + def extractIsStatement(tree: Tree): List[c.universe.Tree] = tree match { + // TODO: remove when Chisel compatibility package is removed + case q"Chisel.`package`.is.apply( ..$params )( ..$body )" => List(q"$sc.is( ..$params )( ..$body )") + case q"chisel.is.apply( ..$params )( ..$body )" => List(q"$sc.is( ..$params )( ..$body )") + case b => throw new Exception(s"Cannot include blocks that do not begin with is() in switch.") + } + val q"..$body" = x + val ises = body.flatMap(extractIsStatement(_)) + q"""{ val $sc = new SwitchContext($cond); ..$ises }""" + } +} diff --git a/src/main/scala/chisel/util/Counter.scala b/src/main/scala/chisel/util/Counter.scala new file mode 100644 index 00000000..dde1e347 --- /dev/null +++ b/src/main/scala/chisel/util/Counter.scala @@ -0,0 +1,44 @@ +// See LICENSE for license details. + +package chisel + +/** A counter module + * @param n number of counts before the counter resets (or one more than the + * maximum output value of the counter), need not be a power of two + */ +class Counter(val n: Int) { + require(n >= 0) + val value = if (n > 1) Reg(init=UInt(0, log2Up(n))) else UInt(0) + /** Increment the counter, returning whether the counter currently is at the + * maximum and will wrap. The incremented value is registered and will be + * visible on the next cycle. + */ + def inc(): Bool = { + if (n > 1) { + val wrap = value === UInt(n-1) + value := value + UInt(1) + if (!isPow2(n)) { + when (wrap) { value := UInt(0) } + } + wrap + } else { + Bool(true) + } + } +} + +/** Counter Object + * Example Usage: + * {{{ val countOn = Bool(true) // increment counter every clock cycle + * val myCounter = Counter(countOn, n) + * when ( myCounter.value === UInt(3) ) { ... } }}}*/ +object Counter +{ + def apply(n: Int): Counter = new Counter(n) + def apply(cond: Bool, n: Int): (UInt, Bool) = { + val c = new Counter(n) + var wrap: Bool = null + when (cond) { wrap = c.inc() } + (c.value, cond && wrap) + } +} diff --git a/src/main/scala/chisel/util/Decoupled.scala b/src/main/scala/chisel/util/Decoupled.scala new file mode 100644 index 00000000..955b0870 --- /dev/null +++ b/src/main/scala/chisel/util/Decoupled.scala @@ -0,0 +1,183 @@ +// See LICENSE for license details. + +/** Wrappers for ready-valid (Decoupled) interfaces and associated circuit generators using them. + */ + +package chisel + +/** An I/O Bundle with simple handshaking using valid and ready signals for data 'bits'*/ +class DecoupledIO[+T <: Data](gen: T) extends Bundle +{ + val ready = Bool(INPUT) + val valid = Bool(OUTPUT) + val bits = gen.cloneType.asOutput + def fire(dummy: Int = 0): Bool = ready && valid + override def cloneType: this.type = new DecoupledIO(gen).asInstanceOf[this.type] +} + +/** Adds a ready-valid handshaking protocol to any interface. + * The standard used is that the consumer uses the flipped interface. + */ +object Decoupled { + def apply[T <: Data](gen: T): DecoupledIO[T] = new DecoupledIO(gen) +} + +/** An I/O bundle for enqueuing data with valid/ready handshaking + * Initialization must be handled, if necessary, by the parent circuit + */ +class EnqIO[T <: Data](gen: T) extends DecoupledIO(gen) +{ + /** push dat onto the output bits of this interface to let the consumer know it has happened. + * @param dat the values to assign to bits. + * @return dat. + */ + def enq(dat: T): T = { valid := Bool(true); bits := dat; dat } + + /** Initialize this Bundle. Valid is set to false, and all bits are set to zero. + * NOTE: This method of initialization is still being discussed and could change in the + * future. + */ + def init(): Unit = { + valid := Bool(false) + for (io <- bits.flatten) + io := UInt(0) + } + override def cloneType: this.type = { new EnqIO(gen).asInstanceOf[this.type]; } +} + +/** An I/O bundle for dequeuing data with valid/ready handshaking. + * Initialization must be handled, if necessary, by the parent circuit + */ +class DeqIO[T <: Data](gen: T) extends DecoupledIO(gen) with Flipped +{ + /** Assert ready on this port and return the associated data bits. + * This is typically used when valid has been asserted by the producer side. + * @param b ignored + * @return the data for this device, + */ + def deq(b: Boolean = false): T = { ready := Bool(true); bits } + + /** Initialize this Bundle. + * NOTE: This method of initialization is still being discussed and could change in the + * future. + */ + def init(): Unit = { + ready := Bool(false) + } + override def cloneType: this.type = { new DeqIO(gen).asInstanceOf[this.type]; } +} + +/** An I/O bundle for dequeuing data with valid/ready handshaking */ +class DecoupledIOC[+T <: Data](gen: T) extends Bundle +{ + val ready = Bool(INPUT) + val valid = Bool(OUTPUT) + val bits = gen.cloneType.asOutput +} + +/** An I/O Bundle for Queues + * @param gen The type of data to queue + * @param entries The max number of entries in the queue */ +class QueueIO[T <: Data](gen: T, entries: Int) extends Bundle +{ + /** I/O to enqueue data, is [[Chisel.DecoupledIO]] flipped */ + val enq = Decoupled(gen.cloneType).flip() + /** I/O to enqueue data, is [[Chisel.DecoupledIO]]*/ + val deq = Decoupled(gen.cloneType) + /** The current amount of data in the queue */ + val count = UInt(OUTPUT, log2Up(entries + 1)) +} + +/** A hardware module implementing a Queue + * @param gen The type of data to queue + * @param entries The max number of entries in the queue + * @param pipe True if a single entry queue can run at full throughput (like a pipeline). The ''ready'' signals are + * combinationally coupled. + * @param flow True if the inputs can be consumed on the same cycle (the inputs "flow" through the queue immediately). + * The ''valid'' signals are coupled. + * + * Example usage: + * {{{ val q = new Queue(UInt(), 16) + * q.io.enq <> producer.io.out + * consumer.io.in <> q.io.deq }}} + */ +class Queue[T <: Data](gen: T, val entries: Int, + pipe: Boolean = false, + flow: Boolean = false, + override_reset: Option[Bool] = None) +extends Module(override_reset=override_reset) { + def this(gen: T, entries: Int, pipe: Boolean, flow: Boolean, _reset: Bool) = + this(gen, entries, pipe, flow, Some(_reset)) + + val io = new QueueIO(gen, entries) + + val ram = Mem(entries, gen) + val enq_ptr = Counter(entries) + val deq_ptr = Counter(entries) + val maybe_full = Reg(init=Bool(false)) + + val ptr_match = enq_ptr.value === deq_ptr.value + val empty = ptr_match && !maybe_full + val full = ptr_match && maybe_full + val do_enq = Wire(init=io.enq.fire()) + val do_deq = Wire(init=io.deq.fire()) + + when (do_enq) { + ram(enq_ptr.value) := io.enq.bits + enq_ptr.inc() + } + when (do_deq) { + deq_ptr.inc() + } + when (do_enq != do_deq) { + maybe_full := do_enq + } + + io.deq.valid := !empty + io.enq.ready := !full + io.deq.bits := ram(deq_ptr.value) + + if (flow) { + when (io.enq.valid) { io.deq.valid := Bool(true) } + when (empty) { + io.deq.bits := io.enq.bits + do_deq := Bool(false) + when (io.deq.ready) { do_enq := Bool(false) } + } + } + + if (pipe) { + when (io.deq.ready) { io.enq.ready := Bool(true) } + } + + val ptr_diff = enq_ptr.value - deq_ptr.value + if (isPow2(entries)) { + io.count := Cat(maybe_full && ptr_match, ptr_diff) + } else { + io.count := Mux(ptr_match, + Mux(maybe_full, + UInt(entries), UInt(0)), + Mux(deq_ptr.value > enq_ptr.value, + UInt(entries) + ptr_diff, ptr_diff)) + } +} + +/** Generic hardware queue. Required parameter entries controls + the depth of the queues. The width of the queue is determined + from the inputs. + + Example usage: + {{{ val q = Queue(Decoupled(UInt()), 16) + q.io.enq <> producer.io.out + consumer.io.in <> q.io.deq }}} + */ +object Queue +{ + def apply[T <: Data](enq: DecoupledIO[T], entries: Int = 2, pipe: Boolean = false): DecoupledIO[T] = { + val q = Module(new Queue(enq.bits.cloneType, entries, pipe)) + q.io.enq.valid := enq.valid // not using <> so that override is allowed + q.io.enq.bits := enq.bits + enq.ready := q.io.enq.ready + TransitName(q.io.deq, q) + } +} diff --git a/src/main/scala/chisel/util/Enum.scala b/src/main/scala/chisel/util/Enum.scala new file mode 100644 index 00000000..2757a06c --- /dev/null +++ b/src/main/scala/chisel/util/Enum.scala @@ -0,0 +1,21 @@ +// See LICENSE for license details. + +/** Enum generators, allowing circuit constants to have more meaningful names. + */ + +package chisel + +object Enum { + /** Returns a sequence of Bits subtypes with values from 0 until n. Helper method. */ + private def createValues[T <: Bits](nodeType: T, n: Int): Seq[T] = + (0 until n).map(x => nodeType.fromInt(x, log2Up(n))) + + /** create n enum values of given type */ + def apply[T <: Bits](nodeType: T, n: Int): List[T] = createValues(nodeType, n).toList + + /** create enum values of given type and names */ + def apply[T <: Bits](nodeType: T, l: Symbol *): Map[Symbol, T] = (l zip createValues(nodeType, l.length)).toMap + + /** create enum values of given type and names */ + def apply[T <: Bits](nodeType: T, l: List[Symbol]): Map[Symbol, T] = (l zip createValues(nodeType, l.length)).toMap +} diff --git a/src/main/scala/chisel/util/LFSR.scala b/src/main/scala/chisel/util/LFSR.scala new file mode 100644 index 00000000..1befb8ca --- /dev/null +++ b/src/main/scala/chisel/util/LFSR.scala @@ -0,0 +1,22 @@ +// See LICENSE for license details. + +/** LFSRs in all shapes and sizes. + */ + +package chisel + +// scalastyle:off magic.number +/** linear feedback shift register + */ +object LFSR16 +{ + def apply(increment: Bool = Bool(true)): UInt = + { + val width = 16 + val lfsr = Reg(init=UInt(1, width)) + when (increment) { lfsr := Cat(lfsr(0)^lfsr(2)^lfsr(3)^lfsr(5), lfsr(width-1,1)) } + lfsr + } +} +// scalastyle:on magic.number + diff --git a/src/main/scala/chisel/util/Lookup.scala b/src/main/scala/chisel/util/Lookup.scala new file mode 100644 index 00000000..1fdfd6ae --- /dev/null +++ b/src/main/scala/chisel/util/Lookup.scala @@ -0,0 +1,17 @@ +// See LICENSE for license details. + +package chisel + +object ListLookup { + def apply[T <: Data](addr: UInt, default: List[T], mapping: Array[(BitPat, List[T])]): List[T] = { + val map = mapping.map(m => (m._1 === addr, m._2)) + default.zipWithIndex map { case (d, i) => + map.foldRight(d)((m, n) => Mux(m._1, m._2(i), n)) + } + } +} + +object Lookup { + def apply[T <: Bits](addr: UInt, default: T, mapping: Seq[(BitPat, T)]): T = + ListLookup(addr, List(default), mapping.map(m => (m._1, List(m._2))).toArray).head +} diff --git a/src/main/scala/chisel/util/Math.scala b/src/main/scala/chisel/util/Math.scala new file mode 100644 index 00000000..1bf667ce --- /dev/null +++ b/src/main/scala/chisel/util/Math.scala @@ -0,0 +1,42 @@ +// See LICENSE for license details. + +/** Scala-land math helper functions, like logs. + */ + +package chisel + +/** Compute the log2 rounded up with min value of 1 */ +object log2Up { + def apply(in: BigInt): Int = { + require(in >= 0) + 1 max (in-1).bitLength + } + def apply(in: Int): Int = apply(BigInt(in)) +} + +/** Compute the log2 rounded up */ +object log2Ceil { + def apply(in: BigInt): Int = { + require(in > 0) + (in-1).bitLength + } + def apply(in: Int): Int = apply(BigInt(in)) +} + +/** Compute the log2 rounded down with min value of 1 */ +object log2Down { + def apply(in: BigInt): Int = log2Up(in) - (if (isPow2(in)) 0 else 1) + def apply(in: Int): Int = apply(BigInt(in)) +} + +/** Compute the log2 rounded down */ +object log2Floor { + def apply(in: BigInt): Int = log2Ceil(in) - (if (isPow2(in)) 0 else 1) + def apply(in: Int): Int = apply(BigInt(in)) +} + +/** Check if an Integer is a power of 2 */ +object isPow2 { + def apply(in: BigInt): Boolean = in > 0 && ((in & (in-1)) == 0) + def apply(in: Int): Boolean = apply(BigInt(in)) +} diff --git a/src/main/scala/chisel/util/Mux.scala b/src/main/scala/chisel/util/Mux.scala new file mode 100644 index 00000000..97467240 --- /dev/null +++ b/src/main/scala/chisel/util/Mux.scala @@ -0,0 +1,61 @@ +// See LICENSE for license details. + +/** Mux circuit generators. + */ + +package chisel + +/** Builds a Mux tree out of the input signal vector using a one hot encoded + select signal. Returns the output of the Mux tree. + */ +object Mux1H +{ + def apply[T <: Data](sel: Seq[Bool], in: Seq[T]): T = + apply(sel zip in) + def apply[T <: Data](in: Iterable[(Bool, T)]): T = SeqUtils.oneHotMux(in) + def apply[T <: Data](sel: UInt, in: Seq[T]): T = + apply((0 until in.size).map(sel(_)), in) + def apply(sel: UInt, in: UInt): Bool = (sel & in).orR +} + +/** Builds a Mux tree under the assumption that multiple select signals + can be enabled. Priority is given to the first select signal. + + Returns the output of the Mux tree. + */ +object PriorityMux +{ + def apply[T <: Data](in: Seq[(Bool, T)]): T = SeqUtils.priorityMux(in) + def apply[T <: Data](sel: Seq[Bool], in: Seq[T]): T = apply(sel zip in) + def apply[T <: Data](sel: Bits, in: Seq[T]): T = apply((0 until in.size).map(sel(_)), in) +} + +/** MuxLookup creates a cascade of n Muxs to search for a key value */ +object MuxLookup { + /** @param key a key to search for + * @param default a default value if nothing is found + * @param mapping a sequence to search of keys and values + * @return the value found or the default if not + */ + def apply[S <: UInt, T <: Bits] (key: S, default: T, mapping: Seq[(S, T)]): T = { + var res = default + for ((k, v) <- mapping.reverse) + res = Mux(k === key, v, res) + res + } + +} + +/** MuxCase returns the first value that is enabled in a map of values */ +object MuxCase { + /** @param default the default value if none are enabled + * @param mapping a set of data values with associated enables + * @return the first value in mapping that is enabled */ + def apply[T <: Bits] (default: T, mapping: Seq[(Bool, T)]): T = { + var res = default + for ((t, v) <- mapping.reverse){ + res = Mux(t, v, res) + } + res + } +} diff --git a/src/main/scala/chisel/util/OneHot.scala b/src/main/scala/chisel/util/OneHot.scala new file mode 100644 index 00000000..5d1de1a7 --- /dev/null +++ b/src/main/scala/chisel/util/OneHot.scala @@ -0,0 +1,62 @@ +// See LICENSE for license details. + +/** Circuit generators for working with one-hot representations. + */ + +package chisel + +/** Converts from One Hot Encoding to a UInt indicating which bit is active + * This is the inverse of [[Chisel.UIntToOH UIntToOH]]*/ +object OHToUInt { + def apply(in: Seq[Bool]): UInt = apply(Vec(in)) + def apply(in: Vec[Bool]): UInt = apply(in.toBits, in.size) + def apply(in: Bits): UInt = apply(in, in.getWidth) + + def apply(in: Bits, width: Int): UInt = { + if (width <= 2) { + Log2(in, width) + } else { + val mid = 1 << (log2Up(width)-1) + val hi = in(width-1, mid) + val lo = in(mid-1, 0) + Cat(hi.orR, apply(hi | lo, mid)) + } + } +} + +/** @return the bit position of the trailing 1 in the input vector + * with the assumption that multiple bits of the input bit vector can be set + * @example {{{ data_out := PriorityEncoder(data_in) }}} + */ +object PriorityEncoder { + def apply(in: Seq[Bool]): UInt = PriorityMux(in, (0 until in.size).map(UInt(_))) + def apply(in: Bits): UInt = apply(in.toBools) +} + +/** Returns the one hot encoding of the input UInt. + */ +object UIntToOH +{ + def apply(in: UInt, width: Int = -1): UInt = + if (width == -1) { + UInt(1) << in + } else { + (UInt(1) << in(log2Up(width)-1,0))(width-1,0) + } +} + +/** Returns a bit vector in which only the least-significant 1 bit in + the input vector, if any, is set. + */ +object PriorityEncoderOH +{ + private def encode(in: Seq[Bool]): UInt = { + val outs = Seq.tabulate(in.size)(i => UInt(BigInt(1) << i, in.size)) + PriorityMux(in :+ Bool(true), outs :+ UInt(0, in.size)) + } + def apply(in: Seq[Bool]): Seq[Bool] = { + val enc = encode(in) + Seq.tabulate(in.size)(enc(_)) + } + def apply(in: Bits): UInt = encode((0 until in.getWidth).map(i => in(i))) +} diff --git a/src/main/scala/chisel/util/Reg.scala b/src/main/scala/chisel/util/Reg.scala new file mode 100644 index 00000000..1808af76 --- /dev/null +++ b/src/main/scala/chisel/util/Reg.scala @@ -0,0 +1,55 @@ +// See LICENSE for license details. + +/** Variations and helpers for registers. + */ + +package chisel + +object RegNext { + + def apply[T <: Data](next: T): T = Reg[T](null.asInstanceOf[T], next, null.asInstanceOf[T]) + + def apply[T <: Data](next: T, init: T): T = Reg[T](null.asInstanceOf[T], next, init) + +} + +object RegInit { + + def apply[T <: Data](init: T): T = Reg[T](null.asInstanceOf[T], null.asInstanceOf[T], init) + +} + +/** A register with an Enable signal */ +object RegEnable +{ + def apply[T <: Data](updateData: T, enable: Bool): T = { + val r = Reg(updateData) + when (enable) { r := updateData } + r + } + def apply[T <: Data](updateData: T, resetData: T, enable: Bool): T = { + val r = RegInit(resetData) + when (enable) { r := updateData } + r + } +} + +/** Returns the n-cycle delayed version of the input signal. + */ +object ShiftRegister +{ + /** @param in input to delay + * @param n number of cycles to delay + * @param en enable the shift */ + def apply[T <: Data](in: T, n: Int, en: Bool = Bool(true)): T = + { + // The order of tests reflects the expected use cases. + if (n == 1) { + RegEnable(in, en) + } else if (n != 0) { + RegNext(apply(in, n-1, en)) + } else { + in + } + } +} diff --git a/src/main/scala/chisel/util/TransitName.scala b/src/main/scala/chisel/util/TransitName.scala new file mode 100644 index 00000000..141b10bc --- /dev/null +++ b/src/main/scala/chisel/util/TransitName.scala @@ -0,0 +1,21 @@ +package chisel + +import internal.HasId + +object TransitName { + // The purpose of this is to allow a library to 'move' a name call to a more + // appropriate place. + // For example, a library factory function may create a module and return + // the io. The only user-exposed field is that given IO, which can't use + // any name supplied by the user. This can add a hook so that the supplied + // name then names the Module. + // See Queue companion object for working example + def apply[T<:HasId](from: T, to: HasId): T = { + from.addPostnameHook((given_name: String) => {to.suggestName(given_name)}) + from + } + def withSuffix[T<:HasId](suffix: String)(from: T, to: HasId): T = { + from.addPostnameHook((given_name: String) => {to.suggestName(given_name+suffix)}) + from + } +} diff --git a/src/main/scala/chisel/util/Valid.scala b/src/main/scala/chisel/util/Valid.scala new file mode 100644 index 00000000..cffed0a7 --- /dev/null +++ b/src/main/scala/chisel/util/Valid.scala @@ -0,0 +1,59 @@ +// See LICENSE for license details. + +/** Wrappers for valid interfaces and associated circuit generators using them. + */ + +package chisel + +/** An I/O Bundle containing data and a signal determining if it is valid */ +class ValidIO[+T <: Data](gen2: T) extends Bundle +{ + val valid = Bool(OUTPUT) + val bits = gen2.cloneType.asOutput + def fire(dummy: Int = 0): Bool = valid + override def cloneType: this.type = new ValidIO(gen2).asInstanceOf[this.type] +} + +/** Adds a valid protocol to any interface. The standard used is + that the consumer uses the flipped interface. +*/ +object Valid { + def apply[T <: Data](gen: T): ValidIO[T] = new ValidIO(gen) +} + +/** A hardware module that delays data coming down the pipeline + by the number of cycles set by the latency parameter. Functionality + is similar to ShiftRegister but this exposes a Pipe interface. + + Example usage: + val pipe = new Pipe(UInt()) + pipe.io.enq <> produce.io.out + consumer.io.in <> pipe.io.deq + */ +object Pipe +{ + def apply[T <: Data](enqValid: Bool, enqBits: T, latency: Int): ValidIO[T] = { + if (latency == 0) { + val out = Wire(Valid(enqBits)) + out.valid <> enqValid + out.bits <> enqBits + out + } else { + val v = Reg(Bool(), next=enqValid, init=Bool(false)) + val b = RegEnable(enqBits, enqValid) + apply(v, b, latency-1) + } + } + def apply[T <: Data](enqValid: Bool, enqBits: T): ValidIO[T] = apply(enqValid, enqBits, 1) + def apply[T <: Data](enq: ValidIO[T], latency: Int = 1): ValidIO[T] = apply(enq.valid, enq.bits, latency) +} + +class Pipe[T <: Data](gen: T, latency: Int = 1) extends Module +{ + val io = new Bundle { + val enq = Valid(gen).flip + val deq = Valid(gen) + } + + io.deq <> Pipe(io.enq, latency) +} -- cgit v1.2.3 From 65df106578e12e8bd71f9775e0435bbe107ee4da Mon Sep 17 00:00:00 2001 From: ducky Date: Fri, 20 May 2016 18:25:22 -0700 Subject: Rename Chisel -> chisel in tests --- src/test/scala/chiselTests/Assert.scala | 4 ++-- src/test/scala/chiselTests/BitwiseOps.scala | 4 ++-- src/test/scala/chiselTests/BlackBox.scala | 4 ++-- src/test/scala/chiselTests/BundleWire.scala | 4 ++-- src/test/scala/chiselTests/ChiselSpec.scala | 4 ++-- src/test/scala/chiselTests/ComplexAssign.scala | 4 ++-- src/test/scala/chiselTests/Counter.scala | 4 ++-- src/test/scala/chiselTests/Decoder.scala | 4 ++-- src/test/scala/chiselTests/DeqIOSpec.scala | 4 ++-- src/test/scala/chiselTests/Direction.scala | 4 ++-- src/test/scala/chiselTests/EnableShiftRegister.scala | 4 ++-- src/test/scala/chiselTests/GCD.scala | 4 ++-- src/test/scala/chiselTests/Harness.scala | 5 +++-- src/test/scala/chiselTests/LFSR16.scala | 5 +++-- src/test/scala/chiselTests/MemorySearch.scala | 5 +++-- src/test/scala/chiselTests/Module.scala | 3 ++- src/test/scala/chiselTests/MulLookup.scala | 4 ++-- src/test/scala/chiselTests/MultiAssign.scala | 4 ++-- src/test/scala/chiselTests/OptionBundle.scala | 4 ++-- src/test/scala/chiselTests/Padding.scala | 3 ++- src/test/scala/chiselTests/ParameterizedModule.scala | 4 ++-- src/test/scala/chiselTests/Printf.scala | 4 ++-- src/test/scala/chiselTests/Reg.scala | 4 ++-- src/test/scala/chiselTests/Risc.scala | 3 ++- src/test/scala/chiselTests/SIntOps.scala | 5 +++-- src/test/scala/chiselTests/Stack.scala | 3 ++- src/test/scala/chiselTests/Stop.scala | 4 ++-- src/test/scala/chiselTests/Tbl.scala | 4 ++-- src/test/scala/chiselTests/TesterDriverSpec.scala | 4 ++-- src/test/scala/chiselTests/UIntOps.scala | 5 +++-- src/test/scala/chiselTests/Vec.scala | 4 ++-- src/test/scala/chiselTests/VectorPacketIO.scala | 4 ++-- src/test/scala/chiselTests/VendingMachine.scala | 3 ++- src/test/scala/chiselTests/When.scala | 4 ++-- 34 files changed, 73 insertions(+), 63 deletions(-) diff --git a/src/test/scala/chiselTests/Assert.scala b/src/test/scala/chiselTests/Assert.scala index 24eb8b55..eccf98e1 100644 --- a/src/test/scala/chiselTests/Assert.scala +++ b/src/test/scala/chiselTests/Assert.scala @@ -3,8 +3,8 @@ package chiselTests import org.scalatest._ -import Chisel._ -import Chisel.testers.BasicTester +import chisel._ +import chisel.testers.BasicTester class FailingAssertTester() extends BasicTester { assert(Bool(false)) diff --git a/src/test/scala/chiselTests/BitwiseOps.scala b/src/test/scala/chiselTests/BitwiseOps.scala index 19aa956c..0c1d4d74 100644 --- a/src/test/scala/chiselTests/BitwiseOps.scala +++ b/src/test/scala/chiselTests/BitwiseOps.scala @@ -2,10 +2,10 @@ package chiselTests -import Chisel._ +import chisel._ import org.scalatest._ import org.scalatest.prop._ -import Chisel.testers.BasicTester +import chisel.testers.BasicTester class BitwiseOpsTester(w: Int, _a: Int, _b: Int) extends BasicTester { val mask = (1 << w) - 1 diff --git a/src/test/scala/chiselTests/BlackBox.scala b/src/test/scala/chiselTests/BlackBox.scala index ca94087c..962a9db1 100644 --- a/src/test/scala/chiselTests/BlackBox.scala +++ b/src/test/scala/chiselTests/BlackBox.scala @@ -4,8 +4,8 @@ package chiselTests import java.io.File import org.scalatest._ -import Chisel._ -import Chisel.testers.BasicTester +import chisel._ +import chisel.testers.BasicTester class BlackBoxInverter extends BlackBox { val io = new Bundle() { diff --git a/src/test/scala/chiselTests/BundleWire.scala b/src/test/scala/chiselTests/BundleWire.scala index d2e42fa9..36dbb365 100644 --- a/src/test/scala/chiselTests/BundleWire.scala +++ b/src/test/scala/chiselTests/BundleWire.scala @@ -1,10 +1,10 @@ // See LICENSE for license details. package chiselTests -import Chisel._ +import chisel._ import org.scalatest._ import org.scalatest.prop._ -import Chisel.testers.BasicTester +import chisel.testers.BasicTester class Coord extends Bundle { val x = UInt(width = 32) diff --git a/src/test/scala/chiselTests/ChiselSpec.scala b/src/test/scala/chiselTests/ChiselSpec.scala index da68b0cb..9c66b0db 100644 --- a/src/test/scala/chiselTests/ChiselSpec.scala +++ b/src/test/scala/chiselTests/ChiselSpec.scala @@ -6,8 +6,8 @@ import java.io.File import org.scalatest._ import org.scalatest.prop._ import org.scalacheck._ -import Chisel._ -import Chisel.testers._ +import chisel._ +import chisel.testers._ /** Common utility functions for Chisel unit tests. */ trait ChiselRunners extends Assertions { diff --git a/src/test/scala/chiselTests/ComplexAssign.scala b/src/test/scala/chiselTests/ComplexAssign.scala index d79a2625..8f79f76d 100644 --- a/src/test/scala/chiselTests/ComplexAssign.scala +++ b/src/test/scala/chiselTests/ComplexAssign.scala @@ -1,11 +1,11 @@ // See LICENSE for license details. package chiselTests -import Chisel._ +import chisel._ import org.scalatest._ import org.scalatest.prop._ -import Chisel.testers.BasicTester +import chisel.testers.BasicTester class Complex[T <: Data](val re: T, val im: T) extends Bundle { override def cloneType: this.type = diff --git a/src/test/scala/chiselTests/Counter.scala b/src/test/scala/chiselTests/Counter.scala index 07a76cdc..cbc80b86 100644 --- a/src/test/scala/chiselTests/Counter.scala +++ b/src/test/scala/chiselTests/Counter.scala @@ -1,10 +1,10 @@ // See LICENSE for license details. package chiselTests -import Chisel._ +import chisel._ import org.scalatest._ import org.scalatest.prop._ -import Chisel.testers.BasicTester +import chisel.testers.BasicTester class CountTester(max: Int) extends BasicTester { val cnt = Counter(max) diff --git a/src/test/scala/chiselTests/Decoder.scala b/src/test/scala/chiselTests/Decoder.scala index e5cdfd07..1e6e7648 100644 --- a/src/test/scala/chiselTests/Decoder.scala +++ b/src/test/scala/chiselTests/Decoder.scala @@ -1,11 +1,11 @@ // See LICENSE for license details. package chiselTests -import Chisel._ +import chisel._ import org.scalatest._ import org.scalatest.prop._ import org.scalacheck._ -import Chisel.testers.BasicTester +import chisel.testers.BasicTester class Decoder(bitpats: List[String]) extends Module { val io = new Bundle { diff --git a/src/test/scala/chiselTests/DeqIOSpec.scala b/src/test/scala/chiselTests/DeqIOSpec.scala index 8f7937ab..9fd47ab0 100644 --- a/src/test/scala/chiselTests/DeqIOSpec.scala +++ b/src/test/scala/chiselTests/DeqIOSpec.scala @@ -2,8 +2,8 @@ package chiselTests -import Chisel._ -import Chisel.testers.BasicTester +import chisel._ +import chisel.testers.BasicTester /** * Created by chick on 2/8/16. diff --git a/src/test/scala/chiselTests/Direction.scala b/src/test/scala/chiselTests/Direction.scala index dd2f6572..3ed543aa 100644 --- a/src/test/scala/chiselTests/Direction.scala +++ b/src/test/scala/chiselTests/Direction.scala @@ -2,10 +2,10 @@ package chiselTests -import Chisel._ +import chisel._ import org.scalatest._ import org.scalatest.prop._ -import Chisel.testers.BasicTester +import chisel.testers.BasicTester class DirectionHaver extends Module { val io = new Bundle { diff --git a/src/test/scala/chiselTests/EnableShiftRegister.scala b/src/test/scala/chiselTests/EnableShiftRegister.scala index 6600df2a..30fc2486 100644 --- a/src/test/scala/chiselTests/EnableShiftRegister.scala +++ b/src/test/scala/chiselTests/EnableShiftRegister.scala @@ -1,8 +1,8 @@ // See LICENSE for license details. package chiselTests -import Chisel._ -import Chisel.testers.BasicTester +import chisel._ +import chisel.testers.BasicTester class EnableShiftRegister extends Module { val io = new Bundle { diff --git a/src/test/scala/chiselTests/GCD.scala b/src/test/scala/chiselTests/GCD.scala index a1bfffda..77452db6 100644 --- a/src/test/scala/chiselTests/GCD.scala +++ b/src/test/scala/chiselTests/GCD.scala @@ -2,8 +2,8 @@ package chiselTests -import Chisel._ -import Chisel.testers.BasicTester +import chisel._ +import chisel.testers.BasicTester import org.scalatest._ import org.scalatest.prop._ diff --git a/src/test/scala/chiselTests/Harness.scala b/src/test/scala/chiselTests/Harness.scala index bc838766..805e2de9 100644 --- a/src/test/scala/chiselTests/Harness.scala +++ b/src/test/scala/chiselTests/Harness.scala @@ -1,13 +1,14 @@ // See LICENSE for license details. package chiselTests -import Chisel.testers.BasicTester + +import chisel.testers.BasicTester import org.scalatest._ import org.scalatest.prop._ import java.io.File class HarnessSpec extends ChiselPropSpec - with Chisel.BackendCompilationUtilities { + with chisel.BackendCompilationUtilities { def makeTrivialVerilog: (File => File) = makeHarness((prefix: String) => s""" module ${prefix}; diff --git a/src/test/scala/chiselTests/LFSR16.scala b/src/test/scala/chiselTests/LFSR16.scala index ed76a296..42024a3f 100644 --- a/src/test/scala/chiselTests/LFSR16.scala +++ b/src/test/scala/chiselTests/LFSR16.scala @@ -1,8 +1,9 @@ // See LICENSE for license details. package chiselTests -import Chisel._ -import Chisel.testers.BasicTester + +import chisel._ +import chisel.testers.BasicTester class LFSR16 extends Module { val io = new Bundle { diff --git a/src/test/scala/chiselTests/MemorySearch.scala b/src/test/scala/chiselTests/MemorySearch.scala index 55b704a0..b48d2881 100644 --- a/src/test/scala/chiselTests/MemorySearch.scala +++ b/src/test/scala/chiselTests/MemorySearch.scala @@ -1,8 +1,9 @@ // See LICENSE for license details. package chiselTests -import Chisel._ -import Chisel.testers.BasicTester + +import chisel._ +import chisel.testers.BasicTester class MemorySearch extends Module { val io = new Bundle { diff --git a/src/test/scala/chiselTests/Module.scala b/src/test/scala/chiselTests/Module.scala index 88ba795b..64b00fab 100644 --- a/src/test/scala/chiselTests/Module.scala +++ b/src/test/scala/chiselTests/Module.scala @@ -1,7 +1,8 @@ // See LICENSE for license details. package chiselTests -import Chisel._ + +import chisel._ class SimpleIO extends Bundle { val in = UInt(INPUT, 32) diff --git a/src/test/scala/chiselTests/MulLookup.scala b/src/test/scala/chiselTests/MulLookup.scala index 49ba13c7..5e223f91 100644 --- a/src/test/scala/chiselTests/MulLookup.scala +++ b/src/test/scala/chiselTests/MulLookup.scala @@ -2,10 +2,10 @@ package chiselTests -import Chisel._ +import chisel._ import org.scalatest._ import org.scalatest.prop._ -import Chisel.testers.BasicTester +import chisel.testers.BasicTester class MulLookup(val w: Int) extends Module { val io = new Bundle { diff --git a/src/test/scala/chiselTests/MultiAssign.scala b/src/test/scala/chiselTests/MultiAssign.scala index 2f464123..ff3bc7a5 100644 --- a/src/test/scala/chiselTests/MultiAssign.scala +++ b/src/test/scala/chiselTests/MultiAssign.scala @@ -3,8 +3,8 @@ package chiselTests import org.scalatest._ -import Chisel._ -import Chisel.testers.BasicTester +import chisel._ +import chisel.testers.BasicTester class LastAssignTester() extends BasicTester { val cnt = Counter(2) diff --git a/src/test/scala/chiselTests/OptionBundle.scala b/src/test/scala/chiselTests/OptionBundle.scala index c5a347e6..ab3b6860 100644 --- a/src/test/scala/chiselTests/OptionBundle.scala +++ b/src/test/scala/chiselTests/OptionBundle.scala @@ -3,8 +3,8 @@ package chiselTests import org.scalatest._ -import Chisel._ -import Chisel.testers.BasicTester +import chisel._ +import chisel.testers.BasicTester class OptionBundle(hasIn: Boolean) extends Bundle { val in = if (hasIn) { diff --git a/src/test/scala/chiselTests/Padding.scala b/src/test/scala/chiselTests/Padding.scala index 999b7d36..03496649 100644 --- a/src/test/scala/chiselTests/Padding.scala +++ b/src/test/scala/chiselTests/Padding.scala @@ -1,7 +1,8 @@ // See LICENSE for license details. package chiselTests -import Chisel._ + +import chisel._ class Padder extends Module { val io = new Bundle { diff --git a/src/test/scala/chiselTests/ParameterizedModule.scala b/src/test/scala/chiselTests/ParameterizedModule.scala index 35e3ba78..e2629224 100644 --- a/src/test/scala/chiselTests/ParameterizedModule.scala +++ b/src/test/scala/chiselTests/ParameterizedModule.scala @@ -3,8 +3,8 @@ package chiselTests import org.scalatest._ -import Chisel._ -import Chisel.testers.BasicTester +import chisel._ +import chisel.testers.BasicTester class ParameterizedModule(invert: Boolean) extends Module { val io = new Bundle { diff --git a/src/test/scala/chiselTests/Printf.scala b/src/test/scala/chiselTests/Printf.scala index eb8b4b25..b5e1e66e 100644 --- a/src/test/scala/chiselTests/Printf.scala +++ b/src/test/scala/chiselTests/Printf.scala @@ -3,8 +3,8 @@ package chiselTests import org.scalatest._ -import Chisel._ -import Chisel.testers.BasicTester +import chisel._ +import chisel.testers.BasicTester class SinglePrintfTester() extends BasicTester { val x = UInt(254) diff --git a/src/test/scala/chiselTests/Reg.scala b/src/test/scala/chiselTests/Reg.scala index f2620d88..8954c3ef 100644 --- a/src/test/scala/chiselTests/Reg.scala +++ b/src/test/scala/chiselTests/Reg.scala @@ -3,8 +3,8 @@ package chiselTests import org.scalatest._ -import Chisel._ -import Chisel.testers.BasicTester +import chisel._ +import chisel.testers.BasicTester class RegSpec extends ChiselFlatSpec { "A Reg" should "throw an exception if not given any parameters" in { diff --git a/src/test/scala/chiselTests/Risc.scala b/src/test/scala/chiselTests/Risc.scala index 3daa5bd2..6b0742ae 100644 --- a/src/test/scala/chiselTests/Risc.scala +++ b/src/test/scala/chiselTests/Risc.scala @@ -1,7 +1,8 @@ // See LICENSE for license details. package chiselTests -import Chisel._ + +import chisel._ class Risc extends Module { val io = new Bundle { diff --git a/src/test/scala/chiselTests/SIntOps.scala b/src/test/scala/chiselTests/SIntOps.scala index 0835fb4d..07111af6 100644 --- a/src/test/scala/chiselTests/SIntOps.scala +++ b/src/test/scala/chiselTests/SIntOps.scala @@ -1,8 +1,9 @@ // See LICENSE for license details. package chiselTests -import Chisel._ -import Chisel.testers.BasicTester + +import chisel._ +import chisel.testers.BasicTester class SIntOps extends Module { val io = new Bundle { diff --git a/src/test/scala/chiselTests/Stack.scala b/src/test/scala/chiselTests/Stack.scala index ac799c8a..53c57b5b 100644 --- a/src/test/scala/chiselTests/Stack.scala +++ b/src/test/scala/chiselTests/Stack.scala @@ -1,8 +1,9 @@ // See LICENSE for license details. package chiselTests + import scala.collection.mutable.Stack -import Chisel._ +import chisel._ class ChiselStack(val depth: Int) extends Module { val io = new Bundle { diff --git a/src/test/scala/chiselTests/Stop.scala b/src/test/scala/chiselTests/Stop.scala index 878f090c..d57eb7c6 100644 --- a/src/test/scala/chiselTests/Stop.scala +++ b/src/test/scala/chiselTests/Stop.scala @@ -3,8 +3,8 @@ package chiselTests import org.scalatest._ -import Chisel._ -import Chisel.testers.BasicTester +import chisel._ +import chisel.testers.BasicTester class StopTester() extends BasicTester { stop() diff --git a/src/test/scala/chiselTests/Tbl.scala b/src/test/scala/chiselTests/Tbl.scala index c79eb8a4..918f9158 100644 --- a/src/test/scala/chiselTests/Tbl.scala +++ b/src/test/scala/chiselTests/Tbl.scala @@ -2,10 +2,10 @@ package chiselTests -import Chisel._ +import chisel._ import org.scalatest._ import org.scalatest.prop._ -import Chisel.testers.BasicTester +import chisel.testers.BasicTester class Tbl(w: Int, n: Int) extends Module { val io = new Bundle { diff --git a/src/test/scala/chiselTests/TesterDriverSpec.scala b/src/test/scala/chiselTests/TesterDriverSpec.scala index 3c57daae..e6b5bc1f 100644 --- a/src/test/scala/chiselTests/TesterDriverSpec.scala +++ b/src/test/scala/chiselTests/TesterDriverSpec.scala @@ -2,8 +2,8 @@ package chiselTests -import Chisel._ -import Chisel.testers.BasicTester +import chisel._ +import chisel.testers.BasicTester /** Extend BasicTester with a simple circuit and finish method. TesterDriver will call the * finish method after the FinishTester's constructor has completed, which will alter the diff --git a/src/test/scala/chiselTests/UIntOps.scala b/src/test/scala/chiselTests/UIntOps.scala index bb0b0f06..8b2a31fd 100644 --- a/src/test/scala/chiselTests/UIntOps.scala +++ b/src/test/scala/chiselTests/UIntOps.scala @@ -1,9 +1,10 @@ // See LICENSE for license details. package chiselTests -import Chisel._ + +import chisel._ import org.scalatest._ -import Chisel.testers.BasicTester +import chisel.testers.BasicTester class UIntOps extends Module { val io = new Bundle { diff --git a/src/test/scala/chiselTests/Vec.scala b/src/test/scala/chiselTests/Vec.scala index 943d9e4b..e35c765e 100644 --- a/src/test/scala/chiselTests/Vec.scala +++ b/src/test/scala/chiselTests/Vec.scala @@ -2,10 +2,10 @@ package chiselTests -import Chisel._ +import chisel._ import org.scalatest._ import org.scalatest.prop._ -import Chisel.testers.BasicTester +import chisel.testers.BasicTester class ValueTester(w: Int, values: List[Int]) extends BasicTester { val v = Vec(values.map(UInt(_, width = w))) // TODO: does this need a Wire? Why no error? diff --git a/src/test/scala/chiselTests/VectorPacketIO.scala b/src/test/scala/chiselTests/VectorPacketIO.scala index 99ec66a6..26e87360 100644 --- a/src/test/scala/chiselTests/VectorPacketIO.scala +++ b/src/test/scala/chiselTests/VectorPacketIO.scala @@ -2,8 +2,8 @@ package chiselTests -import Chisel._ -import Chisel.testers.BasicTester +import chisel._ +import chisel.testers.BasicTester /** * This test used to fail when assignment statements were diff --git a/src/test/scala/chiselTests/VendingMachine.scala b/src/test/scala/chiselTests/VendingMachine.scala index 012fc493..e11e48dd 100644 --- a/src/test/scala/chiselTests/VendingMachine.scala +++ b/src/test/scala/chiselTests/VendingMachine.scala @@ -1,7 +1,8 @@ // See LICENSE for license details. package chiselTests -import Chisel._ + +import chisel._ class VendingMachine extends Module { val io = new Bundle { diff --git a/src/test/scala/chiselTests/When.scala b/src/test/scala/chiselTests/When.scala index a6572706..a1bd7c31 100644 --- a/src/test/scala/chiselTests/When.scala +++ b/src/test/scala/chiselTests/When.scala @@ -3,8 +3,8 @@ package chiselTests import org.scalatest._ -import Chisel._ -import Chisel.testers.BasicTester +import chisel._ +import chisel.testers.BasicTester class WhenTester() extends BasicTester { val cnt = Counter(4) -- cgit v1.2.3 From 671117f3332ac10d1e7c5cc4f4cb5278f72ed6ab Mon Sep 17 00:00:00 2001 From: ducky Date: Fri, 20 May 2016 19:50:05 -0700 Subject: Add implicit xToLiteral, add Element, use internal package object --- src/main/scala/chisel/compatibility.scala | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/main/scala/chisel/compatibility.scala b/src/main/scala/chisel/compatibility.scala index 80936a42..fd45987b 100644 --- a/src/main/scala/chisel/compatibility.scala +++ b/src/main/scala/chisel/compatibility.scala @@ -26,6 +26,7 @@ package object Chisel { val BitPat = chisel.BitPat type BitPat = chisel.BitPat + type Element = chisel.Element type Bits = chisel.Bits val Bits = chisel.Bits type Num[T <: Data] = chisel.Num[T] @@ -64,6 +65,12 @@ package object Chisel { val throwException = chisel.throwException + object testers { + type BasicTester = chisel.testers.BasicTester + val TesterDriver = chisel.testers.TesterDriver + } + + val log2Up = chisel.log2Up val log2Ceil = chisel.log2Ceil val log2Down = chisel.log2Down @@ -129,11 +136,15 @@ package object Chisel { val Valid = chisel.Valid val Pipe = chisel.Pipe type Pipe[T <: Data] = chisel.Pipe[T] -} -package Chisel { - package object testers { - type BasicTester = chisel.testers.BasicTester - val TesterDriver = chisel.testers.TesterDriver - } + + import chisel.internal.firrtl.Width + implicit def fromBigIntToLiteral(x: BigInt): chisel.fromBigIntToLiteral = + new chisel.fromBigIntToLiteral(x) + implicit def fromIntToLiteral(x: Int): chisel.fromIntToLiteral= + new chisel.fromIntToLiteral(x) + implicit def fromStringToLiteral(x: String): chisel.fromStringToLiteral= + new chisel.fromStringToLiteral(x) + implicit def fromBooleanToLiteral(x: Boolean): chisel.fromBooleanToLiteral= + new chisel.fromBooleanToLiteral(x) } -- cgit v1.2.3 From 881ac3cb3a9da0c7827a161238468df4727996f0 Mon Sep 17 00:00:00 2001 From: ducky Date: Fri, 27 May 2016 13:24:36 -0700 Subject: Move utils into utils --- src/main/scala/chisel/compatibility.scala | 110 +++++++++++----------- src/main/scala/chisel/util/Arbiter.scala | 4 +- src/main/scala/chisel/util/Bitwise.scala | 4 +- src/main/scala/chisel/util/Cat.scala | 4 +- src/main/scala/chisel/util/CircuitMath.scala | 4 +- src/main/scala/chisel/util/Conditional.scala | 6 +- src/main/scala/chisel/util/Counter.scala | 4 +- src/main/scala/chisel/util/Decoupled.scala | 4 +- src/main/scala/chisel/util/Enum.scala | 4 +- src/main/scala/chisel/util/LFSR.scala | 4 +- src/main/scala/chisel/util/Lookup.scala | 4 +- src/main/scala/chisel/util/Math.scala | 4 +- src/main/scala/chisel/util/Mux.scala | 4 +- src/main/scala/chisel/util/OneHot.scala | 4 +- src/main/scala/chisel/util/Reg.scala | 4 +- src/main/scala/chisel/util/TransitName.scala | 3 +- src/main/scala/chisel/util/Valid.scala | 4 +- src/test/scala/chiselTests/Assert.scala | 1 + src/test/scala/chiselTests/BlackBox.scala | 2 + src/test/scala/chiselTests/ComplexAssign.scala | 4 +- src/test/scala/chiselTests/Counter.scala | 5 +- src/test/scala/chiselTests/Decoder.scala | 5 +- src/test/scala/chiselTests/DeqIOSpec.scala | 1 + src/test/scala/chiselTests/LFSR16.scala | 1 + src/test/scala/chiselTests/MultiAssign.scala | 2 + src/test/scala/chiselTests/Risc.scala | 1 + src/test/scala/chiselTests/Stack.scala | 2 + src/test/scala/chiselTests/Tbl.scala | 4 +- src/test/scala/chiselTests/TesterDriverSpec.scala | 1 + src/test/scala/chiselTests/Vec.scala | 4 +- src/test/scala/chiselTests/VectorPacketIO.scala | 1 + src/test/scala/chiselTests/VendingMachine.scala | 1 + src/test/scala/chiselTests/When.scala | 2 + 33 files changed, 135 insertions(+), 77 deletions(-) diff --git a/src/main/scala/chisel/compatibility.scala b/src/main/scala/chisel/compatibility.scala index fd45987b..9cdef80d 100644 --- a/src/main/scala/chisel/compatibility.scala +++ b/src/main/scala/chisel/compatibility.scala @@ -71,80 +71,80 @@ package object Chisel { } - val log2Up = chisel.log2Up - val log2Ceil = chisel.log2Ceil - val log2Down = chisel.log2Down - val log2Floor = chisel.log2Floor - val isPow2 = chisel.isPow2 + val log2Up = chisel.util.log2Up + val log2Ceil = chisel.util.log2Ceil + val log2Down = chisel.util.log2Down + val log2Floor = chisel.util.log2Floor + val isPow2 = chisel.util.isPow2 - type ArbiterIO[T <: Data] = chisel.ArbiterIO[T] - type LockingArbiterLike[T <: Data] = chisel.LockingArbiterLike[T] - type LockingRRArbiter[T <: Data] = chisel.LockingRRArbiter[T] - type LockingArbiter[T <: Data] = chisel.LockingArbiter[T] - type RRArbiter[T <: Data] = chisel.RRArbiter[T] - type Arbiter[T <: Data] = chisel.Arbiter[T] + type ArbiterIO[T <: Data] = chisel.util.ArbiterIO[T] + type LockingArbiterLike[T <: Data] = chisel.util.LockingArbiterLike[T] + type LockingRRArbiter[T <: Data] = chisel.util.LockingRRArbiter[T] + type LockingArbiter[T <: Data] = chisel.util.LockingArbiter[T] + type RRArbiter[T <: Data] = chisel.util.RRArbiter[T] + type Arbiter[T <: Data] = chisel.util.Arbiter[T] - val FillInterleaved = chisel.FillInterleaved - val PopCount = chisel.PopCount - val Fill = chisel.Fill - val Reverse = chisel.Reverse + val FillInterleaved = chisel.util.FillInterleaved + val PopCount = chisel.util.PopCount + val Fill = chisel.util.Fill + val Reverse = chisel.util.Reverse - val Cat = chisel.Cat + val Cat = chisel.util.Cat - val Log2 = chisel.Log2 + val Log2 = chisel.util.Log2 - val unless = chisel.unless - type SwitchContext[T <: Bits] = chisel.SwitchContext[T] - val is = chisel.is - val switch = chisel.switch + val unless = chisel.util.unless + type SwitchContext[T <: Bits] = chisel.util.SwitchContext[T] + val is = chisel.util.is + val switch = chisel.util.switch - type Counter = chisel.Counter - val Counter = chisel.Counter + type Counter = chisel.util.Counter + val Counter = chisel.util.Counter - type DecoupledIO[+T <: Data] = chisel.DecoupledIO[T] - val Decoupled = chisel.Decoupled - type EnqIO[T <: Data] = chisel.EnqIO[T] - type DeqIO[T <: Data] = chisel.DeqIO[T] - type DecoupledIOC[+T <: Data] = chisel.DecoupledIOC[T] - type QueueIO[T <: Data] = chisel.QueueIO[T] - type Queue[T <: Data] = chisel.Queue[T] - val Queue = chisel.Queue + type DecoupledIO[+T <: Data] = chisel.util.DecoupledIO[T] + val Decoupled = chisel.util.Decoupled + type EnqIO[T <: Data] = chisel.util.EnqIO[T] + type DeqIO[T <: Data] = chisel.util.DeqIO[T] + type DecoupledIOC[+T <: Data] = chisel.util.DecoupledIOC[T] + type QueueIO[T <: Data] = chisel.util.QueueIO[T] + type Queue[T <: Data] = chisel.util.Queue[T] + val Queue = chisel.util.Queue - val Enum = chisel.Enum + val Enum = chisel.util.Enum - val LFSR16 = chisel.LFSR16 + val LFSR16 = chisel.util.LFSR16 - val ListLookup = chisel.ListLookup - val Lookup = chisel.Lookup + val ListLookup = chisel.util.ListLookup + val Lookup = chisel.util.Lookup - val Mux1H = chisel.Mux1H - val PriorityMux = chisel.PriorityMux - val MuxLookup = chisel.MuxLookup - val MuxCase = chisel.MuxCase + val Mux1H = chisel.util.Mux1H + val PriorityMux = chisel.util.PriorityMux + val MuxLookup = chisel.util.MuxLookup + val MuxCase = chisel.util.MuxCase - val OHToUInt = chisel.OHToUInt - val PriorityEncoder = chisel.PriorityEncoder - val UIntToOH = chisel.UIntToOH - val PriorityEncoderOH = chisel.PriorityEncoderOH + val OHToUInt = chisel.util.OHToUInt + val PriorityEncoder = chisel.util.PriorityEncoder + val UIntToOH = chisel.util.UIntToOH + val PriorityEncoderOH = chisel.util.PriorityEncoderOH - val RegNext = chisel.RegNext - val RegInit = chisel.RegInit - val RegEnable = chisel.RegEnable - val ShiftRegister = chisel.ShiftRegister + val RegNext = chisel.util.RegNext + val RegInit = chisel.util.RegInit + val RegEnable = chisel.util.RegEnable + val ShiftRegister = chisel.util.ShiftRegister - type ValidIO[+T <: Data] = chisel.ValidIO[T] - val Valid = chisel.Valid - val Pipe = chisel.Pipe - type Pipe[T <: Data] = chisel.Pipe[T] + type ValidIO[+T <: Data] = chisel.util.ValidIO[T] + val Valid = chisel.util.Valid + val Pipe = chisel.util.Pipe + type Pipe[T <: Data] = chisel.util.Pipe[T] import chisel.internal.firrtl.Width - implicit def fromBigIntToLiteral(x: BigInt): chisel.fromBigIntToLiteral = + implicit def fromBigIntToLiteral(x: BigInt): chisel.fromBigIntToLiteral = new chisel.fromBigIntToLiteral(x) - implicit def fromIntToLiteral(x: Int): chisel.fromIntToLiteral= + implicit def fromIntToLiteral(x: Int): chisel.fromIntToLiteral= new chisel.fromIntToLiteral(x) - implicit def fromStringToLiteral(x: String): chisel.fromStringToLiteral= + implicit def fromStringToLiteral(x: String): chisel.fromStringToLiteral= new chisel.fromStringToLiteral(x) - implicit def fromBooleanToLiteral(x: Boolean): chisel.fromBooleanToLiteral= + implicit def fromBooleanToLiteral(x: Boolean): chisel.fromBooleanToLiteral= new chisel.fromBooleanToLiteral(x) } diff --git a/src/main/scala/chisel/util/Arbiter.scala b/src/main/scala/chisel/util/Arbiter.scala index afe48963..3723f2a9 100644 --- a/src/main/scala/chisel/util/Arbiter.scala +++ b/src/main/scala/chisel/util/Arbiter.scala @@ -3,7 +3,9 @@ /** Arbiters in all shapes and sizes. */ -package chisel +package chisel.util + +import chisel._ /** An I/O bundle for the Arbiter */ class ArbiterIO[T <: Data](gen: T, n: Int) extends Bundle { diff --git a/src/main/scala/chisel/util/Bitwise.scala b/src/main/scala/chisel/util/Bitwise.scala index 27064059..94413fc7 100644 --- a/src/main/scala/chisel/util/Bitwise.scala +++ b/src/main/scala/chisel/util/Bitwise.scala @@ -3,7 +3,9 @@ /** Miscellaneous circuit generators operating on bits. */ -package chisel +package chisel.util + +import chisel._ object FillInterleaved { diff --git a/src/main/scala/chisel/util/Cat.scala b/src/main/scala/chisel/util/Cat.scala index a35619df..5b3c613e 100644 --- a/src/main/scala/chisel/util/Cat.scala +++ b/src/main/scala/chisel/util/Cat.scala @@ -1,6 +1,8 @@ // See LICENSE for license details. -package chisel +package chisel.util + +import chisel._ object Cat { /** Combine data elements together diff --git a/src/main/scala/chisel/util/CircuitMath.scala b/src/main/scala/chisel/util/CircuitMath.scala index 001be802..c3b94fdb 100644 --- a/src/main/scala/chisel/util/CircuitMath.scala +++ b/src/main/scala/chisel/util/CircuitMath.scala @@ -3,7 +3,9 @@ /** Circuit-land math operations. */ -package chisel +package chisel.util + +import chisel._ /** Compute Log2 with truncation of a UInt in hardware using a Mux Tree * An alternative interpretation is it computes the minimum number of bits needed to represent x diff --git a/src/main/scala/chisel/util/Conditional.scala b/src/main/scala/chisel/util/Conditional.scala index 94f00080..01c12799 100644 --- a/src/main/scala/chisel/util/Conditional.scala +++ b/src/main/scala/chisel/util/Conditional.scala @@ -3,13 +3,15 @@ /** Conditional blocks. */ -package chisel +package chisel.util import scala.language.reflectiveCalls import scala.language.experimental.macros import scala.reflect.runtime.universe._ import scala.reflect.macros.blackbox._ +import chisel._ + /** This is identical to [[Chisel.when when]] with the condition inverted */ object unless { // scalastyle:ignore object.name def apply(c: Bool)(block: => Unit) { @@ -61,7 +63,7 @@ object switch { // scalastyle:ignore object.name def extractIsStatement(tree: Tree): List[c.universe.Tree] = tree match { // TODO: remove when Chisel compatibility package is removed case q"Chisel.`package`.is.apply( ..$params )( ..$body )" => List(q"$sc.is( ..$params )( ..$body )") - case q"chisel.is.apply( ..$params )( ..$body )" => List(q"$sc.is( ..$params )( ..$body )") + case q"chisel.util.is.apply( ..$params )( ..$body )" => List(q"$sc.is( ..$params )( ..$body )") case b => throw new Exception(s"Cannot include blocks that do not begin with is() in switch.") } val q"..$body" = x diff --git a/src/main/scala/chisel/util/Counter.scala b/src/main/scala/chisel/util/Counter.scala index dde1e347..1c0b0203 100644 --- a/src/main/scala/chisel/util/Counter.scala +++ b/src/main/scala/chisel/util/Counter.scala @@ -1,6 +1,8 @@ // See LICENSE for license details. -package chisel +package chisel.util + +import chisel._ /** A counter module * @param n number of counts before the counter resets (or one more than the diff --git a/src/main/scala/chisel/util/Decoupled.scala b/src/main/scala/chisel/util/Decoupled.scala index 955b0870..89b0e39d 100644 --- a/src/main/scala/chisel/util/Decoupled.scala +++ b/src/main/scala/chisel/util/Decoupled.scala @@ -3,7 +3,9 @@ /** Wrappers for ready-valid (Decoupled) interfaces and associated circuit generators using them. */ -package chisel +package chisel.util + +import chisel._ /** An I/O Bundle with simple handshaking using valid and ready signals for data 'bits'*/ class DecoupledIO[+T <: Data](gen: T) extends Bundle diff --git a/src/main/scala/chisel/util/Enum.scala b/src/main/scala/chisel/util/Enum.scala index 2757a06c..8babcd23 100644 --- a/src/main/scala/chisel/util/Enum.scala +++ b/src/main/scala/chisel/util/Enum.scala @@ -3,7 +3,9 @@ /** Enum generators, allowing circuit constants to have more meaningful names. */ -package chisel +package chisel.util + +import chisel._ object Enum { /** Returns a sequence of Bits subtypes with values from 0 until n. Helper method. */ diff --git a/src/main/scala/chisel/util/LFSR.scala b/src/main/scala/chisel/util/LFSR.scala index 1befb8ca..f70630bf 100644 --- a/src/main/scala/chisel/util/LFSR.scala +++ b/src/main/scala/chisel/util/LFSR.scala @@ -3,7 +3,9 @@ /** LFSRs in all shapes and sizes. */ -package chisel +package chisel.util + +import chisel._ // scalastyle:off magic.number /** linear feedback shift register diff --git a/src/main/scala/chisel/util/Lookup.scala b/src/main/scala/chisel/util/Lookup.scala index 1fdfd6ae..d32d9aec 100644 --- a/src/main/scala/chisel/util/Lookup.scala +++ b/src/main/scala/chisel/util/Lookup.scala @@ -1,6 +1,8 @@ // See LICENSE for license details. -package chisel +package chisel.util + +import chisel._ object ListLookup { def apply[T <: Data](addr: UInt, default: List[T], mapping: Array[(BitPat, List[T])]): List[T] = { diff --git a/src/main/scala/chisel/util/Math.scala b/src/main/scala/chisel/util/Math.scala index 1bf667ce..69464d15 100644 --- a/src/main/scala/chisel/util/Math.scala +++ b/src/main/scala/chisel/util/Math.scala @@ -3,7 +3,9 @@ /** Scala-land math helper functions, like logs. */ -package chisel +package chisel.util + +import chisel._ /** Compute the log2 rounded up with min value of 1 */ object log2Up { diff --git a/src/main/scala/chisel/util/Mux.scala b/src/main/scala/chisel/util/Mux.scala index 97467240..cfff4485 100644 --- a/src/main/scala/chisel/util/Mux.scala +++ b/src/main/scala/chisel/util/Mux.scala @@ -3,7 +3,9 @@ /** Mux circuit generators. */ -package chisel +package chisel.util + +import chisel._ /** Builds a Mux tree out of the input signal vector using a one hot encoded select signal. Returns the output of the Mux tree. diff --git a/src/main/scala/chisel/util/OneHot.scala b/src/main/scala/chisel/util/OneHot.scala index 5d1de1a7..ef21c65d 100644 --- a/src/main/scala/chisel/util/OneHot.scala +++ b/src/main/scala/chisel/util/OneHot.scala @@ -3,7 +3,9 @@ /** Circuit generators for working with one-hot representations. */ -package chisel +package chisel.util + +import chisel._ /** Converts from One Hot Encoding to a UInt indicating which bit is active * This is the inverse of [[Chisel.UIntToOH UIntToOH]]*/ diff --git a/src/main/scala/chisel/util/Reg.scala b/src/main/scala/chisel/util/Reg.scala index 1808af76..1b40646d 100644 --- a/src/main/scala/chisel/util/Reg.scala +++ b/src/main/scala/chisel/util/Reg.scala @@ -3,7 +3,9 @@ /** Variations and helpers for registers. */ -package chisel +package chisel.util + +import chisel._ object RegNext { diff --git a/src/main/scala/chisel/util/TransitName.scala b/src/main/scala/chisel/util/TransitName.scala index 141b10bc..04e1995b 100644 --- a/src/main/scala/chisel/util/TransitName.scala +++ b/src/main/scala/chisel/util/TransitName.scala @@ -1,5 +1,6 @@ -package chisel +package chisel.util +import chisel._ import internal.HasId object TransitName { diff --git a/src/main/scala/chisel/util/Valid.scala b/src/main/scala/chisel/util/Valid.scala index cffed0a7..56ac9abb 100644 --- a/src/main/scala/chisel/util/Valid.scala +++ b/src/main/scala/chisel/util/Valid.scala @@ -3,7 +3,9 @@ /** Wrappers for valid interfaces and associated circuit generators using them. */ -package chisel +package chisel.util + +import chisel._ /** An I/O Bundle containing data and a signal determining if it is valid */ class ValidIO[+T <: Data](gen2: T) extends Bundle diff --git a/src/test/scala/chiselTests/Assert.scala b/src/test/scala/chiselTests/Assert.scala index eccf98e1..eb8617b2 100644 --- a/src/test/scala/chiselTests/Assert.scala +++ b/src/test/scala/chiselTests/Assert.scala @@ -5,6 +5,7 @@ package chiselTests import org.scalatest._ import chisel._ import chisel.testers.BasicTester +import chisel.util._ class FailingAssertTester() extends BasicTester { assert(Bool(false)) diff --git a/src/test/scala/chiselTests/BlackBox.scala b/src/test/scala/chiselTests/BlackBox.scala index 962a9db1..b77550c1 100644 --- a/src/test/scala/chiselTests/BlackBox.scala +++ b/src/test/scala/chiselTests/BlackBox.scala @@ -4,8 +4,10 @@ package chiselTests import java.io.File import org.scalatest._ + import chisel._ import chisel.testers.BasicTester +import chisel.util._ class BlackBoxInverter extends BlackBox { val io = new Bundle() { diff --git a/src/test/scala/chiselTests/ComplexAssign.scala b/src/test/scala/chiselTests/ComplexAssign.scala index 8f79f76d..53a6a67d 100644 --- a/src/test/scala/chiselTests/ComplexAssign.scala +++ b/src/test/scala/chiselTests/ComplexAssign.scala @@ -1,11 +1,13 @@ // See LICENSE for license details. package chiselTests -import chisel._ + import org.scalatest._ import org.scalatest.prop._ +import chisel._ import chisel.testers.BasicTester +import chisel.util._ class Complex[T <: Data](val re: T, val im: T) extends Bundle { override def cloneType: this.type = diff --git a/src/test/scala/chiselTests/Counter.scala b/src/test/scala/chiselTests/Counter.scala index cbc80b86..963c1c92 100644 --- a/src/test/scala/chiselTests/Counter.scala +++ b/src/test/scala/chiselTests/Counter.scala @@ -1,10 +1,13 @@ // See LICENSE for license details. package chiselTests -import chisel._ + import org.scalatest._ import org.scalatest.prop._ + +import chisel._ import chisel.testers.BasicTester +import chisel.util._ class CountTester(max: Int) extends BasicTester { val cnt = Counter(max) diff --git a/src/test/scala/chiselTests/Decoder.scala b/src/test/scala/chiselTests/Decoder.scala index 1e6e7648..33980955 100644 --- a/src/test/scala/chiselTests/Decoder.scala +++ b/src/test/scala/chiselTests/Decoder.scala @@ -1,11 +1,14 @@ // See LICENSE for license details. package chiselTests -import chisel._ + import org.scalatest._ import org.scalatest.prop._ import org.scalacheck._ + +import chisel._ import chisel.testers.BasicTester +import chisel.util._ class Decoder(bitpats: List[String]) extends Module { val io = new Bundle { diff --git a/src/test/scala/chiselTests/DeqIOSpec.scala b/src/test/scala/chiselTests/DeqIOSpec.scala index 9fd47ab0..95160140 100644 --- a/src/test/scala/chiselTests/DeqIOSpec.scala +++ b/src/test/scala/chiselTests/DeqIOSpec.scala @@ -4,6 +4,7 @@ package chiselTests import chisel._ import chisel.testers.BasicTester +import chisel.util._ /** * Created by chick on 2/8/16. diff --git a/src/test/scala/chiselTests/LFSR16.scala b/src/test/scala/chiselTests/LFSR16.scala index 42024a3f..b3e69884 100644 --- a/src/test/scala/chiselTests/LFSR16.scala +++ b/src/test/scala/chiselTests/LFSR16.scala @@ -4,6 +4,7 @@ package chiselTests import chisel._ import chisel.testers.BasicTester +import chisel.util._ class LFSR16 extends Module { val io = new Bundle { diff --git a/src/test/scala/chiselTests/MultiAssign.scala b/src/test/scala/chiselTests/MultiAssign.scala index ff3bc7a5..152e6723 100644 --- a/src/test/scala/chiselTests/MultiAssign.scala +++ b/src/test/scala/chiselTests/MultiAssign.scala @@ -3,8 +3,10 @@ package chiselTests import org.scalatest._ + import chisel._ import chisel.testers.BasicTester +import chisel.util._ class LastAssignTester() extends BasicTester { val cnt = Counter(2) diff --git a/src/test/scala/chiselTests/Risc.scala b/src/test/scala/chiselTests/Risc.scala index 6b0742ae..741e9896 100644 --- a/src/test/scala/chiselTests/Risc.scala +++ b/src/test/scala/chiselTests/Risc.scala @@ -3,6 +3,7 @@ package chiselTests import chisel._ +import chisel.util._ class Risc extends Module { val io = new Bundle { diff --git a/src/test/scala/chiselTests/Stack.scala b/src/test/scala/chiselTests/Stack.scala index 53c57b5b..0ce228de 100644 --- a/src/test/scala/chiselTests/Stack.scala +++ b/src/test/scala/chiselTests/Stack.scala @@ -3,7 +3,9 @@ package chiselTests import scala.collection.mutable.Stack + import chisel._ +import chisel.util._ class ChiselStack(val depth: Int) extends Module { val io = new Bundle { diff --git a/src/test/scala/chiselTests/Tbl.scala b/src/test/scala/chiselTests/Tbl.scala index 918f9158..2049d8bb 100644 --- a/src/test/scala/chiselTests/Tbl.scala +++ b/src/test/scala/chiselTests/Tbl.scala @@ -2,10 +2,12 @@ package chiselTests -import chisel._ import org.scalatest._ import org.scalatest.prop._ + +import chisel._ import chisel.testers.BasicTester +import chisel.util._ class Tbl(w: Int, n: Int) extends Module { val io = new Bundle { diff --git a/src/test/scala/chiselTests/TesterDriverSpec.scala b/src/test/scala/chiselTests/TesterDriverSpec.scala index e6b5bc1f..50290fab 100644 --- a/src/test/scala/chiselTests/TesterDriverSpec.scala +++ b/src/test/scala/chiselTests/TesterDriverSpec.scala @@ -4,6 +4,7 @@ package chiselTests import chisel._ import chisel.testers.BasicTester +import chisel.util._ /** Extend BasicTester with a simple circuit and finish method. TesterDriver will call the * finish method after the FinishTester's constructor has completed, which will alter the diff --git a/src/test/scala/chiselTests/Vec.scala b/src/test/scala/chiselTests/Vec.scala index e35c765e..35a0c8bc 100644 --- a/src/test/scala/chiselTests/Vec.scala +++ b/src/test/scala/chiselTests/Vec.scala @@ -2,10 +2,12 @@ package chiselTests -import chisel._ import org.scalatest._ import org.scalatest.prop._ + +import chisel._ import chisel.testers.BasicTester +import chisel.util._ class ValueTester(w: Int, values: List[Int]) extends BasicTester { val v = Vec(values.map(UInt(_, width = w))) // TODO: does this need a Wire? Why no error? diff --git a/src/test/scala/chiselTests/VectorPacketIO.scala b/src/test/scala/chiselTests/VectorPacketIO.scala index 26e87360..a1282071 100644 --- a/src/test/scala/chiselTests/VectorPacketIO.scala +++ b/src/test/scala/chiselTests/VectorPacketIO.scala @@ -4,6 +4,7 @@ package chiselTests import chisel._ import chisel.testers.BasicTester +import chisel.util._ /** * This test used to fail when assignment statements were diff --git a/src/test/scala/chiselTests/VendingMachine.scala b/src/test/scala/chiselTests/VendingMachine.scala index e11e48dd..0d621e6a 100644 --- a/src/test/scala/chiselTests/VendingMachine.scala +++ b/src/test/scala/chiselTests/VendingMachine.scala @@ -3,6 +3,7 @@ package chiselTests import chisel._ +import chisel.util._ class VendingMachine extends Module { val io = new Bundle { diff --git a/src/test/scala/chiselTests/When.scala b/src/test/scala/chiselTests/When.scala index a1bd7c31..1c9c3bc5 100644 --- a/src/test/scala/chiselTests/When.scala +++ b/src/test/scala/chiselTests/When.scala @@ -3,8 +3,10 @@ package chiselTests import org.scalatest._ + import chisel._ import chisel.testers.BasicTester +import chisel.util._ class WhenTester() extends BasicTester { val cnt = Counter(4) -- cgit v1.2.3 From 66301b9042530a5265c18c97a0dab9022a0efc50 Mon Sep 17 00:00:00 2001 From: ducky Date: Wed, 1 Jun 2016 12:17:25 -0700 Subject: Move chisel/... to chisel/core/..., make chisel/compatibility package/folder, move more things into utils --- .../src/main/scala/chisel/Aggregate.scala | 377 ---------- chiselFrontend/src/main/scala/chisel/Assert.scala | 73 -- chiselFrontend/src/main/scala/chisel/Bits.scala | 756 --------------------- .../src/main/scala/chisel/BlackBox.scala | 55 -- chiselFrontend/src/main/scala/chisel/Data.scala | 161 ----- chiselFrontend/src/main/scala/chisel/Mem.scala | 134 ---- chiselFrontend/src/main/scala/chisel/Module.scala | 119 ---- chiselFrontend/src/main/scala/chisel/Printf.scala | 36 - chiselFrontend/src/main/scala/chisel/Reg.scala | 71 -- .../src/main/scala/chisel/SeqUtils.scala | 59 -- chiselFrontend/src/main/scala/chisel/When.scala | 59 -- .../src/main/scala/chisel/core/Aggregate.scala | 377 ++++++++++ .../src/main/scala/chisel/core/Assert.scala | 73 ++ .../src/main/scala/chisel/core/Bits.scala | 756 +++++++++++++++++++++ .../src/main/scala/chisel/core/BlackBox.scala | 55 ++ .../src/main/scala/chisel/core/Data.scala | 161 +++++ .../src/main/scala/chisel/core/Mem.scala | 134 ++++ .../src/main/scala/chisel/core/Module.scala | 119 ++++ .../src/main/scala/chisel/core/Printf.scala | 36 + .../src/main/scala/chisel/core/Reg.scala | 71 ++ .../src/main/scala/chisel/core/SeqUtils.scala | 59 ++ .../src/main/scala/chisel/core/When.scala | 59 ++ src/main/scala/Chisel/BitPat.scala | 88 --- src/main/scala/chisel/FileSystemUtilities.scala | 10 - src/main/scala/chisel/ImplicitConversions.scala | 8 - src/main/scala/chisel/Main.scala | 17 - src/main/scala/chisel/compatibility.scala | 14 +- .../chisel/compatibility/FileSystemUtilities.scala | 12 + src/main/scala/chisel/compatibility/Main.scala | 19 + .../chisel/compatibility/throwException.scala | 14 + src/main/scala/chisel/package.scala | 1 + src/main/scala/chisel/throwException.scala | 12 - src/main/scala/chisel/util/BitPat.scala | 89 +++ .../scala/chisel/util/ImplicitConversions.scala | 10 + 34 files changed, 2052 insertions(+), 2042 deletions(-) delete mode 100644 chiselFrontend/src/main/scala/chisel/Aggregate.scala delete mode 100644 chiselFrontend/src/main/scala/chisel/Assert.scala delete mode 100644 chiselFrontend/src/main/scala/chisel/Bits.scala delete mode 100644 chiselFrontend/src/main/scala/chisel/BlackBox.scala delete mode 100644 chiselFrontend/src/main/scala/chisel/Data.scala delete mode 100644 chiselFrontend/src/main/scala/chisel/Mem.scala delete mode 100644 chiselFrontend/src/main/scala/chisel/Module.scala delete mode 100644 chiselFrontend/src/main/scala/chisel/Printf.scala delete mode 100644 chiselFrontend/src/main/scala/chisel/Reg.scala delete mode 100644 chiselFrontend/src/main/scala/chisel/SeqUtils.scala delete mode 100644 chiselFrontend/src/main/scala/chisel/When.scala create mode 100644 chiselFrontend/src/main/scala/chisel/core/Aggregate.scala create mode 100644 chiselFrontend/src/main/scala/chisel/core/Assert.scala create mode 100644 chiselFrontend/src/main/scala/chisel/core/Bits.scala create mode 100644 chiselFrontend/src/main/scala/chisel/core/BlackBox.scala create mode 100644 chiselFrontend/src/main/scala/chisel/core/Data.scala create mode 100644 chiselFrontend/src/main/scala/chisel/core/Mem.scala create mode 100644 chiselFrontend/src/main/scala/chisel/core/Module.scala create mode 100644 chiselFrontend/src/main/scala/chisel/core/Printf.scala create mode 100644 chiselFrontend/src/main/scala/chisel/core/Reg.scala create mode 100644 chiselFrontend/src/main/scala/chisel/core/SeqUtils.scala create mode 100644 chiselFrontend/src/main/scala/chisel/core/When.scala delete mode 100644 src/main/scala/Chisel/BitPat.scala delete mode 100644 src/main/scala/chisel/FileSystemUtilities.scala delete mode 100644 src/main/scala/chisel/ImplicitConversions.scala delete mode 100644 src/main/scala/chisel/Main.scala create mode 100644 src/main/scala/chisel/compatibility/FileSystemUtilities.scala create mode 100644 src/main/scala/chisel/compatibility/Main.scala create mode 100644 src/main/scala/chisel/compatibility/throwException.scala delete mode 100644 src/main/scala/chisel/throwException.scala create mode 100644 src/main/scala/chisel/util/BitPat.scala create mode 100644 src/main/scala/chisel/util/ImplicitConversions.scala diff --git a/chiselFrontend/src/main/scala/chisel/Aggregate.scala b/chiselFrontend/src/main/scala/chisel/Aggregate.scala deleted file mode 100644 index 4f3f3de0..00000000 --- a/chiselFrontend/src/main/scala/chisel/Aggregate.scala +++ /dev/null @@ -1,377 +0,0 @@ -// See LICENSE for license details. - -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. - */ -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] = 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)) - 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] = 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 - * 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] = 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 - * 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] = 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 - * 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)(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])(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])(implicit sourceInfo: SourceInfo): Unit = this := that.asInstanceOf[Data] - - override def := (that: Data)(implicit sourceInfo: SourceInfo): 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])(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])(implicit sourceInfo: SourceInfo): 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)(DeprecatedSourceInfo) - - 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] 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 - - @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 = 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 = 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 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 = 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. - */ - 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 = 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 = 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. - * - * 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 = 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. - * - * 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)(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)(implicit sourceInfo: SourceInfo): 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") -} diff --git a/chiselFrontend/src/main/scala/chisel/Assert.scala b/chiselFrontend/src/main/scala/chisel/Assert.scala deleted file mode 100644 index 0d660bc3..00000000 --- a/chiselFrontend/src/main/scala/chisel/Assert.scala +++ /dev/null @@ -1,73 +0,0 @@ -// See LICENSE for license details. - -package chisel - -import scala.reflect.macros.blackbox.Context -import scala.language.experimental.macros - -import internal._ -import internal.Builder.pushCommand -import internal.firrtl._ -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 - * condition evaluates to false, the circuit simulation stops with an error. - * - * 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 assert make the standard Module assumptions (single clock - * and single reset). - * - * @param cond condition, assertion fires (simulation fails) when false - * @param message optional message to print when the assertion fires - * - * @note currently cannot be used in core Chisel / libraries because macro - * defs need to be compiled first and the SBT project is not set up to do - * that - */ - // 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)(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))($sourceInfo)" - } - - 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)($sourceInfo)" - } - - 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(sourceInfo, Node(Builder.dynamicContext.currentModule.get.clock), 1)) - } - } - - /** An elaboration-time assertion, otherwise the same as the above run-time - * assertion. */ - def apply(cond: Boolean, message: => String) { - Predef.assert(cond, message) - } - - /** A workaround for default-value overloading problems in Scala, just - * 'assert(cond, "")' */ - def apply(cond: Boolean) { - Predef.assert(cond, "") - } -} diff --git a/chiselFrontend/src/main/scala/chisel/Bits.scala b/chiselFrontend/src/main/scala/chisel/Bits.scala deleted file mode 100644 index 8ec7c1b9..00000000 --- a/chiselFrontend/src/main/scala/chisel/Bits.scala +++ /dev/null @@ -1,756 +0,0 @@ -// See LICENSE for license details. - -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 - * uses are for representing primitive data types, like integers and bits. - */ -abstract class Element(dirArg: Direction, val width: Width) extends Data(dirArg) - -/** A data type for values represented by a single bitvector. Provides basic - * bitwise operations. - */ -sealed abstract class Bits(dirArg: Direction, width: Width, override val litArg: Option[LitArg]) - extends Element(dirArg, width) { - // TODO: perhaps make this concrete? - // Arguments for: self-checking code (can't do arithmetic on bits) - // Arguments against: generates down to a FIRRTL UInt anyways - - private[chisel] def fromInt(x: BigInt, w: Int): this.type - - private[chisel] def flatten: IndexedSeq[Bits] = IndexedSeq(this) - - def cloneType: this.type = cloneTypeWidth(width) - - 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 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(sourceInfo, UInt(width = w), TailOp, n) - } - - - 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(sourceInfo, UInt(width = n), HeadOp, n) - } - - /** Returns the specified bit on this wire as a [[Bool]], statically - * addressed. - */ - 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(sourceInfo, Bool(), BitsExtractOp, this.ref, ILit(x), ILit(x))) - } - } - - /** Returns the specified bit on this wire as a [[Bool]], statically - * addressed. - * - * @note convenience method allowing direct use of Ints without implicits - */ - 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 = 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. - * - * @example - * {{{ - * myBits = 0x5 = 0b101 - * myBits(1,0) => 0b01 // extracts the two least significant bits - * }}} - */ - 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)") - } - val w = x - y + 1 - if (isLit()) { - UInt((litValue >> y) & ((BigInt(1) << w) - 1), w) - } else { - 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 = 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 - */ - 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? - 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. - */ - 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. - */ - final def << (that: UInt): Bits = macro SourceInfoWhiteboxTransform.thatArg - - def do_<< (that: UInt)(implicit sourceInfo: SourceInfo): Bits - - /** Shift right operation */ - // REVIEW TODO: redundant - 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. - */ - 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. - */ - 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. - */ - 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 - */ - 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 - */ - final def asUInt(): UInt = macro SourceInfoTransform.noArg - - def do_asUInt(implicit sourceInfo: SourceInfo): UInt - - /** Reinterpret cast to Bits. */ - 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 = do_asSInt(DeprecatedSourceInfo) - @deprecated("Use asUInt, which makes the reinterpret cast more explicit", "chisel3") - final def toUInt(): UInt = do_asUInt(DeprecatedSourceInfo) - - final def toBool(): Bool = macro SourceInfoTransform.noArg - - 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. - */ - 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 = do_asUInt(DeprecatedSourceInfo) - - override def do_fromBits(that: Bits)(implicit sourceInfo: SourceInfo): this.type = { - val res = Wire(this, null).asInstanceOf[this.type] - res := that - res - } -} - -/** Provides a set of operations to create UInt types and literals. - * Identical in functionality to the UInt companion object. - */ -object Bits extends UIntFactory - -// REVIEW TODO: Further discussion needed on what Num actually is. -/** Abstract trait defining operations available on numeric-like wire data - * types. - */ -abstract trait Num[T <: Data] { - // def << (b: T): T - // def >> (b: T): T - //def unary_-(): T - - // REVIEW TODO: double check ops conventions against FIRRTL - - /** Outputs the sum of `this` and `b`. The resulting width is the max of the - * operands plus 1 (should not overflow). - */ - 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. - * - * @note can generate a single-cycle multiplier, which can result in - * significant cycle time and area costs - */ - 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 - */ - final def / (that: T): T = macro SourceInfoTransform.thatArg - - 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). - */ - final def - (that: T): T = macro SourceInfoTransform.thatArg - - def do_- (that: T)(implicit sourceInfo: SourceInfo): T - - /** Outputs true if `this` < `b`. - */ - final def < (that: T): Bool = macro SourceInfoTransform.thatArg - - def do_< (that: T)(implicit sourceInfo: SourceInfo): Bool - - /** Outputs true if `this` <= `b`. - */ - final def <= (that: T): Bool = macro SourceInfoTransform.thatArg - - def do_<= (that: T)(implicit sourceInfo: SourceInfo): Bool - - /** Outputs true if `this` > `b`. - */ - final def > (that: T): Bool = macro SourceInfoTransform.thatArg - - def do_> (that: T)(implicit sourceInfo: SourceInfo): Bool - - /** Outputs true if `this` >= `b`. - */ - 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. - */ - 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. - */ - 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. - * Defines arithmetic operations between other integer types. - */ -sealed class UInt private[chisel] (dir: Direction, width: Width, lit: Option[ULit] = None) - extends Bits(dir, width, lit) with Num[UInt] { - private[chisel] override def cloneTypeWidth(w: Width): this.type = - new UInt(dir, w).asInstanceOf[this.type] - private[chisel] def toType = s"UInt$width" - - override private[chisel] def fromInt(value: BigInt, width: Int): this.type = - UInt(value, width).asInstanceOf[this.type] - - 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 - 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 do_unary_~ (implicit sourceInfo: SourceInfo): UInt = - unop(sourceInfo, UInt(width = width), BitNotOp) - - // REVIEW TODO: Can this be defined on Bits? - 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)) - } - - /** 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. - 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). - */ - 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. -private[chisel] sealed trait UIntFactory { - /** Create a UInt type with inferred width. */ - def apply(): UInt = apply(NO_DIR, Width()) - /** Create a UInt type or port with fixed width. */ - def apply(dir: Direction = NO_DIR, width: Int): UInt = apply(dir, Width(width)) - /** Create a UInt port with inferred width. */ - def apply(dir: Direction): UInt = apply(dir, Width()) - - /** Create a UInt literal with inferred width. */ - def apply(value: BigInt): UInt = apply(value, Width()) - /** Create a UInt literal with fixed width. */ - def apply(value: BigInt, width: Int): UInt = apply(value, Width(width)) - /** Create a UInt literal with inferred width. */ - def apply(n: String): UInt = apply(parse(n), parsedWidth(n)) - /** Create a UInt literal with fixed width. */ - def apply(n: String, width: Int): UInt = apply(parse(n), width) - - /** Create a UInt type with specified width. */ - def apply(width: Width): UInt = apply(NO_DIR, width) - /** Create a UInt port with specified width. */ - def apply(dir: Direction, width: Width): UInt = new UInt(dir, width) - /** Create a UInt literal with specified width. */ - def apply(value: BigInt, width: Width): UInt = { - val lit = ULit(value, width) - new UInt(NO_DIR, lit.width, Some(lit)) - } - - private def parse(n: String) = { - val (base, num) = n.splitAt(1) - val radix = base match { - case "x" | "h" => 16 - case "d" => 10 - case "o" => 8 - case "b" => 2 - case _ => Builder.error(s"Invalid base $base"); 2 - } - BigInt(num.filterNot(_ == '_'), radix) - } - - private def parsedWidth(n: String) = - if (n(0) == 'b') { - Width(n.length-1) - } else if (n(0) == 'h') { - Width((n.length-1) * 4) - } else { - Width() - } -} - -object UInt extends UIntFactory - -sealed class SInt private (dir: Direction, width: Width, lit: Option[SLit] = None) - extends Bits(dir, width, lit) with Num[SInt] { - private[chisel] override def cloneTypeWidth(w: Width): this.type = - new SInt(dir, w).asInstanceOf[this.type] - private[chisel] def toType = s"SInt$width" - - override def := (that: Data)(implicit sourceInfo: SourceInfo): Unit = that match { - case _: SInt => this connect that - case _ => this badConnect that - } - - override private[chisel] def fromInt(value: BigInt, width: Int): this.type = - SInt(value, width).asInstanceOf[this.type] - - 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 */ - 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 */ - final def +% (that: SInt): SInt = macro SourceInfoTransform.thatArg - /** subtract (width +1) operator */ - final def -& (that: SInt): SInt = macro SourceInfoTransform.thatArg - /** subtract (no growth) operator */ - 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 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 { - /** Create an SInt type with inferred width. */ - def apply(): SInt = apply(NO_DIR, Width()) - /** Create an SInt type or port with fixed width. */ - def apply(dir: Direction = NO_DIR, width: Int): SInt = apply(dir, Width(width)) - /** Create an SInt port with inferred width. */ - def apply(dir: Direction): SInt = apply(dir, Width()) - - /** Create an SInt literal with inferred width. */ - def apply(value: BigInt): SInt = apply(value, Width()) - /** Create an SInt literal with fixed width. */ - def apply(value: BigInt, width: Int): SInt = apply(value, Width(width)) - - /** Create an SInt type with specified width. */ - def apply(width: Width): SInt = new SInt(NO_DIR, width) - /** Create an SInt port with specified width. */ - def apply(dir: Direction, width: Width): SInt = new SInt(dir, width) - /** Create an SInt literal with specified width. */ - def apply(value: BigInt, width: Width): SInt = { - val lit = SLit(value, width) - new SInt(NO_DIR, lit.width, Some(lit)) - } -} - -// REVIEW TODO: Why does this extend UInt and not Bits? Does defining airth -// operations on a Bool make sense? -/** A data type for booleans, defined as a single bit indicating true or false. - */ -sealed class Bool(dir: Direction, lit: Option[ULit] = None) extends UInt(dir, Width(1), lit) { - private[chisel] override def cloneTypeWidth(w: Width): this.type = { - require(!w.known || w.get == 1) - new Bool(dir).asInstanceOf[this.type] - } - - override private[chisel] def fromInt(value: BigInt, width: Int): this.type = { - require((value == 0 || value == 1) && width == 1) - Bool(value == 1).asInstanceOf[this.type] - } - - // REVIEW TODO: Why does this need to exist and have different conventions - // than Bits? - 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 do_unary_~ (implicit sourceInfo: SourceInfo): Bool = - unop(sourceInfo, Bool(), BitNotOp) - - /** Outputs the logical OR of two Bools. - */ - 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 = macro SourceInfoTransform.thatArg - - def do_&& (that: Bool)(implicit sourceInfo: SourceInfo): Bool = this & that -} - -object Bool { - /** Creates an empty Bool. - */ - def apply(dir: Direction = NO_DIR): Bool = new Bool(dir) - - /** Creates Bool literal. - */ - def apply(x: Boolean): Bool = new Bool(NO_DIR, Some(ULit(if (x) 1 else 0, Width(1)))) -} - -object Mux { - /** Creates a mux, whose output is one of the inputs depending on the - * value of the condition. - * - * @param cond condition determining the input to choose - * @param con the value chosen when `cond` is true - * @param alt the value chosen when `cond` is false - * @example - * {{{ - * val muxOut = Mux(data_in === UInt(3), UInt(3, 4), UInt(0, 4)) - * }}} - */ - 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] - case (c: Bool, a: UInt) => doMux(cond, c << 0, a).asInstanceOf[T] - case (c: Bits, a: Bits) => doMux(cond, c, a).asInstanceOf[T] - case _ => doAggregateMux(cond, con, alt) - } - - 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(sourceInfo, d, MultiplexOp, cond.ref, con.ref, alt.ref)) - } - - 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") - doMux(cond, con, alt) - } -} - diff --git a/chiselFrontend/src/main/scala/chisel/BlackBox.scala b/chiselFrontend/src/main/scala/chisel/BlackBox.scala deleted file mode 100644 index 1dabc18f..00000000 --- a/chiselFrontend/src/main/scala/chisel/BlackBox.scala +++ /dev/null @@ -1,55 +0,0 @@ -// See LICENSE for license details. - -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 - * to RTL modules defined outside Chisel. - * - * @example - * {{{ - * ... to be written once a spec is finalized ... - * }}} - */ -// REVIEW TODO: make Verilog parameters part of the constructor interface? -abstract class BlackBox extends Module { - // Don't bother taking override_clock|reset, clock/reset locked out anyway - // TODO: actually implement this. - def setVerilogParameters(s: String): Unit = {} - - // The body of a BlackBox is empty, the real logic happens in firrtl/Emitter.scala - // Bypass standard clock, reset, io port declaration by flattening io - // TODO(twigg): ? Really, overrides are bad, should extend BaseModule.... - override private[chisel] def ports = io.elements.toSeq - - // Do not do reflective naming of internal signals, just name io - override private[chisel] def setRefs(): this.type = { - for ((name, port) <- ports) { - port.setRef(ModuleIO(this, _namespace.name(name))) - } - // setRef is not called on the actual io. - // There is a risk of user improperly attempting to connect directly with io - // Long term solution will be to define BlackBox IO differently as part of - // it not descending from the (current) Module - this - } - - // Don't setup clock, reset - // Cann't invalide io in one bunch, must invalidate each part separately - override private[chisel] def setupInParent(implicit sourceInfo: SourceInfo): this.type = _parent match { - case Some(p) => { - // Just init instance inputs - for((_,port) <- ports) pushCommand(DefInvalid(sourceInfo, port.ref)) - this - } - case None => this - } - - // Using null is horrible but these signals SHOULD NEVER be used: - override val clock = null - override val reset = null -} diff --git a/chiselFrontend/src/main/scala/chisel/Data.scala b/chiselFrontend/src/main/scala/chisel/Data.scala deleted file mode 100644 index c08adf9d..00000000 --- a/chiselFrontend/src/main/scala/chisel/Data.scala +++ /dev/null @@ -1,161 +0,0 @@ -// 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, DeprecatedSourceInfo, UnlocatableSourceInfo, WireTransform, SourceInfoTransform} - -sealed abstract class Direction(name: String) { - override def toString: String = name - def flip: Direction -} -object INPUT extends Direction("input") { override def flip: Direction = OUTPUT } -object OUTPUT extends Direction("output") { override def flip: Direction = INPUT } -object NO_DIR extends Direction("?") { override def flip: Direction = NO_DIR } - -@deprecated("debug doesn't do anything in Chisel3 as no pruning happens in the frontend", "chisel3") -object debug { // scalastyle:ignore object.name - def apply (arg: Data): Data = arg -} - -/** Mixing in this trait flips the direction of an Aggregate. */ -trait Flipped extends Data { - this.overrideDirection(_.flip, !_) -} - -/** This forms the root of the type system for wire data types. The data value - * must be representable as some number (need not be known at Chisel compile - * time) of bits, and must have methods to pack / unpack structured data to / - * from bits. - */ -abstract class Data(dirArg: Direction) extends HasId { - def dir: Direction = dirVar - - // Sucks this is mutable state, but cloneType doesn't take a Direction arg - private var isFlipVar = dirArg == INPUT - private var dirVar = dirArg - private[chisel] def isFlip = isFlipVar - - private[chisel] def overrideDirection(newDir: Direction => Direction, - newFlip: Boolean => Boolean): this.type = { - this.isFlipVar = newFlip(this.isFlipVar) - for (field <- this.flatten) - (field: Data).dirVar = newDir((field: Data).dirVar) - this - } - def asInput: this.type = cloneType.overrideDirection(_ => INPUT, _ => true) - def asOutput: this.type = cloneType.overrideDirection(_ => OUTPUT, _ => false) - def flip(): this.type = cloneType.overrideDirection(_.flip, !_) - - private[chisel] def badConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit = - throwException(s"cannot connect ${this} and ${that}") - 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)(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 - def isLit(): Boolean = litArg.isDefined - - def width: Width - final def getWidth: Int = width.get - - // While this being in the Data API doesn't really make sense (should be in - // Aggregate, right?) this is because of an implementation limitation: - // cloneWithDirection, which is private and defined here, needs flatten to - // set element directionality. - // Related: directionality is mutable state. A possible solution for both is - // to define directionality relative to the container, but these parent links - // currently don't exist (while this information may be available during - // FIRRTL emission, it would break directionality querying from Chisel, which - // does get used). - private[chisel] def flatten: IndexedSeq[Bits] - - /** Creates an new instance of this type, unpacking the input Bits into - * structured data. - * - * This performs the inverse operation of toBits. - * - * @note does NOT assign to the object this is called on, instead creates - * and returns a NEW object (useful in a clone-and-assign scenario) - * @note does NOT check bit widths, may drop bits during assignment - * @note what fromBits assigs to must have known widths - */ - 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 (that.width.known && that.width.get >= wire.width.get) { - that - } else { - Wire(that.cloneTypeWidth(wire.width), init = that) - } - for (x <- wire.flatten) { - x := bits(i + x.getWidth-1, i) - i += x.getWidth - } - wire.asInstanceOf[this.type] - } - - /** Packs the value of this object as plain Bits. - * - * This performs the inverse operation of fromBits(Bits). - */ - @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 = 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 = - 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 = - do_apply(t, init)(UnlocatableSourceInfo) - - def do_apply[T <: Data](t: T, init: T)(implicit sourceInfo: SourceInfo): T = { - val x = Reg.makeType(t, null.asInstanceOf[T], init) - pushCommand(DefWire(sourceInfo, x)) - pushCommand(DefInvalid(sourceInfo, x.ref)) - if (init != null) { - x := init - } - x - } -} - -object Clock { - def apply(dir: Direction = NO_DIR): Clock = new Clock(dir) -} - -// TODO: Document this. -sealed class Clock(dirArg: Direction) extends Element(dirArg, Width(1)) { - def cloneType: this.type = Clock(dirArg).asInstanceOf[this.type] - private[chisel] override def flatten: IndexedSeq[Bits] = IndexedSeq() - private[chisel] def cloneTypeWidth(width: Width): this.type = cloneType - private[chisel] def toType = "Clock" - - 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 deleted file mode 100644 index 5fd8b81e..00000000 --- a/chiselFrontend/src/main/scala/chisel/Mem.scala +++ /dev/null @@ -1,134 +0,0 @@ -// 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, 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] = 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] = 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(sourceInfo, mem, mt, size)) // TODO multi-clock - mem - } -} - -sealed abstract class MemBase[T <: Data](t: T, val length: Int) extends HasId with VecLike[T] { - // REVIEW TODO: make accessors (static/dynamic, read/write) combinations consistent. - - /** Creates a read accessor into the memory with static addressing. See the - * class documentation of the memory for more detailed information. - */ - def apply(idx: Int): T = apply(UInt(idx)) - - /** 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(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(UnlocatableSourceInfo, idx, MemPortDirection.READ) - - /** Creates a write accessor into the memory. - * - * @param idx memory element index to write into - * @param data new data to write - */ - def write(idx: UInt, data: T): Unit = { - implicit val sourceInfo = UnlocatableSourceInfo - makePort(UnlocatableSourceInfo, idx, MemPortDirection.WRITE) := data - } - - /** Creates a masked write accessor into the memory. - * - * @param idx memory element index to write into - * @param data new data to write - * @param mask write mask as a Vec of Bool: a write to the Vec element in - * memory is only performed if the corresponding mask index is true. - * - * @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 = { - 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})") - } - if (accessor.length != mask.length) { - Builder.error(s"Mem write mask must contain ${accessor.length} elements (found ${mask.length})") - } - for (((cond, port), datum) <- mask zip accessor zip dataVec) - when (cond) { port := datum } - } - - 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. - * - * Writes take effect on the rising clock edge after the request. Reads are - * combinational (requests will return data on the same cycle). - * Read-after-write hazards are not an issue. - * - * @note when multiple conflicting writes are performed on a Mem element, the - * result is undefined (unlike Vec, where the last assignment wins) - */ -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] = 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] = 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(sourceInfo, mem, mt, size)) // TODO multi-clock - mem - } -} - -/** A sequential-read, sequential-write memory. - * - * Writes take effect on the rising clock edge after the request. Reads return - * data on the rising edge after the request. Read-after-write behavior (when - * a read and write to the same address are requested on the same cycle) is - * undefined. - * - * @note when multiple conflicting writes are performed on a Mem element, the - * result is undefined (unlike Vec, where the last assignment wins) - */ -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 deleted file mode 100644 index f7f8c0b5..00000000 --- a/chiselFrontend/src/main/scala/chisel/Module.scala +++ /dev/null @@ -1,119 +0,0 @@ -// See LICENSE for license details. - -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 - * (necessary to help Chisel track internal state). - * - * @param m the Module being created - * - * @return the input module `m` with Chisel metadata properly set - */ - 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(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(sourceInfo, m, ports)) - m.setupInParent(childSourceInfo) - } -} - -/** Abstract base class for Modules, which behave much like Verilog modules. - * These may contain both logic and state which are written in the Module - * body (constructor). - * - * @note Module instantiations must be wrapped in a Module() call. - */ -abstract class Module( - override_clock: Option[Clock]=None, override_reset: Option[Bool]=None) -extends HasId { - // _clock and _reset can be clock and reset in these 2ary constructors - // once chisel2 compatibility issues are resolved - def this(_clock: Clock) = this(Option(_clock), None) - def this(_reset: Bool) = this(None, Option(_reset)) - def this(_clock: Clock, _reset: Bool) = this(Option(_clock), Option(_reset)) - - private[chisel] val _namespace = Builder.globalNamespace.child - private[chisel] val _commands = ArrayBuffer[Command]() - private[chisel] val _ids = ArrayBuffer[HasId]() - dynamicContext.currentModule = Some(this) - - /** Name of the instance. */ - val name = Builder.globalNamespace.name(getClass.getName.split('.').last) - - /** IO for this Module. At the Scala level (pre-FIRRTL transformations), - * connections in and out of a Module may only go through `io` elements. - */ - def io: Bundle - val clock = Clock(INPUT) - val reset = Bool(INPUT) - - private[chisel] def addId(d: HasId) { _ids += d } - - private[chisel] def ports: Seq[(String,Data)] = Vector( - ("clk", clock), ("reset", reset), ("io", io) - ) - - private[chisel] def computePorts = for((name, port) <- ports) yield { - val bundleDir = if (port.isFlip) INPUT else OUTPUT - Port(port, if (port.dir == NO_DIR) bundleDir else port.dir) - } - - 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 - } - } - - private[chisel] def setRefs(): this.type = { - for ((name, port) <- ports) { - port.setRef(ModuleIO(this, _namespace.name(name))) - } - - // Suggest names to nodes using runtime reflection - val valNames = HashSet[String](getClass.getDeclaredFields.map(_.getName):_*) - def isPublicVal(m: java.lang.reflect.Method) = - m.getParameterTypes.isEmpty && valNames.contains(m.getName) - val methods = getClass.getMethods.sortWith(_.getName > _.getName) - for (m <- methods; if isPublicVal(m)) m.invoke(this) match { - case (id: HasId) => id.suggestName(m.getName) - case _ => - } - - // For Module instances we haven't named, suggest the name of the Module - _ids foreach { - case m: Module => m.suggestName(m.name) - case _ => - } - - // All suggestions are in, force names to every node. - _ids.foreach(_.forceName(default="T", _namespace)) - _ids.foreach(_._onModuleClose) - this - } -} diff --git a/chiselFrontend/src/main/scala/chisel/Printf.scala b/chiselFrontend/src/main/scala/chisel/Printf.scala deleted file mode 100644 index 27b72815..00000000 --- a/chiselFrontend/src/main/scala/chisel/Printf.scala +++ /dev/null @@ -1,36 +0,0 @@ -// 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 deleted file mode 100644 index 0ed320d7..00000000 --- a/chiselFrontend/src/main/scala/chisel/Reg.scala +++ /dev/null @@ -1,71 +0,0 @@ -// See LICENSE for license details. - -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 = { - if (t ne null) { - t.cloneType - } else if (next ne null) { - next.cloneTypeWidth(Width()) - } else if (init ne null) { - init.litArg match { - // For e.g. Reg(init=UInt(0, k)), fix the Reg's width to k - case Some(lit) if lit.forcedWidth => init.cloneType - case _ => init.cloneTypeWidth(Width()) - } - } else { - throwException("cannot infer type") - } - } - - /** Creates a register with optional next and initialization values. - * - * @param t: data type for the register - * @param next: new value register is to be updated with every cycle (or - * empty to not update unless assigned to using the := operator) - * @param init: initialization value on reset (or empty for uninitialized, - * where the register value persists across a reset) - * - * @note this may result in a type error if called from a type parameterized - * function, since the Scala compiler isn't smart enough to know that null - * 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 = - // 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()). - // Implicit conversions to Option (or similar) types were also considered, - // but Scala's type inferencer and implicit insertion isn't smart enough - // to resolve all use cases. If the type inferencer / implicit resolution - // system improves, this may be changed. - val x = makeType(t, next, init) - val clock = Node(x._parent.get.clock) // TODO multi-clock - if (init == null) { - pushCommand(DefReg(sourceInfo, x, clock)) - } else { - pushCommand(DefRegInit(sourceInfo, x, clock, Node(x._parent.get.reset), init.ref)) - } - if (next != null) { - x := next - } - x - } -} diff --git a/chiselFrontend/src/main/scala/chisel/SeqUtils.scala b/chiselFrontend/src/main/scala/chisel/SeqUtils.scala deleted file mode 100644 index da75edae..00000000 --- a/chiselFrontend/src/main/scala/chisel/SeqUtils.scala +++ /dev/null @@ -1,59 +0,0 @@ -// See LICENSE for license details. - -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 = macro SourceInfoTransform.inArg - - def do_asUInt[T <: Bits](in: Seq[T])(implicit sourceInfo: SourceInfo): UInt = { - if (in.tail.isEmpty) { - in.head.asUInt - } else { - val left = asUInt(in.slice(0, in.length/2)) - val right = asUInt(in.slice(in.length/2, in.length)) - right ## left - } - } - - /** Counts the number of true Bools in a Seq */ - 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) { - in.head - } else { - count(in.slice(0, in.size/2)) + (UInt(0) ## count(in.slice(in.size/2, in.size))) - } - } - - /** Returns data value corresponding to first true predicate */ - def priorityMux[T <: Data](in: Seq[(Bool, T)]): T = macro SourceInfoTransform.inArg - - def do_priorityMux[T <: Data](in: Seq[(Bool, T)])(implicit sourceInfo: SourceInfo): T = { - if (in.size == 1) { - in.head._2 - } else { - Mux(in.head._1, in.head._2, priorityMux(in.tail)) - } - } - - /** Returns data value corresponding to lone true predicate */ - 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 { - val masked = for ((s, i) <- in) yield Mux(s, i.toBits, Bits(0)) - val width = in.map(_._2.width).reduce(_ max _) - in.head._2.cloneTypeWidth(width).fromBits(masked.reduceLeft(_|_)) - } - } -} diff --git a/chiselFrontend/src/main/scala/chisel/When.scala b/chiselFrontend/src/main/scala/chisel/When.scala deleted file mode 100644 index 37c59f24..00000000 --- a/chiselFrontend/src/main/scala/chisel/When.scala +++ /dev/null @@ -1,59 +0,0 @@ -// 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 when { // scalastyle:ignore object.name - /** Create a `when` condition block, where whether a block of logic is - * executed or not depends on the conditional. - * - * @param cond condition to execute upon - * @param block logic that runs only if `cond` is true - * - * @example - * {{{ - * when ( myData === UInt(3) ) { - * // Some logic to run when myData equals 3. - * } .elsewhen ( myData === UInt(1) ) { - * // Some logic to run when myData equals 1. - * } .otherwise { - * // Some logic to run when myData is neither 3 nor 1. - * } - * }}} - */ - def apply(cond: Bool)(block: => Unit)(implicit sourceInfo: SourceInfo): WhenContext = { - new WhenContext(sourceInfo, cond, !cond, block) - } -} - -/** Internal mechanism for generating a when. Because of the way FIRRTL - * commands are emitted, generating a FIRRTL elsewhen or nested whens inside - * elses would be difficult. Instead, this keeps track of the negative of the - * previous conditions, so when an elsewhen or otherwise is used, it checks - * that both the condition is true and all the previous conditions have been - * false. - */ -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)(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)(implicit sourceInfo: SourceInfo): Unit = - new WhenContext(sourceInfo, prevCond, null, block) - - pushCommand(WhenBegin(sourceInfo, cond.ref)) - block - pushCommand(WhenEnd(sourceInfo)) -} diff --git a/chiselFrontend/src/main/scala/chisel/core/Aggregate.scala b/chiselFrontend/src/main/scala/chisel/core/Aggregate.scala new file mode 100644 index 00000000..4f3f3de0 --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel/core/Aggregate.scala @@ -0,0 +1,377 @@ +// See LICENSE for license details. + +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. + */ +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] = 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)) + 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] = 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 + * 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] = 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 + * 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] = 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 + * 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)(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])(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])(implicit sourceInfo: SourceInfo): Unit = this := that.asInstanceOf[Data] + + override def := (that: Data)(implicit sourceInfo: SourceInfo): 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])(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])(implicit sourceInfo: SourceInfo): 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)(DeprecatedSourceInfo) + + 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] 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 + + @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 = 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 = 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 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 = 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. + */ + 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 = 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 = 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. + * + * 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 = 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. + * + * 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)(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)(implicit sourceInfo: SourceInfo): 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") +} diff --git a/chiselFrontend/src/main/scala/chisel/core/Assert.scala b/chiselFrontend/src/main/scala/chisel/core/Assert.scala new file mode 100644 index 00000000..0d660bc3 --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel/core/Assert.scala @@ -0,0 +1,73 @@ +// See LICENSE for license details. + +package chisel + +import scala.reflect.macros.blackbox.Context +import scala.language.experimental.macros + +import internal._ +import internal.Builder.pushCommand +import internal.firrtl._ +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 + * condition evaluates to false, the circuit simulation stops with an error. + * + * 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 assert make the standard Module assumptions (single clock + * and single reset). + * + * @param cond condition, assertion fires (simulation fails) when false + * @param message optional message to print when the assertion fires + * + * @note currently cannot be used in core Chisel / libraries because macro + * defs need to be compiled first and the SBT project is not set up to do + * that + */ + // 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)(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))($sourceInfo)" + } + + 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)($sourceInfo)" + } + + 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(sourceInfo, Node(Builder.dynamicContext.currentModule.get.clock), 1)) + } + } + + /** An elaboration-time assertion, otherwise the same as the above run-time + * assertion. */ + def apply(cond: Boolean, message: => String) { + Predef.assert(cond, message) + } + + /** A workaround for default-value overloading problems in Scala, just + * 'assert(cond, "")' */ + def apply(cond: Boolean) { + Predef.assert(cond, "") + } +} diff --git a/chiselFrontend/src/main/scala/chisel/core/Bits.scala b/chiselFrontend/src/main/scala/chisel/core/Bits.scala new file mode 100644 index 00000000..8ec7c1b9 --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel/core/Bits.scala @@ -0,0 +1,756 @@ +// See LICENSE for license details. + +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 + * uses are for representing primitive data types, like integers and bits. + */ +abstract class Element(dirArg: Direction, val width: Width) extends Data(dirArg) + +/** A data type for values represented by a single bitvector. Provides basic + * bitwise operations. + */ +sealed abstract class Bits(dirArg: Direction, width: Width, override val litArg: Option[LitArg]) + extends Element(dirArg, width) { + // TODO: perhaps make this concrete? + // Arguments for: self-checking code (can't do arithmetic on bits) + // Arguments against: generates down to a FIRRTL UInt anyways + + private[chisel] def fromInt(x: BigInt, w: Int): this.type + + private[chisel] def flatten: IndexedSeq[Bits] = IndexedSeq(this) + + def cloneType: this.type = cloneTypeWidth(width) + + 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 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(sourceInfo, UInt(width = w), TailOp, n) + } + + + 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(sourceInfo, UInt(width = n), HeadOp, n) + } + + /** Returns the specified bit on this wire as a [[Bool]], statically + * addressed. + */ + 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(sourceInfo, Bool(), BitsExtractOp, this.ref, ILit(x), ILit(x))) + } + } + + /** Returns the specified bit on this wire as a [[Bool]], statically + * addressed. + * + * @note convenience method allowing direct use of Ints without implicits + */ + 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 = 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. + * + * @example + * {{{ + * myBits = 0x5 = 0b101 + * myBits(1,0) => 0b01 // extracts the two least significant bits + * }}} + */ + 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)") + } + val w = x - y + 1 + if (isLit()) { + UInt((litValue >> y) & ((BigInt(1) << w) - 1), w) + } else { + 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 = 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 + */ + 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? + 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. + */ + 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. + */ + final def << (that: UInt): Bits = macro SourceInfoWhiteboxTransform.thatArg + + def do_<< (that: UInt)(implicit sourceInfo: SourceInfo): Bits + + /** Shift right operation */ + // REVIEW TODO: redundant + 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. + */ + 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. + */ + 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. + */ + 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 + */ + 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 + */ + final def asUInt(): UInt = macro SourceInfoTransform.noArg + + def do_asUInt(implicit sourceInfo: SourceInfo): UInt + + /** Reinterpret cast to Bits. */ + 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 = do_asSInt(DeprecatedSourceInfo) + @deprecated("Use asUInt, which makes the reinterpret cast more explicit", "chisel3") + final def toUInt(): UInt = do_asUInt(DeprecatedSourceInfo) + + final def toBool(): Bool = macro SourceInfoTransform.noArg + + 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. + */ + 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 = do_asUInt(DeprecatedSourceInfo) + + override def do_fromBits(that: Bits)(implicit sourceInfo: SourceInfo): this.type = { + val res = Wire(this, null).asInstanceOf[this.type] + res := that + res + } +} + +/** Provides a set of operations to create UInt types and literals. + * Identical in functionality to the UInt companion object. + */ +object Bits extends UIntFactory + +// REVIEW TODO: Further discussion needed on what Num actually is. +/** Abstract trait defining operations available on numeric-like wire data + * types. + */ +abstract trait Num[T <: Data] { + // def << (b: T): T + // def >> (b: T): T + //def unary_-(): T + + // REVIEW TODO: double check ops conventions against FIRRTL + + /** Outputs the sum of `this` and `b`. The resulting width is the max of the + * operands plus 1 (should not overflow). + */ + 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. + * + * @note can generate a single-cycle multiplier, which can result in + * significant cycle time and area costs + */ + 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 + */ + final def / (that: T): T = macro SourceInfoTransform.thatArg + + 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). + */ + final def - (that: T): T = macro SourceInfoTransform.thatArg + + def do_- (that: T)(implicit sourceInfo: SourceInfo): T + + /** Outputs true if `this` < `b`. + */ + final def < (that: T): Bool = macro SourceInfoTransform.thatArg + + def do_< (that: T)(implicit sourceInfo: SourceInfo): Bool + + /** Outputs true if `this` <= `b`. + */ + final def <= (that: T): Bool = macro SourceInfoTransform.thatArg + + def do_<= (that: T)(implicit sourceInfo: SourceInfo): Bool + + /** Outputs true if `this` > `b`. + */ + final def > (that: T): Bool = macro SourceInfoTransform.thatArg + + def do_> (that: T)(implicit sourceInfo: SourceInfo): Bool + + /** Outputs true if `this` >= `b`. + */ + 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. + */ + 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. + */ + 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. + * Defines arithmetic operations between other integer types. + */ +sealed class UInt private[chisel] (dir: Direction, width: Width, lit: Option[ULit] = None) + extends Bits(dir, width, lit) with Num[UInt] { + private[chisel] override def cloneTypeWidth(w: Width): this.type = + new UInt(dir, w).asInstanceOf[this.type] + private[chisel] def toType = s"UInt$width" + + override private[chisel] def fromInt(value: BigInt, width: Int): this.type = + UInt(value, width).asInstanceOf[this.type] + + 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 + 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 do_unary_~ (implicit sourceInfo: SourceInfo): UInt = + unop(sourceInfo, UInt(width = width), BitNotOp) + + // REVIEW TODO: Can this be defined on Bits? + 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)) + } + + /** 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. + 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). + */ + 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. +private[chisel] sealed trait UIntFactory { + /** Create a UInt type with inferred width. */ + def apply(): UInt = apply(NO_DIR, Width()) + /** Create a UInt type or port with fixed width. */ + def apply(dir: Direction = NO_DIR, width: Int): UInt = apply(dir, Width(width)) + /** Create a UInt port with inferred width. */ + def apply(dir: Direction): UInt = apply(dir, Width()) + + /** Create a UInt literal with inferred width. */ + def apply(value: BigInt): UInt = apply(value, Width()) + /** Create a UInt literal with fixed width. */ + def apply(value: BigInt, width: Int): UInt = apply(value, Width(width)) + /** Create a UInt literal with inferred width. */ + def apply(n: String): UInt = apply(parse(n), parsedWidth(n)) + /** Create a UInt literal with fixed width. */ + def apply(n: String, width: Int): UInt = apply(parse(n), width) + + /** Create a UInt type with specified width. */ + def apply(width: Width): UInt = apply(NO_DIR, width) + /** Create a UInt port with specified width. */ + def apply(dir: Direction, width: Width): UInt = new UInt(dir, width) + /** Create a UInt literal with specified width. */ + def apply(value: BigInt, width: Width): UInt = { + val lit = ULit(value, width) + new UInt(NO_DIR, lit.width, Some(lit)) + } + + private def parse(n: String) = { + val (base, num) = n.splitAt(1) + val radix = base match { + case "x" | "h" => 16 + case "d" => 10 + case "o" => 8 + case "b" => 2 + case _ => Builder.error(s"Invalid base $base"); 2 + } + BigInt(num.filterNot(_ == '_'), radix) + } + + private def parsedWidth(n: String) = + if (n(0) == 'b') { + Width(n.length-1) + } else if (n(0) == 'h') { + Width((n.length-1) * 4) + } else { + Width() + } +} + +object UInt extends UIntFactory + +sealed class SInt private (dir: Direction, width: Width, lit: Option[SLit] = None) + extends Bits(dir, width, lit) with Num[SInt] { + private[chisel] override def cloneTypeWidth(w: Width): this.type = + new SInt(dir, w).asInstanceOf[this.type] + private[chisel] def toType = s"SInt$width" + + override def := (that: Data)(implicit sourceInfo: SourceInfo): Unit = that match { + case _: SInt => this connect that + case _ => this badConnect that + } + + override private[chisel] def fromInt(value: BigInt, width: Int): this.type = + SInt(value, width).asInstanceOf[this.type] + + 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 */ + 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 */ + final def +% (that: SInt): SInt = macro SourceInfoTransform.thatArg + /** subtract (width +1) operator */ + final def -& (that: SInt): SInt = macro SourceInfoTransform.thatArg + /** subtract (no growth) operator */ + 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 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 { + /** Create an SInt type with inferred width. */ + def apply(): SInt = apply(NO_DIR, Width()) + /** Create an SInt type or port with fixed width. */ + def apply(dir: Direction = NO_DIR, width: Int): SInt = apply(dir, Width(width)) + /** Create an SInt port with inferred width. */ + def apply(dir: Direction): SInt = apply(dir, Width()) + + /** Create an SInt literal with inferred width. */ + def apply(value: BigInt): SInt = apply(value, Width()) + /** Create an SInt literal with fixed width. */ + def apply(value: BigInt, width: Int): SInt = apply(value, Width(width)) + + /** Create an SInt type with specified width. */ + def apply(width: Width): SInt = new SInt(NO_DIR, width) + /** Create an SInt port with specified width. */ + def apply(dir: Direction, width: Width): SInt = new SInt(dir, width) + /** Create an SInt literal with specified width. */ + def apply(value: BigInt, width: Width): SInt = { + val lit = SLit(value, width) + new SInt(NO_DIR, lit.width, Some(lit)) + } +} + +// REVIEW TODO: Why does this extend UInt and not Bits? Does defining airth +// operations on a Bool make sense? +/** A data type for booleans, defined as a single bit indicating true or false. + */ +sealed class Bool(dir: Direction, lit: Option[ULit] = None) extends UInt(dir, Width(1), lit) { + private[chisel] override def cloneTypeWidth(w: Width): this.type = { + require(!w.known || w.get == 1) + new Bool(dir).asInstanceOf[this.type] + } + + override private[chisel] def fromInt(value: BigInt, width: Int): this.type = { + require((value == 0 || value == 1) && width == 1) + Bool(value == 1).asInstanceOf[this.type] + } + + // REVIEW TODO: Why does this need to exist and have different conventions + // than Bits? + 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 do_unary_~ (implicit sourceInfo: SourceInfo): Bool = + unop(sourceInfo, Bool(), BitNotOp) + + /** Outputs the logical OR of two Bools. + */ + 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 = macro SourceInfoTransform.thatArg + + def do_&& (that: Bool)(implicit sourceInfo: SourceInfo): Bool = this & that +} + +object Bool { + /** Creates an empty Bool. + */ + def apply(dir: Direction = NO_DIR): Bool = new Bool(dir) + + /** Creates Bool literal. + */ + def apply(x: Boolean): Bool = new Bool(NO_DIR, Some(ULit(if (x) 1 else 0, Width(1)))) +} + +object Mux { + /** Creates a mux, whose output is one of the inputs depending on the + * value of the condition. + * + * @param cond condition determining the input to choose + * @param con the value chosen when `cond` is true + * @param alt the value chosen when `cond` is false + * @example + * {{{ + * val muxOut = Mux(data_in === UInt(3), UInt(3, 4), UInt(0, 4)) + * }}} + */ + 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] + case (c: Bool, a: UInt) => doMux(cond, c << 0, a).asInstanceOf[T] + case (c: Bits, a: Bits) => doMux(cond, c, a).asInstanceOf[T] + case _ => doAggregateMux(cond, con, alt) + } + + 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(sourceInfo, d, MultiplexOp, cond.ref, con.ref, alt.ref)) + } + + 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") + doMux(cond, con, alt) + } +} + diff --git a/chiselFrontend/src/main/scala/chisel/core/BlackBox.scala b/chiselFrontend/src/main/scala/chisel/core/BlackBox.scala new file mode 100644 index 00000000..1dabc18f --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel/core/BlackBox.scala @@ -0,0 +1,55 @@ +// See LICENSE for license details. + +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 + * to RTL modules defined outside Chisel. + * + * @example + * {{{ + * ... to be written once a spec is finalized ... + * }}} + */ +// REVIEW TODO: make Verilog parameters part of the constructor interface? +abstract class BlackBox extends Module { + // Don't bother taking override_clock|reset, clock/reset locked out anyway + // TODO: actually implement this. + def setVerilogParameters(s: String): Unit = {} + + // The body of a BlackBox is empty, the real logic happens in firrtl/Emitter.scala + // Bypass standard clock, reset, io port declaration by flattening io + // TODO(twigg): ? Really, overrides are bad, should extend BaseModule.... + override private[chisel] def ports = io.elements.toSeq + + // Do not do reflective naming of internal signals, just name io + override private[chisel] def setRefs(): this.type = { + for ((name, port) <- ports) { + port.setRef(ModuleIO(this, _namespace.name(name))) + } + // setRef is not called on the actual io. + // There is a risk of user improperly attempting to connect directly with io + // Long term solution will be to define BlackBox IO differently as part of + // it not descending from the (current) Module + this + } + + // Don't setup clock, reset + // Cann't invalide io in one bunch, must invalidate each part separately + override private[chisel] def setupInParent(implicit sourceInfo: SourceInfo): this.type = _parent match { + case Some(p) => { + // Just init instance inputs + for((_,port) <- ports) pushCommand(DefInvalid(sourceInfo, port.ref)) + this + } + case None => this + } + + // Using null is horrible but these signals SHOULD NEVER be used: + override val clock = null + override val reset = null +} diff --git a/chiselFrontend/src/main/scala/chisel/core/Data.scala b/chiselFrontend/src/main/scala/chisel/core/Data.scala new file mode 100644 index 00000000..c08adf9d --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel/core/Data.scala @@ -0,0 +1,161 @@ +// 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, DeprecatedSourceInfo, UnlocatableSourceInfo, WireTransform, SourceInfoTransform} + +sealed abstract class Direction(name: String) { + override def toString: String = name + def flip: Direction +} +object INPUT extends Direction("input") { override def flip: Direction = OUTPUT } +object OUTPUT extends Direction("output") { override def flip: Direction = INPUT } +object NO_DIR extends Direction("?") { override def flip: Direction = NO_DIR } + +@deprecated("debug doesn't do anything in Chisel3 as no pruning happens in the frontend", "chisel3") +object debug { // scalastyle:ignore object.name + def apply (arg: Data): Data = arg +} + +/** Mixing in this trait flips the direction of an Aggregate. */ +trait Flipped extends Data { + this.overrideDirection(_.flip, !_) +} + +/** This forms the root of the type system for wire data types. The data value + * must be representable as some number (need not be known at Chisel compile + * time) of bits, and must have methods to pack / unpack structured data to / + * from bits. + */ +abstract class Data(dirArg: Direction) extends HasId { + def dir: Direction = dirVar + + // Sucks this is mutable state, but cloneType doesn't take a Direction arg + private var isFlipVar = dirArg == INPUT + private var dirVar = dirArg + private[chisel] def isFlip = isFlipVar + + private[chisel] def overrideDirection(newDir: Direction => Direction, + newFlip: Boolean => Boolean): this.type = { + this.isFlipVar = newFlip(this.isFlipVar) + for (field <- this.flatten) + (field: Data).dirVar = newDir((field: Data).dirVar) + this + } + def asInput: this.type = cloneType.overrideDirection(_ => INPUT, _ => true) + def asOutput: this.type = cloneType.overrideDirection(_ => OUTPUT, _ => false) + def flip(): this.type = cloneType.overrideDirection(_.flip, !_) + + private[chisel] def badConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit = + throwException(s"cannot connect ${this} and ${that}") + 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)(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 + def isLit(): Boolean = litArg.isDefined + + def width: Width + final def getWidth: Int = width.get + + // While this being in the Data API doesn't really make sense (should be in + // Aggregate, right?) this is because of an implementation limitation: + // cloneWithDirection, which is private and defined here, needs flatten to + // set element directionality. + // Related: directionality is mutable state. A possible solution for both is + // to define directionality relative to the container, but these parent links + // currently don't exist (while this information may be available during + // FIRRTL emission, it would break directionality querying from Chisel, which + // does get used). + private[chisel] def flatten: IndexedSeq[Bits] + + /** Creates an new instance of this type, unpacking the input Bits into + * structured data. + * + * This performs the inverse operation of toBits. + * + * @note does NOT assign to the object this is called on, instead creates + * and returns a NEW object (useful in a clone-and-assign scenario) + * @note does NOT check bit widths, may drop bits during assignment + * @note what fromBits assigs to must have known widths + */ + 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 (that.width.known && that.width.get >= wire.width.get) { + that + } else { + Wire(that.cloneTypeWidth(wire.width), init = that) + } + for (x <- wire.flatten) { + x := bits(i + x.getWidth-1, i) + i += x.getWidth + } + wire.asInstanceOf[this.type] + } + + /** Packs the value of this object as plain Bits. + * + * This performs the inverse operation of fromBits(Bits). + */ + @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 = 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 = + 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 = + do_apply(t, init)(UnlocatableSourceInfo) + + def do_apply[T <: Data](t: T, init: T)(implicit sourceInfo: SourceInfo): T = { + val x = Reg.makeType(t, null.asInstanceOf[T], init) + pushCommand(DefWire(sourceInfo, x)) + pushCommand(DefInvalid(sourceInfo, x.ref)) + if (init != null) { + x := init + } + x + } +} + +object Clock { + def apply(dir: Direction = NO_DIR): Clock = new Clock(dir) +} + +// TODO: Document this. +sealed class Clock(dirArg: Direction) extends Element(dirArg, Width(1)) { + def cloneType: this.type = Clock(dirArg).asInstanceOf[this.type] + private[chisel] override def flatten: IndexedSeq[Bits] = IndexedSeq() + private[chisel] def cloneTypeWidth(width: Width): this.type = cloneType + private[chisel] def toType = "Clock" + + 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/core/Mem.scala b/chiselFrontend/src/main/scala/chisel/core/Mem.scala new file mode 100644 index 00000000..5fd8b81e --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel/core/Mem.scala @@ -0,0 +1,134 @@ +// 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, 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] = 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] = 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(sourceInfo, mem, mt, size)) // TODO multi-clock + mem + } +} + +sealed abstract class MemBase[T <: Data](t: T, val length: Int) extends HasId with VecLike[T] { + // REVIEW TODO: make accessors (static/dynamic, read/write) combinations consistent. + + /** Creates a read accessor into the memory with static addressing. See the + * class documentation of the memory for more detailed information. + */ + def apply(idx: Int): T = apply(UInt(idx)) + + /** 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(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(UnlocatableSourceInfo, idx, MemPortDirection.READ) + + /** Creates a write accessor into the memory. + * + * @param idx memory element index to write into + * @param data new data to write + */ + def write(idx: UInt, data: T): Unit = { + implicit val sourceInfo = UnlocatableSourceInfo + makePort(UnlocatableSourceInfo, idx, MemPortDirection.WRITE) := data + } + + /** Creates a masked write accessor into the memory. + * + * @param idx memory element index to write into + * @param data new data to write + * @param mask write mask as a Vec of Bool: a write to the Vec element in + * memory is only performed if the corresponding mask index is true. + * + * @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 = { + 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})") + } + if (accessor.length != mask.length) { + Builder.error(s"Mem write mask must contain ${accessor.length} elements (found ${mask.length})") + } + for (((cond, port), datum) <- mask zip accessor zip dataVec) + when (cond) { port := datum } + } + + 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. + * + * Writes take effect on the rising clock edge after the request. Reads are + * combinational (requests will return data on the same cycle). + * Read-after-write hazards are not an issue. + * + * @note when multiple conflicting writes are performed on a Mem element, the + * result is undefined (unlike Vec, where the last assignment wins) + */ +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] = 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] = 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(sourceInfo, mem, mt, size)) // TODO multi-clock + mem + } +} + +/** A sequential-read, sequential-write memory. + * + * Writes take effect on the rising clock edge after the request. Reads return + * data on the rising edge after the request. Read-after-write behavior (when + * a read and write to the same address are requested on the same cycle) is + * undefined. + * + * @note when multiple conflicting writes are performed on a Mem element, the + * result is undefined (unlike Vec, where the last assignment wins) + */ +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/core/Module.scala b/chiselFrontend/src/main/scala/chisel/core/Module.scala new file mode 100644 index 00000000..f7f8c0b5 --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel/core/Module.scala @@ -0,0 +1,119 @@ +// See LICENSE for license details. + +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 + * (necessary to help Chisel track internal state). + * + * @param m the Module being created + * + * @return the input module `m` with Chisel metadata properly set + */ + 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(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(sourceInfo, m, ports)) + m.setupInParent(childSourceInfo) + } +} + +/** Abstract base class for Modules, which behave much like Verilog modules. + * These may contain both logic and state which are written in the Module + * body (constructor). + * + * @note Module instantiations must be wrapped in a Module() call. + */ +abstract class Module( + override_clock: Option[Clock]=None, override_reset: Option[Bool]=None) +extends HasId { + // _clock and _reset can be clock and reset in these 2ary constructors + // once chisel2 compatibility issues are resolved + def this(_clock: Clock) = this(Option(_clock), None) + def this(_reset: Bool) = this(None, Option(_reset)) + def this(_clock: Clock, _reset: Bool) = this(Option(_clock), Option(_reset)) + + private[chisel] val _namespace = Builder.globalNamespace.child + private[chisel] val _commands = ArrayBuffer[Command]() + private[chisel] val _ids = ArrayBuffer[HasId]() + dynamicContext.currentModule = Some(this) + + /** Name of the instance. */ + val name = Builder.globalNamespace.name(getClass.getName.split('.').last) + + /** IO for this Module. At the Scala level (pre-FIRRTL transformations), + * connections in and out of a Module may only go through `io` elements. + */ + def io: Bundle + val clock = Clock(INPUT) + val reset = Bool(INPUT) + + private[chisel] def addId(d: HasId) { _ids += d } + + private[chisel] def ports: Seq[(String,Data)] = Vector( + ("clk", clock), ("reset", reset), ("io", io) + ) + + private[chisel] def computePorts = for((name, port) <- ports) yield { + val bundleDir = if (port.isFlip) INPUT else OUTPUT + Port(port, if (port.dir == NO_DIR) bundleDir else port.dir) + } + + 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 + } + } + + private[chisel] def setRefs(): this.type = { + for ((name, port) <- ports) { + port.setRef(ModuleIO(this, _namespace.name(name))) + } + + // Suggest names to nodes using runtime reflection + val valNames = HashSet[String](getClass.getDeclaredFields.map(_.getName):_*) + def isPublicVal(m: java.lang.reflect.Method) = + m.getParameterTypes.isEmpty && valNames.contains(m.getName) + val methods = getClass.getMethods.sortWith(_.getName > _.getName) + for (m <- methods; if isPublicVal(m)) m.invoke(this) match { + case (id: HasId) => id.suggestName(m.getName) + case _ => + } + + // For Module instances we haven't named, suggest the name of the Module + _ids foreach { + case m: Module => m.suggestName(m.name) + case _ => + } + + // All suggestions are in, force names to every node. + _ids.foreach(_.forceName(default="T", _namespace)) + _ids.foreach(_._onModuleClose) + this + } +} diff --git a/chiselFrontend/src/main/scala/chisel/core/Printf.scala b/chiselFrontend/src/main/scala/chisel/core/Printf.scala new file mode 100644 index 00000000..27b72815 --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel/core/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/core/Reg.scala b/chiselFrontend/src/main/scala/chisel/core/Reg.scala new file mode 100644 index 00000000..0ed320d7 --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel/core/Reg.scala @@ -0,0 +1,71 @@ +// See LICENSE for license details. + +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 = { + if (t ne null) { + t.cloneType + } else if (next ne null) { + next.cloneTypeWidth(Width()) + } else if (init ne null) { + init.litArg match { + // For e.g. Reg(init=UInt(0, k)), fix the Reg's width to k + case Some(lit) if lit.forcedWidth => init.cloneType + case _ => init.cloneTypeWidth(Width()) + } + } else { + throwException("cannot infer type") + } + } + + /** Creates a register with optional next and initialization values. + * + * @param t: data type for the register + * @param next: new value register is to be updated with every cycle (or + * empty to not update unless assigned to using the := operator) + * @param init: initialization value on reset (or empty for uninitialized, + * where the register value persists across a reset) + * + * @note this may result in a type error if called from a type parameterized + * function, since the Scala compiler isn't smart enough to know that null + * 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 = + // 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()). + // Implicit conversions to Option (or similar) types were also considered, + // but Scala's type inferencer and implicit insertion isn't smart enough + // to resolve all use cases. If the type inferencer / implicit resolution + // system improves, this may be changed. + val x = makeType(t, next, init) + val clock = Node(x._parent.get.clock) // TODO multi-clock + if (init == null) { + pushCommand(DefReg(sourceInfo, x, clock)) + } else { + pushCommand(DefRegInit(sourceInfo, x, clock, Node(x._parent.get.reset), init.ref)) + } + if (next != null) { + x := next + } + x + } +} diff --git a/chiselFrontend/src/main/scala/chisel/core/SeqUtils.scala b/chiselFrontend/src/main/scala/chisel/core/SeqUtils.scala new file mode 100644 index 00000000..da75edae --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel/core/SeqUtils.scala @@ -0,0 +1,59 @@ +// See LICENSE for license details. + +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 = macro SourceInfoTransform.inArg + + def do_asUInt[T <: Bits](in: Seq[T])(implicit sourceInfo: SourceInfo): UInt = { + if (in.tail.isEmpty) { + in.head.asUInt + } else { + val left = asUInt(in.slice(0, in.length/2)) + val right = asUInt(in.slice(in.length/2, in.length)) + right ## left + } + } + + /** Counts the number of true Bools in a Seq */ + 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) { + in.head + } else { + count(in.slice(0, in.size/2)) + (UInt(0) ## count(in.slice(in.size/2, in.size))) + } + } + + /** Returns data value corresponding to first true predicate */ + def priorityMux[T <: Data](in: Seq[(Bool, T)]): T = macro SourceInfoTransform.inArg + + def do_priorityMux[T <: Data](in: Seq[(Bool, T)])(implicit sourceInfo: SourceInfo): T = { + if (in.size == 1) { + in.head._2 + } else { + Mux(in.head._1, in.head._2, priorityMux(in.tail)) + } + } + + /** Returns data value corresponding to lone true predicate */ + 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 { + val masked = for ((s, i) <- in) yield Mux(s, i.toBits, Bits(0)) + val width = in.map(_._2.width).reduce(_ max _) + in.head._2.cloneTypeWidth(width).fromBits(masked.reduceLeft(_|_)) + } + } +} diff --git a/chiselFrontend/src/main/scala/chisel/core/When.scala b/chiselFrontend/src/main/scala/chisel/core/When.scala new file mode 100644 index 00000000..37c59f24 --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel/core/When.scala @@ -0,0 +1,59 @@ +// 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 when { // scalastyle:ignore object.name + /** Create a `when` condition block, where whether a block of logic is + * executed or not depends on the conditional. + * + * @param cond condition to execute upon + * @param block logic that runs only if `cond` is true + * + * @example + * {{{ + * when ( myData === UInt(3) ) { + * // Some logic to run when myData equals 3. + * } .elsewhen ( myData === UInt(1) ) { + * // Some logic to run when myData equals 1. + * } .otherwise { + * // Some logic to run when myData is neither 3 nor 1. + * } + * }}} + */ + def apply(cond: Bool)(block: => Unit)(implicit sourceInfo: SourceInfo): WhenContext = { + new WhenContext(sourceInfo, cond, !cond, block) + } +} + +/** Internal mechanism for generating a when. Because of the way FIRRTL + * commands are emitted, generating a FIRRTL elsewhen or nested whens inside + * elses would be difficult. Instead, this keeps track of the negative of the + * previous conditions, so when an elsewhen or otherwise is used, it checks + * that both the condition is true and all the previous conditions have been + * false. + */ +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)(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)(implicit sourceInfo: SourceInfo): Unit = + new WhenContext(sourceInfo, prevCond, null, block) + + pushCommand(WhenBegin(sourceInfo, cond.ref)) + block + pushCommand(WhenEnd(sourceInfo)) +} diff --git a/src/main/scala/Chisel/BitPat.scala b/src/main/scala/Chisel/BitPat.scala deleted file mode 100644 index a6833ed2..00000000 --- a/src/main/scala/Chisel/BitPat.scala +++ /dev/null @@ -1,88 +0,0 @@ -// See LICENSE for license details. - -package chisel - -import scala.language.experimental.macros - -import chisel.internal.sourceinfo.{SourceInfo, SourceInfoTransform} - -object BitPat { - /** Parses a bit pattern string into (bits, mask, width). - * - * @return bits the literal value, with don't cares being 0 - * @return mask the mask bits, with don't cares being 0 and cares being 1 - * @return width the number of bits in the literal, including values and - * don't cares. - */ - private def parse(x: String): (BigInt, BigInt, Int) = { - // Notes: - // While Verilog Xs also handle octal and hex cases, there isn't a - // compelling argument and no one has asked for it. - // If ? parsing is to be exposed, the return API needs further scrutiny - // (especially with things like mask polarity). - require(x.head == 'b', "BitPats must be in binary and be prefixed with 'b'") - var bits = BigInt(0) - var mask = BigInt(0) - for (d <- x.tail) { - if (d != '_') { - require("01?".contains(d), "Literal: " + x + " contains illegal character: " + d) - mask = (mask << 1) + (if (d == '?') 0 else 1) - bits = (bits << 1) + (if (d == '1') 1 else 0) - } - } - (bits, mask, x.length - 1) - } - - /** Creates a [[BitPat]] literal from a string. - * - * @param n the literal value as a string, in binary, prefixed with 'b' - * @note legal characters are '0', '1', and '?', as well as '_' as white - * space (which are ignored) - */ - def apply(n: String): BitPat = { - val (bits, mask, width) = parse(n) - new BitPat(bits, mask, width) - } - - /** Creates a [[BitPat]] of all don't cares of the specified bitwidth. */ - def dontCare(width: Int): BitPat = BitPat("b" + ("?" * width)) - - @deprecated("Use BitPat.dontCare", "chisel3") - def DC(width: Int): BitPat = dontCare(width) // scalastyle:ignore method.name - - /** Allows BitPats to be used where a UInt is expected. - * - * @note the BitPat must not have don't care bits (will error out otherwise) - */ - def bitPatToUInt(x: BitPat): UInt = { - require(x.mask == (BigInt(1) << x.getWidth) - 1) - UInt(x.value, x.getWidth) - } - - /** Allows UInts to be used where a BitPat is expected, useful for when an - * interface is defined with BitPats but not all cases need the partial - * matching capability. - * - * @note the UInt must be a literal - */ - def apply(x: UInt): BitPat = { - require(x.isLit) - BitPat("b" + x.litValue.toString(2)) - } -} - -// TODO: Break out of Core? (this doesn't involve FIRRTL generation) -/** Bit patterns are literals with masks, used to represent values with don't - * cares. Equality comparisons will ignore don't care bits (for example, - * BitPat(0b10?1) === UInt(0b1001) and UInt(0b1011)). - */ -sealed class BitPat(val value: BigInt, val mask: BigInt, width: Int) { - def getWidth: Int = width - 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/src/main/scala/chisel/FileSystemUtilities.scala b/src/main/scala/chisel/FileSystemUtilities.scala deleted file mode 100644 index f100eaf6..00000000 --- a/src/main/scala/chisel/FileSystemUtilities.scala +++ /dev/null @@ -1,10 +0,0 @@ -// See LICENSE for license details. - -package chisel - -@deprecated("FileSystemUtilities doesn't exist in chisel3", "3.0.0") -trait FileSystemUtilities { - def createOutputFile(name: String): java.io.FileWriter = { - new java.io.FileWriter(Driver.targetDir + "/" + name) - } -} diff --git a/src/main/scala/chisel/ImplicitConversions.scala b/src/main/scala/chisel/ImplicitConversions.scala deleted file mode 100644 index f786d4f1..00000000 --- a/src/main/scala/chisel/ImplicitConversions.scala +++ /dev/null @@ -1,8 +0,0 @@ -// See LICENSE for license details. - -package chisel - -object ImplicitConversions { - implicit def intToUInt(x: Int): UInt = UInt(x) - implicit def booleanToBool(x: Boolean): Bool = Bool(x) -} diff --git a/src/main/scala/chisel/Main.scala b/src/main/scala/chisel/Main.scala deleted file mode 100644 index 79e5c9ca..00000000 --- a/src/main/scala/chisel/Main.scala +++ /dev/null @@ -1,17 +0,0 @@ -// See LICENSE for license details. - -package chisel - -import java.io.File - -@deprecated("chiselMain doesn't exist in Chisel3", "3.0") object chiselMain { - def apply[T <: Module](args: Array[String], gen: () => T): Unit = - Predef.assert(false, "No more chiselMain in Chisel3") - - def run[T <: Module] (args: Array[String], gen: () => T): Unit = { - val circuit = Driver.elaborate(gen) - Driver.parseArgs(args) - val output_file = new File(Driver.targetDir + "/" + circuit.name + ".fir") - Driver.dumpFirrtl(circuit, Option(output_file)) - } -} diff --git a/src/main/scala/chisel/compatibility.scala b/src/main/scala/chisel/compatibility.scala index 9cdef80d..6e72cdd3 100644 --- a/src/main/scala/chisel/compatibility.scala +++ b/src/main/scala/chisel/compatibility.scala @@ -23,9 +23,6 @@ package object Chisel { val assert = chisel.assert - val BitPat = chisel.BitPat - type BitPat = chisel.BitPat - type Element = chisel.Element type Bits = chisel.Bits val Bits = chisel.Bits @@ -59,10 +56,10 @@ package object Chisel { type BackendCompilationUtilities = chisel.BackendCompilationUtilities val Driver = chisel.Driver - type FileSystemUtilities = chisel.FileSystemUtilities - val ImplicitConversions = chisel.ImplicitConversions - val chiselMain = chisel.chiselMain - val throwException = chisel.throwException + type FileSystemUtilities = chisel.compatibility.FileSystemUtilities + val ImplicitConversions = chisel.util.ImplicitConversions + val chiselMain = chisel.compatibility.chiselMain + val throwException = chisel.compatibility.throwException object testers { @@ -77,6 +74,9 @@ package object Chisel { val log2Floor = chisel.util.log2Floor val isPow2 = chisel.util.isPow2 + val BitPat = chisel.util.BitPat + type BitPat = chisel.util.BitPat + type ArbiterIO[T <: Data] = chisel.util.ArbiterIO[T] type LockingArbiterLike[T <: Data] = chisel.util.LockingArbiterLike[T] type LockingRRArbiter[T <: Data] = chisel.util.LockingRRArbiter[T] diff --git a/src/main/scala/chisel/compatibility/FileSystemUtilities.scala b/src/main/scala/chisel/compatibility/FileSystemUtilities.scala new file mode 100644 index 00000000..d12e627d --- /dev/null +++ b/src/main/scala/chisel/compatibility/FileSystemUtilities.scala @@ -0,0 +1,12 @@ +// See LICENSE for license details. + +package chisel.compatibility + +import chisel._ + +@deprecated("FileSystemUtilities doesn't exist in chisel3", "3.0.0") +trait FileSystemUtilities { + def createOutputFile(name: String): java.io.FileWriter = { + new java.io.FileWriter(Driver.targetDir + "/" + name) + } +} diff --git a/src/main/scala/chisel/compatibility/Main.scala b/src/main/scala/chisel/compatibility/Main.scala new file mode 100644 index 00000000..9072bfcf --- /dev/null +++ b/src/main/scala/chisel/compatibility/Main.scala @@ -0,0 +1,19 @@ +// See LICENSE for license details. + +package chisel.compatibility + +import java.io.File + +import chisel._ + +@deprecated("chiselMain doesn't exist in Chisel3", "3.0") object chiselMain { + def apply[T <: Module](args: Array[String], gen: () => T): Unit = + Predef.assert(false, "No more chiselMain in Chisel3") + + def run[T <: Module] (args: Array[String], gen: () => T): Unit = { + val circuit = Driver.elaborate(gen) + Driver.parseArgs(args) + val output_file = new File(Driver.targetDir + "/" + circuit.name + ".fir") + Driver.dumpFirrtl(circuit, Option(output_file)) + } +} diff --git a/src/main/scala/chisel/compatibility/throwException.scala b/src/main/scala/chisel/compatibility/throwException.scala new file mode 100644 index 00000000..3b9fd06e --- /dev/null +++ b/src/main/scala/chisel/compatibility/throwException.scala @@ -0,0 +1,14 @@ +// See LICENSE for license details. + +package chisel.compatibility + +import chisel._ + +@deprecated("throwException doesn't exist in Chisel3", "3.0.0") +@throws(classOf[Exception]) +object throwException { + def apply(s: String, t: Throwable = null) = { + val xcpt = new Exception(s, t) + throw xcpt + } +} diff --git a/src/main/scala/chisel/package.scala b/src/main/scala/chisel/package.scala index 1abbc74f..b6036c75 100644 --- a/src/main/scala/chisel/package.scala +++ b/src/main/scala/chisel/package.scala @@ -3,6 +3,7 @@ package object chisel { import internal.firrtl.Width import internal.sourceinfo.{SourceInfo, SourceInfoTransform} + import util.BitPat implicit class fromBigIntToLiteral(val x: BigInt) extends AnyVal { def U: UInt = UInt(x, Width()) diff --git a/src/main/scala/chisel/throwException.scala b/src/main/scala/chisel/throwException.scala deleted file mode 100644 index fdd62c7e..00000000 --- a/src/main/scala/chisel/throwException.scala +++ /dev/null @@ -1,12 +0,0 @@ -// See LICENSE for license details. - -package chisel - -@deprecated("throwException doesn't exist in Chisel3", "3.0.0") -@throws(classOf[Exception]) -object throwException { - def apply(s: String, t: Throwable = null) = { - val xcpt = new Exception(s, t) - throw xcpt - } -} diff --git a/src/main/scala/chisel/util/BitPat.scala b/src/main/scala/chisel/util/BitPat.scala new file mode 100644 index 00000000..13bbe1b0 --- /dev/null +++ b/src/main/scala/chisel/util/BitPat.scala @@ -0,0 +1,89 @@ +// See LICENSE for license details. + +package chisel.util + +import scala.language.experimental.macros + +import chisel._ +import chisel.internal.sourceinfo.{SourceInfo, SourceInfoTransform} + +object BitPat { + /** Parses a bit pattern string into (bits, mask, width). + * + * @return bits the literal value, with don't cares being 0 + * @return mask the mask bits, with don't cares being 0 and cares being 1 + * @return width the number of bits in the literal, including values and + * don't cares. + */ + private def parse(x: String): (BigInt, BigInt, Int) = { + // Notes: + // While Verilog Xs also handle octal and hex cases, there isn't a + // compelling argument and no one has asked for it. + // If ? parsing is to be exposed, the return API needs further scrutiny + // (especially with things like mask polarity). + require(x.head == 'b', "BitPats must be in binary and be prefixed with 'b'") + var bits = BigInt(0) + var mask = BigInt(0) + for (d <- x.tail) { + if (d != '_') { + require("01?".contains(d), "Literal: " + x + " contains illegal character: " + d) + mask = (mask << 1) + (if (d == '?') 0 else 1) + bits = (bits << 1) + (if (d == '1') 1 else 0) + } + } + (bits, mask, x.length - 1) + } + + /** Creates a [[BitPat]] literal from a string. + * + * @param n the literal value as a string, in binary, prefixed with 'b' + * @note legal characters are '0', '1', and '?', as well as '_' as white + * space (which are ignored) + */ + def apply(n: String): BitPat = { + val (bits, mask, width) = parse(n) + new BitPat(bits, mask, width) + } + + /** Creates a [[BitPat]] of all don't cares of the specified bitwidth. */ + def dontCare(width: Int): BitPat = BitPat("b" + ("?" * width)) + + @deprecated("Use BitPat.dontCare", "chisel3") + def DC(width: Int): BitPat = dontCare(width) // scalastyle:ignore method.name + + /** Allows BitPats to be used where a UInt is expected. + * + * @note the BitPat must not have don't care bits (will error out otherwise) + */ + def bitPatToUInt(x: BitPat): UInt = { + require(x.mask == (BigInt(1) << x.getWidth) - 1) + UInt(x.value, x.getWidth) + } + + /** Allows UInts to be used where a BitPat is expected, useful for when an + * interface is defined with BitPats but not all cases need the partial + * matching capability. + * + * @note the UInt must be a literal + */ + def apply(x: UInt): BitPat = { + require(x.isLit) + BitPat("b" + x.litValue.toString(2)) + } +} + +// TODO: Break out of Core? (this doesn't involve FIRRTL generation) +/** Bit patterns are literals with masks, used to represent values with don't + * cares. Equality comparisons will ignore don't care bits (for example, + * BitPat(0b10?1) === UInt(0b1001) and UInt(0b1011)). + */ +sealed class BitPat(val value: BigInt, val mask: BigInt, width: Int) { + def getWidth: Int = width + 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/src/main/scala/chisel/util/ImplicitConversions.scala b/src/main/scala/chisel/util/ImplicitConversions.scala new file mode 100644 index 00000000..846c0cbd --- /dev/null +++ b/src/main/scala/chisel/util/ImplicitConversions.scala @@ -0,0 +1,10 @@ +// See LICENSE for license details. + +package chisel.util + +import chisel._ + +object ImplicitConversions { + implicit def intToUInt(x: Int): UInt = UInt(x) + implicit def booleanToBool(x: Boolean): Bool = Bool(x) +} -- cgit v1.2.3 From 69c984607e87cb62c82c99056b2664f11b968267 Mon Sep 17 00:00:00 2001 From: ducky Date: Wed, 1 Jun 2016 12:46:05 -0700 Subject: Package split chisel core --- .../src/main/scala/chisel/core/Aggregate.scala | 18 ++-- .../src/main/scala/chisel/core/Assert.scala | 10 +-- .../src/main/scala/chisel/core/Bits.scala | 32 ++++---- .../src/main/scala/chisel/core/BlackBox.scala | 14 ++-- .../src/main/scala/chisel/core/Data.scala | 26 +++--- .../src/main/scala/chisel/core/Mem.scala | 10 +-- .../src/main/scala/chisel/core/Module.scala | 24 +++--- .../src/main/scala/chisel/core/Printf.scala | 12 +-- .../src/main/scala/chisel/core/Reg.scala | 12 +-- .../src/main/scala/chisel/core/SeqUtils.scala | 4 +- .../src/main/scala/chisel/core/When.scala | 10 +-- .../src/main/scala/chisel/internal/Builder.scala | 1 + .../src/main/scala/chisel/internal/Error.scala | 2 +- .../src/main/scala/chisel/internal/firrtl/IR.scala | 1 + src/main/scala/chisel/compatibility.scala | 96 +++++++++++----------- src/main/scala/chisel/package.scala | 50 +++++++++++ src/main/scala/chisel/util/Bitwise.scala | 1 + src/main/scala/chisel/util/Cat.scala | 1 + src/main/scala/chisel/util/Mux.scala | 1 + 19 files changed, 190 insertions(+), 135 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel/core/Aggregate.scala b/chiselFrontend/src/main/scala/chisel/core/Aggregate.scala index 4f3f3de0..38a42fea 100644 --- a/chiselFrontend/src/main/scala/chisel/core/Aggregate.scala +++ b/chiselFrontend/src/main/scala/chisel/core/Aggregate.scala @@ -1,21 +1,21 @@ // See LICENSE for license details. -package chisel +package chisel.core 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} +import chisel.internal._ +import chisel.internal.Builder.pushCommand +import chisel.internal.firrtl._ +import chisel.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, VecTransform, SourceInfoTransform} /** 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 + private[core] def cloneTypeWidth(width: Width): this.type = cloneType def width: Width = flatten.map(_.width).reduce(_ + _) } @@ -315,7 +315,7 @@ class Bundle extends Aggregate(NO_DIR) { /** Returns a list of elements in this Bundle. */ - private[chisel] lazy val namedElts = { + private[core] lazy val namedElts = { val nameMap = LinkedHashMap[String, Data]() val seen = HashSet[Data]() for (m <- getClass.getMethods.sortWith(_.getName < _.getName)) { @@ -339,7 +339,7 @@ class Bundle extends Aggregate(NO_DIR) { 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 = + private[core] 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)) } @@ -372,6 +372,6 @@ class Bundle extends Aggregate(NO_DIR) { } } -private[chisel] object Bundle { +private[core] object Bundle { val keywords = List("flip", "asInput", "asOutput", "cloneType", "toBits") } diff --git a/chiselFrontend/src/main/scala/chisel/core/Assert.scala b/chiselFrontend/src/main/scala/chisel/core/Assert.scala index 0d660bc3..00cb00f4 100644 --- a/chiselFrontend/src/main/scala/chisel/core/Assert.scala +++ b/chiselFrontend/src/main/scala/chisel/core/Assert.scala @@ -1,14 +1,14 @@ // See LICENSE for license details. -package chisel +package chisel.core import scala.reflect.macros.blackbox.Context import scala.language.experimental.macros -import internal._ -import internal.Builder.pushCommand -import internal.firrtl._ -import internal.sourceinfo.SourceInfo +import chisel.internal._ +import chisel.internal.Builder.pushCommand +import chisel.internal.firrtl._ +import chisel.internal.sourceinfo.SourceInfo object assert { // scalastyle:ignore object.name /** Checks for a condition to be valid in the circuit at all times. If the diff --git a/chiselFrontend/src/main/scala/chisel/core/Bits.scala b/chiselFrontend/src/main/scala/chisel/core/Bits.scala index 8ec7c1b9..38e71f8d 100644 --- a/chiselFrontend/src/main/scala/chisel/core/Bits.scala +++ b/chiselFrontend/src/main/scala/chisel/core/Bits.scala @@ -1,15 +1,15 @@ // See LICENSE for license details. -package chisel +package chisel.core import scala.language.experimental.macros -import internal._ -import internal.Builder.pushOp -import internal.firrtl._ -import internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, SourceInfoTransform, SourceInfoWhiteboxTransform, +import chisel.internal._ +import chisel.internal.Builder.pushOp +import chisel.internal.firrtl._ +import chisel.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, SourceInfoTransform, SourceInfoWhiteboxTransform, UIntTransform, MuxTransform} -import firrtl.PrimOp._ +import chisel.internal.firrtl.PrimOp._ /** Element is a leaf data type: it cannot contain other Data objects. Example * uses are for representing primitive data types, like integers and bits. @@ -118,16 +118,16 @@ sealed abstract class Bits(dirArg: Direction, width: Width, override val litArg: 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 = + private[core] 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 = + private[core] 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 = + private[core] 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 = + private[core] 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 = + private[core] def redop(sourceInfo: SourceInfo, op: PrimOp): Bool = pushOp(DefPrim(sourceInfo, Bool(), op, this.ref)) /** Returns this wire zero padded up to the specified width. @@ -356,9 +356,9 @@ abstract trait Num[T <: Data] { /** A data type for unsigned integers, represented as a binary bitvector. * Defines arithmetic operations between other integer types. */ -sealed class UInt private[chisel] (dir: Direction, width: Width, lit: Option[ULit] = None) +sealed class UInt private[core] (dir: Direction, width: Width, lit: Option[ULit] = None) extends Bits(dir, width, lit) with Num[UInt] { - private[chisel] override def cloneTypeWidth(w: Width): this.type = + private[core] override def cloneTypeWidth(w: Width): this.type = new UInt(dir, w).asInstanceOf[this.type] private[chisel] def toType = s"UInt$width" @@ -482,7 +482,7 @@ sealed class UInt private[chisel] (dir: Direction, width: Width, lit: Option[ULi } // This is currently a factory because both Bits and UInt inherit it. -private[chisel] sealed trait UIntFactory { +private[core] sealed trait UIntFactory { /** Create a UInt type with inferred width. */ def apply(): UInt = apply(NO_DIR, Width()) /** Create a UInt type or port with fixed width. */ @@ -535,7 +535,7 @@ object UInt extends UIntFactory sealed class SInt private (dir: Direction, width: Width, lit: Option[SLit] = None) extends Bits(dir, width, lit) with Num[SInt] { - private[chisel] override def cloneTypeWidth(w: Width): this.type = + private[core] override def cloneTypeWidth(w: Width): this.type = new SInt(dir, w).asInstanceOf[this.type] private[chisel] def toType = s"SInt$width" @@ -666,7 +666,7 @@ object SInt { /** A data type for booleans, defined as a single bit indicating true or false. */ sealed class Bool(dir: Direction, lit: Option[ULit] = None) extends UInt(dir, Width(1), lit) { - private[chisel] override def cloneTypeWidth(w: Width): this.type = { + private[core] override def cloneTypeWidth(w: Width): this.type = { require(!w.known || w.get == 1) new Bool(dir).asInstanceOf[this.type] } diff --git a/chiselFrontend/src/main/scala/chisel/core/BlackBox.scala b/chiselFrontend/src/main/scala/chisel/core/BlackBox.scala index 1dabc18f..2126ebce 100644 --- a/chiselFrontend/src/main/scala/chisel/core/BlackBox.scala +++ b/chiselFrontend/src/main/scala/chisel/core/BlackBox.scala @@ -1,10 +1,10 @@ // See LICENSE for license details. -package chisel +package chisel.core -import internal.Builder.pushCommand -import internal.firrtl.{ModuleIO, DefInvalid} -import internal.sourceinfo.SourceInfo +import chisel.internal.Builder.pushCommand +import chisel.internal.firrtl.{ModuleIO, DefInvalid} +import chisel.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 @@ -24,10 +24,10 @@ abstract class BlackBox extends Module { // The body of a BlackBox is empty, the real logic happens in firrtl/Emitter.scala // Bypass standard clock, reset, io port declaration by flattening io // TODO(twigg): ? Really, overrides are bad, should extend BaseModule.... - override private[chisel] def ports = io.elements.toSeq + override private[core] def ports = io.elements.toSeq // Do not do reflective naming of internal signals, just name io - override private[chisel] def setRefs(): this.type = { + override private[core] def setRefs(): this.type = { for ((name, port) <- ports) { port.setRef(ModuleIO(this, _namespace.name(name))) } @@ -40,7 +40,7 @@ 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(implicit sourceInfo: SourceInfo): this.type = _parent match { + override private[core] def setupInParent(implicit sourceInfo: SourceInfo): this.type = _parent match { case Some(p) => { // Just init instance inputs for((_,port) <- ports) pushCommand(DefInvalid(sourceInfo, port.ref)) diff --git a/chiselFrontend/src/main/scala/chisel/core/Data.scala b/chiselFrontend/src/main/scala/chisel/core/Data.scala index c08adf9d..077c4893 100644 --- a/chiselFrontend/src/main/scala/chisel/core/Data.scala +++ b/chiselFrontend/src/main/scala/chisel/core/Data.scala @@ -1,13 +1,13 @@ // See LICENSE for license details. -package chisel +package chisel.core import scala.language.experimental.macros -import internal._ -import internal.Builder.pushCommand -import internal.firrtl._ -import internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, UnlocatableSourceInfo, WireTransform, SourceInfoTransform} +import chisel.internal._ +import chisel.internal.Builder.pushCommand +import chisel.internal.firrtl._ +import chisel.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, UnlocatableSourceInfo, WireTransform, SourceInfoTransform} sealed abstract class Direction(name: String) { override def toString: String = name @@ -38,9 +38,9 @@ abstract class Data(dirArg: Direction) extends HasId { // Sucks this is mutable state, but cloneType doesn't take a Direction arg private var isFlipVar = dirArg == INPUT private var dirVar = dirArg - private[chisel] def isFlip = isFlipVar + private[core] def isFlip = isFlipVar - private[chisel] def overrideDirection(newDir: Direction => Direction, + private[core] def overrideDirection(newDir: Direction => Direction, newFlip: Boolean => Boolean): this.type = { this.isFlipVar = newFlip(this.isFlipVar) for (field <- this.flatten) @@ -51,15 +51,15 @@ 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)(implicit sourceInfo: SourceInfo): Unit = + private[core] def badConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit = throwException(s"cannot connect ${this} and ${that}") - private[chisel] def connect(that: Data)(implicit sourceInfo: SourceInfo): Unit = + private[core] 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 = + private[core] def bulkConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit = pushCommand(BulkConnect(sourceInfo, this.lref, that.lref)) - private[chisel] def lref: Node = Node(this) + private[core] 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[core] def cloneTypeWidth(width: Width): this.type private[chisel] def toType: String def := (that: Data)(implicit sourceInfo: SourceInfo): Unit = this badConnect that @@ -151,7 +151,7 @@ object Clock { sealed class Clock(dirArg: Direction) extends Element(dirArg, Width(1)) { def cloneType: this.type = Clock(dirArg).asInstanceOf[this.type] private[chisel] override def flatten: IndexedSeq[Bits] = IndexedSeq() - private[chisel] def cloneTypeWidth(width: Width): this.type = cloneType + private[core] def cloneTypeWidth(width: Width): this.type = cloneType private[chisel] def toType = "Clock" override def := (that: Data)(implicit sourceInfo: SourceInfo): Unit = that match { diff --git a/chiselFrontend/src/main/scala/chisel/core/Mem.scala b/chiselFrontend/src/main/scala/chisel/core/Mem.scala index 5fd8b81e..a2df2910 100644 --- a/chiselFrontend/src/main/scala/chisel/core/Mem.scala +++ b/chiselFrontend/src/main/scala/chisel/core/Mem.scala @@ -1,13 +1,13 @@ // See LICENSE for license details. -package chisel +package chisel.core import scala.language.experimental.macros -import internal._ -import internal.Builder.pushCommand -import internal.firrtl._ -import internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, UnlocatableSourceInfo, MemTransform} +import chisel.internal._ +import chisel.internal.Builder.pushCommand +import chisel.internal.firrtl._ +import chisel.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") diff --git a/chiselFrontend/src/main/scala/chisel/core/Module.scala b/chiselFrontend/src/main/scala/chisel/core/Module.scala index f7f8c0b5..1de3efe5 100644 --- a/chiselFrontend/src/main/scala/chisel/core/Module.scala +++ b/chiselFrontend/src/main/scala/chisel/core/Module.scala @@ -1,15 +1,15 @@ // See LICENSE for license details. -package chisel +package chisel.core 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} +import chisel.internal._ +import chisel.internal.Builder.pushCommand +import chisel.internal.Builder.dynamicContext +import chisel.internal.firrtl._ +import chisel.internal.sourceinfo.{SourceInfo, InstTransform, UnlocatableSourceInfo} object Module { /** A wrapper method that all Module instantiations must be wrapped in @@ -52,9 +52,9 @@ extends HasId { def this(_reset: Bool) = this(None, Option(_reset)) def this(_clock: Clock, _reset: Bool) = this(Option(_clock), Option(_reset)) - private[chisel] val _namespace = Builder.globalNamespace.child + private[core] val _namespace = Builder.globalNamespace.child private[chisel] val _commands = ArrayBuffer[Command]() - private[chisel] val _ids = ArrayBuffer[HasId]() + private[core] val _ids = ArrayBuffer[HasId]() dynamicContext.currentModule = Some(this) /** Name of the instance. */ @@ -69,16 +69,16 @@ extends HasId { private[chisel] def addId(d: HasId) { _ids += d } - private[chisel] def ports: Seq[(String,Data)] = Vector( + private[core] def ports: Seq[(String,Data)] = Vector( ("clk", clock), ("reset", reset), ("io", io) ) - private[chisel] def computePorts = for((name, port) <- ports) yield { + private[core] def computePorts = for((name, port) <- ports) yield { val bundleDir = if (port.isFlip) INPUT else OUTPUT Port(port, if (port.dir == NO_DIR) bundleDir else port.dir) } - private[chisel] def setupInParent(implicit sourceInfo: SourceInfo): this.type = { + private[core] def setupInParent(implicit sourceInfo: SourceInfo): this.type = { _parent match { case Some(p) => { pushCommand(DefInvalid(sourceInfo, io.ref)) // init instance inputs @@ -90,7 +90,7 @@ extends HasId { } } - private[chisel] def setRefs(): this.type = { + private[core] def setRefs(): this.type = { for ((name, port) <- ports) { port.setRef(ModuleIO(this, _namespace.name(name))) } diff --git a/chiselFrontend/src/main/scala/chisel/core/Printf.scala b/chiselFrontend/src/main/scala/chisel/core/Printf.scala index 27b72815..a7970816 100644 --- a/chiselFrontend/src/main/scala/chisel/core/Printf.scala +++ b/chiselFrontend/src/main/scala/chisel/core/Printf.scala @@ -1,13 +1,13 @@ // See LICENSE for license details. -package chisel +package chisel.core import scala.language.experimental.macros -import internal._ -import internal.Builder.pushCommand -import internal.firrtl._ -import internal.sourceinfo.SourceInfo +import chisel.internal._ +import chisel.internal.Builder.pushCommand +import chisel.internal.firrtl._ +import chisel.internal.sourceinfo.SourceInfo object printf { // scalastyle:ignore object.name /** Prints a message in simulation. @@ -29,7 +29,7 @@ object printf { // scalastyle:ignore object.name } } - private[chisel] def printfWithoutReset(fmt: String, data: Bits*)(implicit sourceInfo: SourceInfo) { + private[core] 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/core/Reg.scala b/chiselFrontend/src/main/scala/chisel/core/Reg.scala index 0ed320d7..78461334 100644 --- a/chiselFrontend/src/main/scala/chisel/core/Reg.scala +++ b/chiselFrontend/src/main/scala/chisel/core/Reg.scala @@ -1,14 +1,14 @@ // See LICENSE for license details. -package chisel +package chisel.core -import internal._ -import internal.Builder.pushCommand -import internal.firrtl._ -import internal.sourceinfo.{SourceInfo, UnlocatableSourceInfo} +import chisel.internal._ +import chisel.internal.Builder.pushCommand +import chisel.internal.firrtl._ +import chisel.internal.sourceinfo.{SourceInfo, UnlocatableSourceInfo} object Reg { - private[chisel] def makeType[T <: Data](t: T = null, next: T = null, init: T = null): T = { + private[core] def makeType[T <: Data](t: T = null, next: T = null, init: T = null): T = { if (t ne null) { t.cloneType } else if (next ne null) { diff --git a/chiselFrontend/src/main/scala/chisel/core/SeqUtils.scala b/chiselFrontend/src/main/scala/chisel/core/SeqUtils.scala index da75edae..e31119a5 100644 --- a/chiselFrontend/src/main/scala/chisel/core/SeqUtils.scala +++ b/chiselFrontend/src/main/scala/chisel/core/SeqUtils.scala @@ -1,10 +1,10 @@ // See LICENSE for license details. -package chisel +package chisel.core import scala.language.experimental.macros -import internal.sourceinfo.{SourceInfo, SourceInfoTransform} +import chisel.internal.sourceinfo.{SourceInfo, SourceInfoTransform} private[chisel] object SeqUtils { /** Equivalent to Cat(r(n-1), ..., r(0)) */ diff --git a/chiselFrontend/src/main/scala/chisel/core/When.scala b/chiselFrontend/src/main/scala/chisel/core/When.scala index 37c59f24..5d484313 100644 --- a/chiselFrontend/src/main/scala/chisel/core/When.scala +++ b/chiselFrontend/src/main/scala/chisel/core/When.scala @@ -1,13 +1,13 @@ // See LICENSE for license details. -package chisel +package chisel.core import scala.language.experimental.macros -import internal._ -import internal.Builder.pushCommand -import internal.firrtl._ -import internal.sourceinfo.{SourceInfo} +import chisel.internal._ +import chisel.internal.Builder.pushCommand +import chisel.internal.firrtl._ +import chisel.internal.sourceinfo.{SourceInfo} object when { // scalastyle:ignore object.name /** Create a `when` condition block, where whether a block of logic is diff --git a/chiselFrontend/src/main/scala/chisel/internal/Builder.scala b/chiselFrontend/src/main/scala/chisel/internal/Builder.scala index bacde365..9c0a3514 100644 --- a/chiselFrontend/src/main/scala/chisel/internal/Builder.scala +++ b/chiselFrontend/src/main/scala/chisel/internal/Builder.scala @@ -6,6 +6,7 @@ import scala.util.DynamicVariable import scala.collection.mutable.{ArrayBuffer, HashMap} import chisel._ +import core._ import firrtl._ private[chisel] class Namespace(parent: Option[Namespace], keywords: Set[String]) { diff --git a/chiselFrontend/src/main/scala/chisel/internal/Error.scala b/chiselFrontend/src/main/scala/chisel/internal/Error.scala index 256a6d7f..f0481dc4 100644 --- a/chiselFrontend/src/main/scala/chisel/internal/Error.scala +++ b/chiselFrontend/src/main/scala/chisel/internal/Error.scala @@ -4,7 +4,7 @@ package chisel.internal import scala.collection.mutable.ArrayBuffer -import chisel._ +import chisel.core._ class ChiselException(message: String, cause: Throwable) extends Exception(message, cause) diff --git a/chiselFrontend/src/main/scala/chisel/internal/firrtl/IR.scala b/chiselFrontend/src/main/scala/chisel/internal/firrtl/IR.scala index 9c1ce98e..70e9938b 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 core._ import chisel.internal._ import chisel.internal.sourceinfo.{SourceInfo, NoSourceInfo} diff --git a/src/main/scala/chisel/compatibility.scala b/src/main/scala/chisel/compatibility.scala index 6e72cdd3..54cf033d 100644 --- a/src/main/scala/chisel/compatibility.scala +++ b/src/main/scala/chisel/compatibility.scala @@ -4,54 +4,54 @@ // moving to the more standard package naming convention chisel (lowercase c). package object Chisel { - type Direction = chisel.Direction - val INPUT = chisel.INPUT - val OUTPUT = chisel.OUTPUT - val NO_DIR = chisel.NO_DIR - val debug = chisel.debug - type Flipped = chisel.Flipped - type Data = chisel.Data - val Wire = chisel.Wire - val Clock = chisel.Clock - type Clock = chisel.Clock - - type Aggregate = chisel.Aggregate - val Vec = chisel.Vec - type Vec[T <: Data] = chisel.Vec[T] - type VecLike[T <: Data] = chisel.VecLike[T] - type Bundle = chisel.Bundle - - val assert = chisel.assert - - type Element = chisel.Element - type Bits = chisel.Bits - val Bits = chisel.Bits - type Num[T <: Data] = chisel.Num[T] - type UInt = chisel.UInt - val UInt = chisel.UInt - type SInt = chisel.SInt - val SInt = chisel.SInt - type Bool = chisel.Bool - val Bool = chisel.Bool - val Mux = chisel.Mux - - type BlackBox = chisel.BlackBox - - val Mem = chisel.Mem - type MemBase[T <: Data] = chisel.MemBase[T] - type Mem[T <: Data] = chisel.Mem[T] - val SeqMem = chisel.SeqMem - type SeqMem[T <: Data] = chisel.SeqMem[T] - - val Module = chisel.Module - type Module = chisel.Module - - val printf = chisel.printf - - val Reg = chisel.Reg - - val when = chisel.when - type WhenContext = chisel.WhenContext + type Direction = chisel.core.Direction + val INPUT = chisel.core.INPUT + val OUTPUT = chisel.core.OUTPUT + val NO_DIR = chisel.core.NO_DIR + val debug = chisel.core.debug + type Flipped = chisel.core.Flipped + type Data = chisel.core.Data + val Wire = chisel.core.Wire + val Clock = chisel.core.Clock + type Clock = chisel.core.Clock + + type Aggregate = chisel.core.Aggregate + val Vec = chisel.core.Vec + type Vec[T <: Data] = chisel.core.Vec[T] + type VecLike[T <: Data] = chisel.core.VecLike[T] + type Bundle = chisel.core.Bundle + + val assert = chisel.core.assert + + type Element = chisel.core.Element + type Bits = chisel.core.Bits + val Bits = chisel.core.Bits + type Num[T <: Data] = chisel.core.Num[T] + type UInt = chisel.core.UInt + val UInt = chisel.core.UInt + type SInt = chisel.core.SInt + val SInt = chisel.core.SInt + type Bool = chisel.core.Bool + val Bool = chisel.core.Bool + val Mux = chisel.core.Mux + + type BlackBox = chisel.core.BlackBox + + val Mem = chisel.core.Mem + type MemBase[T <: Data] = chisel.core.MemBase[T] + type Mem[T <: Data] = chisel.core.Mem[T] + val SeqMem = chisel.core.SeqMem + type SeqMem[T <: Data] = chisel.core.SeqMem[T] + + val Module = chisel.core.Module + type Module = chisel.core.Module + + val printf = chisel.core.printf + + val Reg = chisel.core.Reg + + val when = chisel.core.when + type WhenContext = chisel.core.WhenContext type BackendCompilationUtilities = chisel.BackendCompilationUtilities diff --git a/src/main/scala/chisel/package.scala b/src/main/scala/chisel/package.scala index b6036c75..f7ed6b13 100644 --- a/src/main/scala/chisel/package.scala +++ b/src/main/scala/chisel/package.scala @@ -5,6 +5,56 @@ package object chisel { import internal.sourceinfo.{SourceInfo, SourceInfoTransform} import util.BitPat + + type Direction = chisel.core.Direction + val INPUT = chisel.core.INPUT + val OUTPUT = chisel.core.OUTPUT + val NO_DIR = chisel.core.NO_DIR + type Flipped = chisel.core.Flipped + type Data = chisel.core.Data + val Wire = chisel.core.Wire + val Clock = chisel.core.Clock + type Clock = chisel.core.Clock + + type Aggregate = chisel.core.Aggregate + val Vec = chisel.core.Vec + type Vec[T <: Data] = chisel.core.Vec[T] + type VecLike[T <: Data] = chisel.core.VecLike[T] + type Bundle = chisel.core.Bundle + + val assert = chisel.core.assert + + type Element = chisel.core.Element + type Bits = chisel.core.Bits + val Bits = chisel.core.Bits + type Num[T <: Data] = chisel.core.Num[T] + type UInt = chisel.core.UInt + val UInt = chisel.core.UInt + type SInt = chisel.core.SInt + val SInt = chisel.core.SInt + type Bool = chisel.core.Bool + val Bool = chisel.core.Bool + val Mux = chisel.core.Mux + + type BlackBox = chisel.core.BlackBox + + val Mem = chisel.core.Mem + type MemBase[T <: Data] = chisel.core.MemBase[T] + type Mem[T <: Data] = chisel.core.Mem[T] + val SeqMem = chisel.core.SeqMem + type SeqMem[T <: Data] = chisel.core.SeqMem[T] + + val Module = chisel.core.Module + type Module = chisel.core.Module + + val printf = chisel.core.printf + + val Reg = chisel.core.Reg + + val when = chisel.core.when + type WhenContext = chisel.core.WhenContext + + implicit class fromBigIntToLiteral(val x: BigInt) extends AnyVal { def U: UInt = UInt(x, Width()) def S: SInt = SInt(x, Width()) diff --git a/src/main/scala/chisel/util/Bitwise.scala b/src/main/scala/chisel/util/Bitwise.scala index 94413fc7..d7d62ea3 100644 --- a/src/main/scala/chisel/util/Bitwise.scala +++ b/src/main/scala/chisel/util/Bitwise.scala @@ -6,6 +6,7 @@ package chisel.util import chisel._ +import chisel.core.SeqUtils object FillInterleaved { diff --git a/src/main/scala/chisel/util/Cat.scala b/src/main/scala/chisel/util/Cat.scala index 5b3c613e..b47da706 100644 --- a/src/main/scala/chisel/util/Cat.scala +++ b/src/main/scala/chisel/util/Cat.scala @@ -3,6 +3,7 @@ package chisel.util import chisel._ +import chisel.core.SeqUtils object Cat { /** Combine data elements together diff --git a/src/main/scala/chisel/util/Mux.scala b/src/main/scala/chisel/util/Mux.scala index cfff4485..6f074a7e 100644 --- a/src/main/scala/chisel/util/Mux.scala +++ b/src/main/scala/chisel/util/Mux.scala @@ -6,6 +6,7 @@ package chisel.util import chisel._ +import chisel.core.SeqUtils /** Builds a Mux tree out of the input signal vector using a one hot encoded select signal. Returns the output of the Mux tree. -- cgit v1.2.3 From 68447044e8eba5c8f525639130f1a347677ff543 Mon Sep 17 00:00:00 2001 From: ducky Date: Wed, 1 Jun 2016 13:00:40 -0700 Subject: Move deprecated debug into compatibility --- chiselFrontend/src/main/scala/chisel/core/Data.scala | 5 ----- src/main/scala/chisel/compatibility.scala | 4 ++-- src/main/scala/chisel/compatibility/debug.scala | 8 ++++++++ 3 files changed, 10 insertions(+), 7 deletions(-) create mode 100644 src/main/scala/chisel/compatibility/debug.scala diff --git a/chiselFrontend/src/main/scala/chisel/core/Data.scala b/chiselFrontend/src/main/scala/chisel/core/Data.scala index 077c4893..cae38144 100644 --- a/chiselFrontend/src/main/scala/chisel/core/Data.scala +++ b/chiselFrontend/src/main/scala/chisel/core/Data.scala @@ -17,11 +17,6 @@ object INPUT extends Direction("input") { override def flip: Direction = OUTPUT object OUTPUT extends Direction("output") { override def flip: Direction = INPUT } object NO_DIR extends Direction("?") { override def flip: Direction = NO_DIR } -@deprecated("debug doesn't do anything in Chisel3 as no pruning happens in the frontend", "chisel3") -object debug { // scalastyle:ignore object.name - def apply (arg: Data): Data = arg -} - /** Mixing in this trait flips the direction of an Aggregate. */ trait Flipped extends Data { this.overrideDirection(_.flip, !_) diff --git a/src/main/scala/chisel/compatibility.scala b/src/main/scala/chisel/compatibility.scala index 54cf033d..56088562 100644 --- a/src/main/scala/chisel/compatibility.scala +++ b/src/main/scala/chisel/compatibility.scala @@ -8,7 +8,7 @@ package object Chisel { val INPUT = chisel.core.INPUT val OUTPUT = chisel.core.OUTPUT val NO_DIR = chisel.core.NO_DIR - val debug = chisel.core.debug + type Flipped = chisel.core.Flipped type Data = chisel.core.Data val Wire = chisel.core.Wire @@ -60,7 +60,7 @@ package object Chisel { val ImplicitConversions = chisel.util.ImplicitConversions val chiselMain = chisel.compatibility.chiselMain val throwException = chisel.compatibility.throwException - + val debug = chisel.compatibility.debug object testers { type BasicTester = chisel.testers.BasicTester diff --git a/src/main/scala/chisel/compatibility/debug.scala b/src/main/scala/chisel/compatibility/debug.scala new file mode 100644 index 00000000..8850c76b --- /dev/null +++ b/src/main/scala/chisel/compatibility/debug.scala @@ -0,0 +1,8 @@ +package chisel.compatibility + +import chisel.core._ + +@deprecated("debug doesn't do anything in Chisel3 as no pruning happens in the frontend", "chisel3") +object debug { // scalastyle:ignore object.name + def apply (arg: Data): Data = arg +} -- cgit v1.2.3 From b5a534914795d9d17f4dfe623525f1b804e4c60f Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Wed, 15 Jun 2016 10:54:15 -0700 Subject: Generate better node names when names collide (#221) Rather than using a global counter, memoize the last returned value for colliding names to generate smaller sequence numbers.--- .../src/main/scala/chisel/internal/Builder.scala | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel/internal/Builder.scala b/chiselFrontend/src/main/scala/chisel/internal/Builder.scala index 9c0a3514..01628105 100644 --- a/chiselFrontend/src/main/scala/chisel/internal/Builder.scala +++ b/chiselFrontend/src/main/scala/chisel/internal/Builder.scala @@ -10,21 +10,26 @@ import core._ import firrtl._ private[chisel] class Namespace(parent: Option[Namespace], keywords: Set[String]) { - private var i = 0L - private val names = collection.mutable.HashSet[String]() - - private def rename(n: String) = { i += 1; s"${n}_${i}" } + private val names = collection.mutable.HashMap[String, Long]() + for (keyword <- keywords) + names(keyword) = 1 + + private def rename(n: String): String = { + val index = names.getOrElse(n, 1L) + val tryName = s"${n}_${index}" + names(n) = index + 1 + if (this contains tryName) rename(n) else tryName + } def contains(elem: String): Boolean = { - keywords.contains(elem) || names.contains(elem) || - parent.map(_ contains elem).getOrElse(false) + names.contains(elem) || parent.map(_ contains elem).getOrElse(false) } def name(elem: String): String = { if (this contains elem) { name(rename(elem)) } else { - names += elem + names(elem) = 1 elem } } -- cgit v1.2.3 From d408d73a171535bd7c2ba9d0037c194022b8a62f Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Mon, 20 Jun 2016 11:08:46 -0700 Subject: Rename chisel3 package. --- .../src/main/scala/chisel/core/Aggregate.scala | 377 ---------- .../src/main/scala/chisel/core/Assert.scala | 73 -- .../src/main/scala/chisel/core/Bits.scala | 756 --------------------- .../src/main/scala/chisel/core/BlackBox.scala | 55 -- .../src/main/scala/chisel/core/Data.scala | 156 ----- .../src/main/scala/chisel/core/Mem.scala | 134 ---- .../src/main/scala/chisel/core/Module.scala | 119 ---- .../src/main/scala/chisel/core/Printf.scala | 36 - .../src/main/scala/chisel/core/Reg.scala | 71 -- .../src/main/scala/chisel/core/SeqUtils.scala | 59 -- .../src/main/scala/chisel/core/When.scala | 59 -- .../src/main/scala/chisel/internal/Builder.scala | 129 ---- .../src/main/scala/chisel/internal/Error.scala | 91 --- .../main/scala/chisel/internal/SourceInfo.scala | 51 -- .../src/main/scala/chisel/internal/firrtl/IR.scala | 190 ------ .../src/main/scala/chisel3/core/Aggregate.scala | 377 ++++++++++ .../src/main/scala/chisel3/core/Assert.scala | 73 ++ .../src/main/scala/chisel3/core/Bits.scala | 756 +++++++++++++++++++++ .../src/main/scala/chisel3/core/BlackBox.scala | 55 ++ .../src/main/scala/chisel3/core/Data.scala | 156 +++++ .../src/main/scala/chisel3/core/Mem.scala | 134 ++++ .../src/main/scala/chisel3/core/Module.scala | 119 ++++ .../src/main/scala/chisel3/core/Printf.scala | 36 + .../src/main/scala/chisel3/core/Reg.scala | 71 ++ .../src/main/scala/chisel3/core/SeqUtils.scala | 59 ++ .../src/main/scala/chisel3/core/When.scala | 59 ++ .../src/main/scala/chisel3/internal/Builder.scala | 129 ++++ .../src/main/scala/chisel3/internal/Error.scala | 91 +++ .../main/scala/chisel3/internal/SourceInfo.scala | 51 ++ .../main/scala/chisel3/internal/firrtl/IR.scala | 190 ++++++ .../internal/sourceinfo/SourceInfoTransform.scala | 156 ----- .../internal/sourceinfo/SourceInfoTransform.scala | 156 +++++ src/main/scala/chisel/Driver.scala | 132 ---- src/main/scala/chisel/compatibility.scala | 150 ---- .../chisel/compatibility/FileSystemUtilities.scala | 12 - src/main/scala/chisel/compatibility/Main.scala | 19 - src/main/scala/chisel/compatibility/debug.scala | 8 - .../chisel/compatibility/throwException.scala | 14 - .../scala/chisel/internal/firrtl/Emitter.scala | 112 --- src/main/scala/chisel/package.scala | 82 --- src/main/scala/chisel/testers/BasicTester.scala | 38 -- src/main/scala/chisel/testers/TesterDriver.scala | 69 -- src/main/scala/chisel/util/Arbiter.scala | 119 ---- src/main/scala/chisel/util/BitPat.scala | 89 --- src/main/scala/chisel/util/Bitwise.scala | 74 -- src/main/scala/chisel/util/Cat.scala | 21 - src/main/scala/chisel/util/CircuitMath.scala | 28 - src/main/scala/chisel/util/Conditional.scala | 73 -- src/main/scala/chisel/util/Counter.scala | 46 -- src/main/scala/chisel/util/Decoupled.scala | 185 ----- src/main/scala/chisel/util/Enum.scala | 23 - .../scala/chisel/util/ImplicitConversions.scala | 10 - src/main/scala/chisel/util/LFSR.scala | 24 - src/main/scala/chisel/util/Lookup.scala | 19 - src/main/scala/chisel/util/Math.scala | 44 -- src/main/scala/chisel/util/Mux.scala | 64 -- src/main/scala/chisel/util/OneHot.scala | 64 -- src/main/scala/chisel/util/Reg.scala | 57 -- src/main/scala/chisel/util/TransitName.scala | 22 - src/main/scala/chisel/util/Valid.scala | 61 -- src/main/scala/chisel3/Driver.scala | 132 ++++ src/main/scala/chisel3/compatibility.scala | 150 ++++ .../compatibility/FileSystemUtilities.scala | 12 + src/main/scala/chisel3/compatibility/Main.scala | 19 + src/main/scala/chisel3/compatibility/debug.scala | 8 + .../chisel3/compatibility/throwException.scala | 14 + .../scala/chisel3/internal/firrtl/Emitter.scala | 112 +++ src/main/scala/chisel3/package.scala | 82 +++ src/main/scala/chisel3/testers/BasicTester.scala | 38 ++ src/main/scala/chisel3/testers/TesterDriver.scala | 69 ++ src/main/scala/chisel3/util/Arbiter.scala | 119 ++++ src/main/scala/chisel3/util/BitPat.scala | 89 +++ src/main/scala/chisel3/util/Bitwise.scala | 74 ++ src/main/scala/chisel3/util/Cat.scala | 21 + src/main/scala/chisel3/util/CircuitMath.scala | 28 + src/main/scala/chisel3/util/Conditional.scala | 73 ++ src/main/scala/chisel3/util/Counter.scala | 46 ++ src/main/scala/chisel3/util/Decoupled.scala | 185 +++++ src/main/scala/chisel3/util/Enum.scala | 23 + .../scala/chisel3/util/ImplicitConversions.scala | 10 + src/main/scala/chisel3/util/LFSR.scala | 24 + src/main/scala/chisel3/util/Lookup.scala | 19 + src/main/scala/chisel3/util/Math.scala | 44 ++ src/main/scala/chisel3/util/Mux.scala | 64 ++ src/main/scala/chisel3/util/OneHot.scala | 64 ++ src/main/scala/chisel3/util/Reg.scala | 57 ++ src/main/scala/chisel3/util/TransitName.scala | 22 + src/main/scala/chisel3/util/Valid.scala | 61 ++ 88 files changed, 4171 insertions(+), 4171 deletions(-) delete mode 100644 chiselFrontend/src/main/scala/chisel/core/Aggregate.scala delete mode 100644 chiselFrontend/src/main/scala/chisel/core/Assert.scala delete mode 100644 chiselFrontend/src/main/scala/chisel/core/Bits.scala delete mode 100644 chiselFrontend/src/main/scala/chisel/core/BlackBox.scala delete mode 100644 chiselFrontend/src/main/scala/chisel/core/Data.scala delete mode 100644 chiselFrontend/src/main/scala/chisel/core/Mem.scala delete mode 100644 chiselFrontend/src/main/scala/chisel/core/Module.scala delete mode 100644 chiselFrontend/src/main/scala/chisel/core/Printf.scala delete mode 100644 chiselFrontend/src/main/scala/chisel/core/Reg.scala delete mode 100644 chiselFrontend/src/main/scala/chisel/core/SeqUtils.scala delete mode 100644 chiselFrontend/src/main/scala/chisel/core/When.scala delete mode 100644 chiselFrontend/src/main/scala/chisel/internal/Builder.scala delete mode 100644 chiselFrontend/src/main/scala/chisel/internal/Error.scala delete mode 100644 chiselFrontend/src/main/scala/chisel/internal/SourceInfo.scala delete mode 100644 chiselFrontend/src/main/scala/chisel/internal/firrtl/IR.scala create mode 100644 chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala create mode 100644 chiselFrontend/src/main/scala/chisel3/core/Assert.scala create mode 100644 chiselFrontend/src/main/scala/chisel3/core/Bits.scala create mode 100644 chiselFrontend/src/main/scala/chisel3/core/BlackBox.scala create mode 100644 chiselFrontend/src/main/scala/chisel3/core/Data.scala create mode 100644 chiselFrontend/src/main/scala/chisel3/core/Mem.scala create mode 100644 chiselFrontend/src/main/scala/chisel3/core/Module.scala create mode 100644 chiselFrontend/src/main/scala/chisel3/core/Printf.scala create mode 100644 chiselFrontend/src/main/scala/chisel3/core/Reg.scala create mode 100644 chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala create mode 100644 chiselFrontend/src/main/scala/chisel3/core/When.scala create mode 100644 chiselFrontend/src/main/scala/chisel3/internal/Builder.scala create mode 100644 chiselFrontend/src/main/scala/chisel3/internal/Error.scala create mode 100644 chiselFrontend/src/main/scala/chisel3/internal/SourceInfo.scala create mode 100644 chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala delete mode 100644 coreMacros/src/main/scala/chisel/internal/sourceinfo/SourceInfoTransform.scala create mode 100644 coreMacros/src/main/scala/chisel3/internal/sourceinfo/SourceInfoTransform.scala delete mode 100644 src/main/scala/chisel/Driver.scala delete mode 100644 src/main/scala/chisel/compatibility.scala delete mode 100644 src/main/scala/chisel/compatibility/FileSystemUtilities.scala delete mode 100644 src/main/scala/chisel/compatibility/Main.scala delete mode 100644 src/main/scala/chisel/compatibility/debug.scala delete mode 100644 src/main/scala/chisel/compatibility/throwException.scala delete mode 100644 src/main/scala/chisel/internal/firrtl/Emitter.scala delete mode 100644 src/main/scala/chisel/package.scala delete mode 100644 src/main/scala/chisel/testers/BasicTester.scala delete mode 100644 src/main/scala/chisel/testers/TesterDriver.scala delete mode 100644 src/main/scala/chisel/util/Arbiter.scala delete mode 100644 src/main/scala/chisel/util/BitPat.scala delete mode 100644 src/main/scala/chisel/util/Bitwise.scala delete mode 100644 src/main/scala/chisel/util/Cat.scala delete mode 100644 src/main/scala/chisel/util/CircuitMath.scala delete mode 100644 src/main/scala/chisel/util/Conditional.scala delete mode 100644 src/main/scala/chisel/util/Counter.scala delete mode 100644 src/main/scala/chisel/util/Decoupled.scala delete mode 100644 src/main/scala/chisel/util/Enum.scala delete mode 100644 src/main/scala/chisel/util/ImplicitConversions.scala delete mode 100644 src/main/scala/chisel/util/LFSR.scala delete mode 100644 src/main/scala/chisel/util/Lookup.scala delete mode 100644 src/main/scala/chisel/util/Math.scala delete mode 100644 src/main/scala/chisel/util/Mux.scala delete mode 100644 src/main/scala/chisel/util/OneHot.scala delete mode 100644 src/main/scala/chisel/util/Reg.scala delete mode 100644 src/main/scala/chisel/util/TransitName.scala delete mode 100644 src/main/scala/chisel/util/Valid.scala create mode 100644 src/main/scala/chisel3/Driver.scala create mode 100644 src/main/scala/chisel3/compatibility.scala create mode 100644 src/main/scala/chisel3/compatibility/FileSystemUtilities.scala create mode 100644 src/main/scala/chisel3/compatibility/Main.scala create mode 100644 src/main/scala/chisel3/compatibility/debug.scala create mode 100644 src/main/scala/chisel3/compatibility/throwException.scala create mode 100644 src/main/scala/chisel3/internal/firrtl/Emitter.scala create mode 100644 src/main/scala/chisel3/package.scala create mode 100644 src/main/scala/chisel3/testers/BasicTester.scala create mode 100644 src/main/scala/chisel3/testers/TesterDriver.scala create mode 100644 src/main/scala/chisel3/util/Arbiter.scala create mode 100644 src/main/scala/chisel3/util/BitPat.scala create mode 100644 src/main/scala/chisel3/util/Bitwise.scala create mode 100644 src/main/scala/chisel3/util/Cat.scala create mode 100644 src/main/scala/chisel3/util/CircuitMath.scala create mode 100644 src/main/scala/chisel3/util/Conditional.scala create mode 100644 src/main/scala/chisel3/util/Counter.scala create mode 100644 src/main/scala/chisel3/util/Decoupled.scala create mode 100644 src/main/scala/chisel3/util/Enum.scala create mode 100644 src/main/scala/chisel3/util/ImplicitConversions.scala create mode 100644 src/main/scala/chisel3/util/LFSR.scala create mode 100644 src/main/scala/chisel3/util/Lookup.scala create mode 100644 src/main/scala/chisel3/util/Math.scala create mode 100644 src/main/scala/chisel3/util/Mux.scala create mode 100644 src/main/scala/chisel3/util/OneHot.scala create mode 100644 src/main/scala/chisel3/util/Reg.scala create mode 100644 src/main/scala/chisel3/util/TransitName.scala create mode 100644 src/main/scala/chisel3/util/Valid.scala diff --git a/chiselFrontend/src/main/scala/chisel/core/Aggregate.scala b/chiselFrontend/src/main/scala/chisel/core/Aggregate.scala deleted file mode 100644 index 38a42fea..00000000 --- a/chiselFrontend/src/main/scala/chisel/core/Aggregate.scala +++ /dev/null @@ -1,377 +0,0 @@ -// See LICENSE for license details. - -package chisel.core - -import scala.collection.immutable.ListMap -import scala.collection.mutable.{ArrayBuffer, HashSet, LinkedHashMap} -import scala.language.experimental.macros - -import chisel.internal._ -import chisel.internal.Builder.pushCommand -import chisel.internal.firrtl._ -import chisel.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, VecTransform, SourceInfoTransform} - -/** 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[core] 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] = 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)) - 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] = 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 - * 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] = 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 - * 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] = 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 - * 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)(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])(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])(implicit sourceInfo: SourceInfo): Unit = this := that.asInstanceOf[Data] - - override def := (that: Data)(implicit sourceInfo: SourceInfo): 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])(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])(implicit sourceInfo: SourceInfo): 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)(DeprecatedSourceInfo) - - 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] 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 - - @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 = 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 = 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 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 = 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. - */ - 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 = 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 = 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. - * - * 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 = 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. - * - * 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)(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)(implicit sourceInfo: SourceInfo): 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[core] 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[core] 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[core] object Bundle { - val keywords = List("flip", "asInput", "asOutput", "cloneType", "toBits") -} diff --git a/chiselFrontend/src/main/scala/chisel/core/Assert.scala b/chiselFrontend/src/main/scala/chisel/core/Assert.scala deleted file mode 100644 index 00cb00f4..00000000 --- a/chiselFrontend/src/main/scala/chisel/core/Assert.scala +++ /dev/null @@ -1,73 +0,0 @@ -// See LICENSE for license details. - -package chisel.core - -import scala.reflect.macros.blackbox.Context -import scala.language.experimental.macros - -import chisel.internal._ -import chisel.internal.Builder.pushCommand -import chisel.internal.firrtl._ -import chisel.internal.sourceinfo.SourceInfo - -object assert { // scalastyle:ignore object.name - /** Checks for a condition to be valid in the circuit at all times. If the - * condition evaluates to false, the circuit simulation stops with an error. - * - * 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 assert make the standard Module assumptions (single clock - * and single reset). - * - * @param cond condition, assertion fires (simulation fails) when false - * @param message optional message to print when the assertion fires - * - * @note currently cannot be used in core Chisel / libraries because macro - * defs need to be compiled first and the SBT project is not set up to do - * that - */ - // 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)(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))($sourceInfo)" - } - - 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)($sourceInfo)" - } - - 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(sourceInfo, Node(Builder.dynamicContext.currentModule.get.clock), 1)) - } - } - - /** An elaboration-time assertion, otherwise the same as the above run-time - * assertion. */ - def apply(cond: Boolean, message: => String) { - Predef.assert(cond, message) - } - - /** A workaround for default-value overloading problems in Scala, just - * 'assert(cond, "")' */ - def apply(cond: Boolean) { - Predef.assert(cond, "") - } -} diff --git a/chiselFrontend/src/main/scala/chisel/core/Bits.scala b/chiselFrontend/src/main/scala/chisel/core/Bits.scala deleted file mode 100644 index 38e71f8d..00000000 --- a/chiselFrontend/src/main/scala/chisel/core/Bits.scala +++ /dev/null @@ -1,756 +0,0 @@ -// See LICENSE for license details. - -package chisel.core - -import scala.language.experimental.macros - -import chisel.internal._ -import chisel.internal.Builder.pushOp -import chisel.internal.firrtl._ -import chisel.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, SourceInfoTransform, SourceInfoWhiteboxTransform, - UIntTransform, MuxTransform} -import chisel.internal.firrtl.PrimOp._ - -/** Element is a leaf data type: it cannot contain other Data objects. Example - * uses are for representing primitive data types, like integers and bits. - */ -abstract class Element(dirArg: Direction, val width: Width) extends Data(dirArg) - -/** A data type for values represented by a single bitvector. Provides basic - * bitwise operations. - */ -sealed abstract class Bits(dirArg: Direction, width: Width, override val litArg: Option[LitArg]) - extends Element(dirArg, width) { - // TODO: perhaps make this concrete? - // Arguments for: self-checking code (can't do arithmetic on bits) - // Arguments against: generates down to a FIRRTL UInt anyways - - private[chisel] def fromInt(x: BigInt, w: Int): this.type - - private[chisel] def flatten: IndexedSeq[Bits] = IndexedSeq(this) - - def cloneType: this.type = cloneTypeWidth(width) - - 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 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(sourceInfo, UInt(width = w), TailOp, n) - } - - - 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(sourceInfo, UInt(width = n), HeadOp, n) - } - - /** Returns the specified bit on this wire as a [[Bool]], statically - * addressed. - */ - 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(sourceInfo, Bool(), BitsExtractOp, this.ref, ILit(x), ILit(x))) - } - } - - /** Returns the specified bit on this wire as a [[Bool]], statically - * addressed. - * - * @note convenience method allowing direct use of Ints without implicits - */ - 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 = 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. - * - * @example - * {{{ - * myBits = 0x5 = 0b101 - * myBits(1,0) => 0b01 // extracts the two least significant bits - * }}} - */ - 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)") - } - val w = x - y + 1 - if (isLit()) { - UInt((litValue >> y) & ((BigInt(1) << w) - 1), w) - } else { - 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 = macro SourceInfoTransform.xyArg - - final def do_apply(x: BigInt, y: BigInt)(implicit sourceInfo: SourceInfo): UInt = - apply(x.toInt, y.toInt) - - private[core] def unop[T <: Data](sourceInfo: SourceInfo, dest: T, op: PrimOp): T = - pushOp(DefPrim(sourceInfo, dest, op, this.ref)) - private[core] def binop[T <: Data](sourceInfo: SourceInfo, dest: T, op: PrimOp, other: BigInt): T = - pushOp(DefPrim(sourceInfo, dest, op, this.ref, ILit(other))) - private[core] def binop[T <: Data](sourceInfo: SourceInfo, dest: T, op: PrimOp, other: Bits): T = - pushOp(DefPrim(sourceInfo, dest, op, this.ref, other.ref)) - - private[core] def compop(sourceInfo: SourceInfo, op: PrimOp, other: Bits): Bool = - pushOp(DefPrim(sourceInfo, Bool(), op, this.ref, other.ref)) - private[core] 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 - */ - 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? - 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. - */ - 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. - */ - final def << (that: UInt): Bits = macro SourceInfoWhiteboxTransform.thatArg - - def do_<< (that: UInt)(implicit sourceInfo: SourceInfo): Bits - - /** Shift right operation */ - // REVIEW TODO: redundant - 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. - */ - 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. - */ - 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. - */ - 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 - */ - 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 - */ - final def asUInt(): UInt = macro SourceInfoTransform.noArg - - def do_asUInt(implicit sourceInfo: SourceInfo): UInt - - /** Reinterpret cast to Bits. */ - 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 = do_asSInt(DeprecatedSourceInfo) - @deprecated("Use asUInt, which makes the reinterpret cast more explicit", "chisel3") - final def toUInt(): UInt = do_asUInt(DeprecatedSourceInfo) - - final def toBool(): Bool = macro SourceInfoTransform.noArg - - 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. - */ - 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 = do_asUInt(DeprecatedSourceInfo) - - override def do_fromBits(that: Bits)(implicit sourceInfo: SourceInfo): this.type = { - val res = Wire(this, null).asInstanceOf[this.type] - res := that - res - } -} - -/** Provides a set of operations to create UInt types and literals. - * Identical in functionality to the UInt companion object. - */ -object Bits extends UIntFactory - -// REVIEW TODO: Further discussion needed on what Num actually is. -/** Abstract trait defining operations available on numeric-like wire data - * types. - */ -abstract trait Num[T <: Data] { - // def << (b: T): T - // def >> (b: T): T - //def unary_-(): T - - // REVIEW TODO: double check ops conventions against FIRRTL - - /** Outputs the sum of `this` and `b`. The resulting width is the max of the - * operands plus 1 (should not overflow). - */ - 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. - * - * @note can generate a single-cycle multiplier, which can result in - * significant cycle time and area costs - */ - 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 - */ - final def / (that: T): T = macro SourceInfoTransform.thatArg - - 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). - */ - final def - (that: T): T = macro SourceInfoTransform.thatArg - - def do_- (that: T)(implicit sourceInfo: SourceInfo): T - - /** Outputs true if `this` < `b`. - */ - final def < (that: T): Bool = macro SourceInfoTransform.thatArg - - def do_< (that: T)(implicit sourceInfo: SourceInfo): Bool - - /** Outputs true if `this` <= `b`. - */ - final def <= (that: T): Bool = macro SourceInfoTransform.thatArg - - def do_<= (that: T)(implicit sourceInfo: SourceInfo): Bool - - /** Outputs true if `this` > `b`. - */ - final def > (that: T): Bool = macro SourceInfoTransform.thatArg - - def do_> (that: T)(implicit sourceInfo: SourceInfo): Bool - - /** Outputs true if `this` >= `b`. - */ - 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. - */ - 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. - */ - 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. - * Defines arithmetic operations between other integer types. - */ -sealed class UInt private[core] (dir: Direction, width: Width, lit: Option[ULit] = None) - extends Bits(dir, width, lit) with Num[UInt] { - private[core] override def cloneTypeWidth(w: Width): this.type = - new UInt(dir, w).asInstanceOf[this.type] - private[chisel] def toType = s"UInt$width" - - override private[chisel] def fromInt(value: BigInt, width: Int): this.type = - UInt(value, width).asInstanceOf[this.type] - - 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 - 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 do_unary_~ (implicit sourceInfo: SourceInfo): UInt = - unop(sourceInfo, UInt(width = width), BitNotOp) - - // REVIEW TODO: Can this be defined on Bits? - 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)) - } - - /** 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. - 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). - */ - 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. -private[core] sealed trait UIntFactory { - /** Create a UInt type with inferred width. */ - def apply(): UInt = apply(NO_DIR, Width()) - /** Create a UInt type or port with fixed width. */ - def apply(dir: Direction = NO_DIR, width: Int): UInt = apply(dir, Width(width)) - /** Create a UInt port with inferred width. */ - def apply(dir: Direction): UInt = apply(dir, Width()) - - /** Create a UInt literal with inferred width. */ - def apply(value: BigInt): UInt = apply(value, Width()) - /** Create a UInt literal with fixed width. */ - def apply(value: BigInt, width: Int): UInt = apply(value, Width(width)) - /** Create a UInt literal with inferred width. */ - def apply(n: String): UInt = apply(parse(n), parsedWidth(n)) - /** Create a UInt literal with fixed width. */ - def apply(n: String, width: Int): UInt = apply(parse(n), width) - - /** Create a UInt type with specified width. */ - def apply(width: Width): UInt = apply(NO_DIR, width) - /** Create a UInt port with specified width. */ - def apply(dir: Direction, width: Width): UInt = new UInt(dir, width) - /** Create a UInt literal with specified width. */ - def apply(value: BigInt, width: Width): UInt = { - val lit = ULit(value, width) - new UInt(NO_DIR, lit.width, Some(lit)) - } - - private def parse(n: String) = { - val (base, num) = n.splitAt(1) - val radix = base match { - case "x" | "h" => 16 - case "d" => 10 - case "o" => 8 - case "b" => 2 - case _ => Builder.error(s"Invalid base $base"); 2 - } - BigInt(num.filterNot(_ == '_'), radix) - } - - private def parsedWidth(n: String) = - if (n(0) == 'b') { - Width(n.length-1) - } else if (n(0) == 'h') { - Width((n.length-1) * 4) - } else { - Width() - } -} - -object UInt extends UIntFactory - -sealed class SInt private (dir: Direction, width: Width, lit: Option[SLit] = None) - extends Bits(dir, width, lit) with Num[SInt] { - private[core] override def cloneTypeWidth(w: Width): this.type = - new SInt(dir, w).asInstanceOf[this.type] - private[chisel] def toType = s"SInt$width" - - override def := (that: Data)(implicit sourceInfo: SourceInfo): Unit = that match { - case _: SInt => this connect that - case _ => this badConnect that - } - - override private[chisel] def fromInt(value: BigInt, width: Int): this.type = - SInt(value, width).asInstanceOf[this.type] - - 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 */ - 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 */ - final def +% (that: SInt): SInt = macro SourceInfoTransform.thatArg - /** subtract (width +1) operator */ - final def -& (that: SInt): SInt = macro SourceInfoTransform.thatArg - /** subtract (no growth) operator */ - 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 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 { - /** Create an SInt type with inferred width. */ - def apply(): SInt = apply(NO_DIR, Width()) - /** Create an SInt type or port with fixed width. */ - def apply(dir: Direction = NO_DIR, width: Int): SInt = apply(dir, Width(width)) - /** Create an SInt port with inferred width. */ - def apply(dir: Direction): SInt = apply(dir, Width()) - - /** Create an SInt literal with inferred width. */ - def apply(value: BigInt): SInt = apply(value, Width()) - /** Create an SInt literal with fixed width. */ - def apply(value: BigInt, width: Int): SInt = apply(value, Width(width)) - - /** Create an SInt type with specified width. */ - def apply(width: Width): SInt = new SInt(NO_DIR, width) - /** Create an SInt port with specified width. */ - def apply(dir: Direction, width: Width): SInt = new SInt(dir, width) - /** Create an SInt literal with specified width. */ - def apply(value: BigInt, width: Width): SInt = { - val lit = SLit(value, width) - new SInt(NO_DIR, lit.width, Some(lit)) - } -} - -// REVIEW TODO: Why does this extend UInt and not Bits? Does defining airth -// operations on a Bool make sense? -/** A data type for booleans, defined as a single bit indicating true or false. - */ -sealed class Bool(dir: Direction, lit: Option[ULit] = None) extends UInt(dir, Width(1), lit) { - private[core] override def cloneTypeWidth(w: Width): this.type = { - require(!w.known || w.get == 1) - new Bool(dir).asInstanceOf[this.type] - } - - override private[chisel] def fromInt(value: BigInt, width: Int): this.type = { - require((value == 0 || value == 1) && width == 1) - Bool(value == 1).asInstanceOf[this.type] - } - - // REVIEW TODO: Why does this need to exist and have different conventions - // than Bits? - 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 do_unary_~ (implicit sourceInfo: SourceInfo): Bool = - unop(sourceInfo, Bool(), BitNotOp) - - /** Outputs the logical OR of two Bools. - */ - 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 = macro SourceInfoTransform.thatArg - - def do_&& (that: Bool)(implicit sourceInfo: SourceInfo): Bool = this & that -} - -object Bool { - /** Creates an empty Bool. - */ - def apply(dir: Direction = NO_DIR): Bool = new Bool(dir) - - /** Creates Bool literal. - */ - def apply(x: Boolean): Bool = new Bool(NO_DIR, Some(ULit(if (x) 1 else 0, Width(1)))) -} - -object Mux { - /** Creates a mux, whose output is one of the inputs depending on the - * value of the condition. - * - * @param cond condition determining the input to choose - * @param con the value chosen when `cond` is true - * @param alt the value chosen when `cond` is false - * @example - * {{{ - * val muxOut = Mux(data_in === UInt(3), UInt(3, 4), UInt(0, 4)) - * }}} - */ - 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] - case (c: Bool, a: UInt) => doMux(cond, c << 0, a).asInstanceOf[T] - case (c: Bits, a: Bits) => doMux(cond, c, a).asInstanceOf[T] - case _ => doAggregateMux(cond, con, alt) - } - - 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(sourceInfo, d, MultiplexOp, cond.ref, con.ref, alt.ref)) - } - - 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") - doMux(cond, con, alt) - } -} - diff --git a/chiselFrontend/src/main/scala/chisel/core/BlackBox.scala b/chiselFrontend/src/main/scala/chisel/core/BlackBox.scala deleted file mode 100644 index 2126ebce..00000000 --- a/chiselFrontend/src/main/scala/chisel/core/BlackBox.scala +++ /dev/null @@ -1,55 +0,0 @@ -// See LICENSE for license details. - -package chisel.core - -import chisel.internal.Builder.pushCommand -import chisel.internal.firrtl.{ModuleIO, DefInvalid} -import chisel.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 - * to RTL modules defined outside Chisel. - * - * @example - * {{{ - * ... to be written once a spec is finalized ... - * }}} - */ -// REVIEW TODO: make Verilog parameters part of the constructor interface? -abstract class BlackBox extends Module { - // Don't bother taking override_clock|reset, clock/reset locked out anyway - // TODO: actually implement this. - def setVerilogParameters(s: String): Unit = {} - - // The body of a BlackBox is empty, the real logic happens in firrtl/Emitter.scala - // Bypass standard clock, reset, io port declaration by flattening io - // TODO(twigg): ? Really, overrides are bad, should extend BaseModule.... - override private[core] def ports = io.elements.toSeq - - // Do not do reflective naming of internal signals, just name io - override private[core] def setRefs(): this.type = { - for ((name, port) <- ports) { - port.setRef(ModuleIO(this, _namespace.name(name))) - } - // setRef is not called on the actual io. - // There is a risk of user improperly attempting to connect directly with io - // Long term solution will be to define BlackBox IO differently as part of - // it not descending from the (current) Module - this - } - - // Don't setup clock, reset - // Cann't invalide io in one bunch, must invalidate each part separately - override private[core] def setupInParent(implicit sourceInfo: SourceInfo): this.type = _parent match { - case Some(p) => { - // Just init instance inputs - for((_,port) <- ports) pushCommand(DefInvalid(sourceInfo, port.ref)) - this - } - case None => this - } - - // Using null is horrible but these signals SHOULD NEVER be used: - override val clock = null - override val reset = null -} diff --git a/chiselFrontend/src/main/scala/chisel/core/Data.scala b/chiselFrontend/src/main/scala/chisel/core/Data.scala deleted file mode 100644 index cae38144..00000000 --- a/chiselFrontend/src/main/scala/chisel/core/Data.scala +++ /dev/null @@ -1,156 +0,0 @@ -// See LICENSE for license details. - -package chisel.core - -import scala.language.experimental.macros - -import chisel.internal._ -import chisel.internal.Builder.pushCommand -import chisel.internal.firrtl._ -import chisel.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, UnlocatableSourceInfo, WireTransform, SourceInfoTransform} - -sealed abstract class Direction(name: String) { - override def toString: String = name - def flip: Direction -} -object INPUT extends Direction("input") { override def flip: Direction = OUTPUT } -object OUTPUT extends Direction("output") { override def flip: Direction = INPUT } -object NO_DIR extends Direction("?") { override def flip: Direction = NO_DIR } - -/** Mixing in this trait flips the direction of an Aggregate. */ -trait Flipped extends Data { - this.overrideDirection(_.flip, !_) -} - -/** This forms the root of the type system for wire data types. The data value - * must be representable as some number (need not be known at Chisel compile - * time) of bits, and must have methods to pack / unpack structured data to / - * from bits. - */ -abstract class Data(dirArg: Direction) extends HasId { - def dir: Direction = dirVar - - // Sucks this is mutable state, but cloneType doesn't take a Direction arg - private var isFlipVar = dirArg == INPUT - private var dirVar = dirArg - private[core] def isFlip = isFlipVar - - private[core] def overrideDirection(newDir: Direction => Direction, - newFlip: Boolean => Boolean): this.type = { - this.isFlipVar = newFlip(this.isFlipVar) - for (field <- this.flatten) - (field: Data).dirVar = newDir((field: Data).dirVar) - this - } - def asInput: this.type = cloneType.overrideDirection(_ => INPUT, _ => true) - def asOutput: this.type = cloneType.overrideDirection(_ => OUTPUT, _ => false) - def flip(): this.type = cloneType.overrideDirection(_.flip, !_) - - private[core] def badConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit = - throwException(s"cannot connect ${this} and ${that}") - private[core] def connect(that: Data)(implicit sourceInfo: SourceInfo): Unit = - pushCommand(Connect(sourceInfo, this.lref, that.ref)) - private[core] def bulkConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit = - pushCommand(BulkConnect(sourceInfo, this.lref, that.lref)) - private[core] def lref: Node = Node(this) - private[chisel] def ref: Arg = if (isLit) litArg.get else lref - private[core] def cloneTypeWidth(width: Width): this.type - private[chisel] def toType: String - - 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 - def isLit(): Boolean = litArg.isDefined - - def width: Width - final def getWidth: Int = width.get - - // While this being in the Data API doesn't really make sense (should be in - // Aggregate, right?) this is because of an implementation limitation: - // cloneWithDirection, which is private and defined here, needs flatten to - // set element directionality. - // Related: directionality is mutable state. A possible solution for both is - // to define directionality relative to the container, but these parent links - // currently don't exist (while this information may be available during - // FIRRTL emission, it would break directionality querying from Chisel, which - // does get used). - private[chisel] def flatten: IndexedSeq[Bits] - - /** Creates an new instance of this type, unpacking the input Bits into - * structured data. - * - * This performs the inverse operation of toBits. - * - * @note does NOT assign to the object this is called on, instead creates - * and returns a NEW object (useful in a clone-and-assign scenario) - * @note does NOT check bit widths, may drop bits during assignment - * @note what fromBits assigs to must have known widths - */ - 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 (that.width.known && that.width.get >= wire.width.get) { - that - } else { - Wire(that.cloneTypeWidth(wire.width), init = that) - } - for (x <- wire.flatten) { - x := bits(i + x.getWidth-1, i) - i += x.getWidth - } - wire.asInstanceOf[this.type] - } - - /** Packs the value of this object as plain Bits. - * - * This performs the inverse operation of fromBits(Bits). - */ - @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 = 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 = - 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 = - do_apply(t, init)(UnlocatableSourceInfo) - - def do_apply[T <: Data](t: T, init: T)(implicit sourceInfo: SourceInfo): T = { - val x = Reg.makeType(t, null.asInstanceOf[T], init) - pushCommand(DefWire(sourceInfo, x)) - pushCommand(DefInvalid(sourceInfo, x.ref)) - if (init != null) { - x := init - } - x - } -} - -object Clock { - def apply(dir: Direction = NO_DIR): Clock = new Clock(dir) -} - -// TODO: Document this. -sealed class Clock(dirArg: Direction) extends Element(dirArg, Width(1)) { - def cloneType: this.type = Clock(dirArg).asInstanceOf[this.type] - private[chisel] override def flatten: IndexedSeq[Bits] = IndexedSeq() - private[core] def cloneTypeWidth(width: Width): this.type = cloneType - private[chisel] def toType = "Clock" - - 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/core/Mem.scala b/chiselFrontend/src/main/scala/chisel/core/Mem.scala deleted file mode 100644 index a2df2910..00000000 --- a/chiselFrontend/src/main/scala/chisel/core/Mem.scala +++ /dev/null @@ -1,134 +0,0 @@ -// See LICENSE for license details. - -package chisel.core - -import scala.language.experimental.macros - -import chisel.internal._ -import chisel.internal.Builder.pushCommand -import chisel.internal.firrtl._ -import chisel.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] = 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] = 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(sourceInfo, mem, mt, size)) // TODO multi-clock - mem - } -} - -sealed abstract class MemBase[T <: Data](t: T, val length: Int) extends HasId with VecLike[T] { - // REVIEW TODO: make accessors (static/dynamic, read/write) combinations consistent. - - /** Creates a read accessor into the memory with static addressing. See the - * class documentation of the memory for more detailed information. - */ - def apply(idx: Int): T = apply(UInt(idx)) - - /** 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(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(UnlocatableSourceInfo, idx, MemPortDirection.READ) - - /** Creates a write accessor into the memory. - * - * @param idx memory element index to write into - * @param data new data to write - */ - def write(idx: UInt, data: T): Unit = { - implicit val sourceInfo = UnlocatableSourceInfo - makePort(UnlocatableSourceInfo, idx, MemPortDirection.WRITE) := data - } - - /** Creates a masked write accessor into the memory. - * - * @param idx memory element index to write into - * @param data new data to write - * @param mask write mask as a Vec of Bool: a write to the Vec element in - * memory is only performed if the corresponding mask index is true. - * - * @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 = { - 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})") - } - if (accessor.length != mask.length) { - Builder.error(s"Mem write mask must contain ${accessor.length} elements (found ${mask.length})") - } - for (((cond, port), datum) <- mask zip accessor zip dataVec) - when (cond) { port := datum } - } - - 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. - * - * Writes take effect on the rising clock edge after the request. Reads are - * combinational (requests will return data on the same cycle). - * Read-after-write hazards are not an issue. - * - * @note when multiple conflicting writes are performed on a Mem element, the - * result is undefined (unlike Vec, where the last assignment wins) - */ -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] = 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] = 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(sourceInfo, mem, mt, size)) // TODO multi-clock - mem - } -} - -/** A sequential-read, sequential-write memory. - * - * Writes take effect on the rising clock edge after the request. Reads return - * data on the rising edge after the request. Read-after-write behavior (when - * a read and write to the same address are requested on the same cycle) is - * undefined. - * - * @note when multiple conflicting writes are performed on a Mem element, the - * result is undefined (unlike Vec, where the last assignment wins) - */ -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/core/Module.scala b/chiselFrontend/src/main/scala/chisel/core/Module.scala deleted file mode 100644 index 1de3efe5..00000000 --- a/chiselFrontend/src/main/scala/chisel/core/Module.scala +++ /dev/null @@ -1,119 +0,0 @@ -// See LICENSE for license details. - -package chisel.core - -import scala.collection.mutable.{ArrayBuffer, HashSet} -import scala.language.experimental.macros - -import chisel.internal._ -import chisel.internal.Builder.pushCommand -import chisel.internal.Builder.dynamicContext -import chisel.internal.firrtl._ -import chisel.internal.sourceinfo.{SourceInfo, InstTransform, UnlocatableSourceInfo} - -object Module { - /** A wrapper method that all Module instantiations must be wrapped in - * (necessary to help Chisel track internal state). - * - * @param m the Module being created - * - * @return the input module `m` with Chisel metadata properly set - */ - 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(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(sourceInfo, m, ports)) - m.setupInParent(childSourceInfo) - } -} - -/** Abstract base class for Modules, which behave much like Verilog modules. - * These may contain both logic and state which are written in the Module - * body (constructor). - * - * @note Module instantiations must be wrapped in a Module() call. - */ -abstract class Module( - override_clock: Option[Clock]=None, override_reset: Option[Bool]=None) -extends HasId { - // _clock and _reset can be clock and reset in these 2ary constructors - // once chisel2 compatibility issues are resolved - def this(_clock: Clock) = this(Option(_clock), None) - def this(_reset: Bool) = this(None, Option(_reset)) - def this(_clock: Clock, _reset: Bool) = this(Option(_clock), Option(_reset)) - - private[core] val _namespace = Builder.globalNamespace.child - private[chisel] val _commands = ArrayBuffer[Command]() - private[core] val _ids = ArrayBuffer[HasId]() - dynamicContext.currentModule = Some(this) - - /** Name of the instance. */ - val name = Builder.globalNamespace.name(getClass.getName.split('.').last) - - /** IO for this Module. At the Scala level (pre-FIRRTL transformations), - * connections in and out of a Module may only go through `io` elements. - */ - def io: Bundle - val clock = Clock(INPUT) - val reset = Bool(INPUT) - - private[chisel] def addId(d: HasId) { _ids += d } - - private[core] def ports: Seq[(String,Data)] = Vector( - ("clk", clock), ("reset", reset), ("io", io) - ) - - private[core] def computePorts = for((name, port) <- ports) yield { - val bundleDir = if (port.isFlip) INPUT else OUTPUT - Port(port, if (port.dir == NO_DIR) bundleDir else port.dir) - } - - private[core] 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 - } - } - - private[core] def setRefs(): this.type = { - for ((name, port) <- ports) { - port.setRef(ModuleIO(this, _namespace.name(name))) - } - - // Suggest names to nodes using runtime reflection - val valNames = HashSet[String](getClass.getDeclaredFields.map(_.getName):_*) - def isPublicVal(m: java.lang.reflect.Method) = - m.getParameterTypes.isEmpty && valNames.contains(m.getName) - val methods = getClass.getMethods.sortWith(_.getName > _.getName) - for (m <- methods; if isPublicVal(m)) m.invoke(this) match { - case (id: HasId) => id.suggestName(m.getName) - case _ => - } - - // For Module instances we haven't named, suggest the name of the Module - _ids foreach { - case m: Module => m.suggestName(m.name) - case _ => - } - - // All suggestions are in, force names to every node. - _ids.foreach(_.forceName(default="T", _namespace)) - _ids.foreach(_._onModuleClose) - this - } -} diff --git a/chiselFrontend/src/main/scala/chisel/core/Printf.scala b/chiselFrontend/src/main/scala/chisel/core/Printf.scala deleted file mode 100644 index a7970816..00000000 --- a/chiselFrontend/src/main/scala/chisel/core/Printf.scala +++ /dev/null @@ -1,36 +0,0 @@ -// See LICENSE for license details. - -package chisel.core - -import scala.language.experimental.macros - -import chisel.internal._ -import chisel.internal.Builder.pushCommand -import chisel.internal.firrtl._ -import chisel.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[core] 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/core/Reg.scala b/chiselFrontend/src/main/scala/chisel/core/Reg.scala deleted file mode 100644 index 78461334..00000000 --- a/chiselFrontend/src/main/scala/chisel/core/Reg.scala +++ /dev/null @@ -1,71 +0,0 @@ -// See LICENSE for license details. - -package chisel.core - -import chisel.internal._ -import chisel.internal.Builder.pushCommand -import chisel.internal.firrtl._ -import chisel.internal.sourceinfo.{SourceInfo, UnlocatableSourceInfo} - -object Reg { - private[core] def makeType[T <: Data](t: T = null, next: T = null, init: T = null): T = { - if (t ne null) { - t.cloneType - } else if (next ne null) { - next.cloneTypeWidth(Width()) - } else if (init ne null) { - init.litArg match { - // For e.g. Reg(init=UInt(0, k)), fix the Reg's width to k - case Some(lit) if lit.forcedWidth => init.cloneType - case _ => init.cloneTypeWidth(Width()) - } - } else { - throwException("cannot infer type") - } - } - - /** Creates a register with optional next and initialization values. - * - * @param t: data type for the register - * @param next: new value register is to be updated with every cycle (or - * empty to not update unless assigned to using the := operator) - * @param init: initialization value on reset (or empty for uninitialized, - * where the register value persists across a reset) - * - * @note this may result in a type error if called from a type parameterized - * function, since the Scala compiler isn't smart enough to know that null - * 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 = - // 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()). - // Implicit conversions to Option (or similar) types were also considered, - // but Scala's type inferencer and implicit insertion isn't smart enough - // to resolve all use cases. If the type inferencer / implicit resolution - // system improves, this may be changed. - val x = makeType(t, next, init) - val clock = Node(x._parent.get.clock) // TODO multi-clock - if (init == null) { - pushCommand(DefReg(sourceInfo, x, clock)) - } else { - pushCommand(DefRegInit(sourceInfo, x, clock, Node(x._parent.get.reset), init.ref)) - } - if (next != null) { - x := next - } - x - } -} diff --git a/chiselFrontend/src/main/scala/chisel/core/SeqUtils.scala b/chiselFrontend/src/main/scala/chisel/core/SeqUtils.scala deleted file mode 100644 index e31119a5..00000000 --- a/chiselFrontend/src/main/scala/chisel/core/SeqUtils.scala +++ /dev/null @@ -1,59 +0,0 @@ -// See LICENSE for license details. - -package chisel.core - -import scala.language.experimental.macros - -import chisel.internal.sourceinfo.{SourceInfo, SourceInfoTransform} - -private[chisel] object SeqUtils { - /** Equivalent to Cat(r(n-1), ..., r(0)) */ - 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 { - val left = asUInt(in.slice(0, in.length/2)) - val right = asUInt(in.slice(in.length/2, in.length)) - right ## left - } - } - - /** Counts the number of true Bools in a Seq */ - 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) { - in.head - } else { - count(in.slice(0, in.size/2)) + (UInt(0) ## count(in.slice(in.size/2, in.size))) - } - } - - /** Returns data value corresponding to first true predicate */ - def priorityMux[T <: Data](in: Seq[(Bool, T)]): T = macro SourceInfoTransform.inArg - - def do_priorityMux[T <: Data](in: Seq[(Bool, T)])(implicit sourceInfo: SourceInfo): T = { - if (in.size == 1) { - in.head._2 - } else { - Mux(in.head._1, in.head._2, priorityMux(in.tail)) - } - } - - /** Returns data value corresponding to lone true predicate */ - 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 { - val masked = for ((s, i) <- in) yield Mux(s, i.toBits, Bits(0)) - val width = in.map(_._2.width).reduce(_ max _) - in.head._2.cloneTypeWidth(width).fromBits(masked.reduceLeft(_|_)) - } - } -} diff --git a/chiselFrontend/src/main/scala/chisel/core/When.scala b/chiselFrontend/src/main/scala/chisel/core/When.scala deleted file mode 100644 index 5d484313..00000000 --- a/chiselFrontend/src/main/scala/chisel/core/When.scala +++ /dev/null @@ -1,59 +0,0 @@ -// See LICENSE for license details. - -package chisel.core - -import scala.language.experimental.macros - -import chisel.internal._ -import chisel.internal.Builder.pushCommand -import chisel.internal.firrtl._ -import chisel.internal.sourceinfo.{SourceInfo} - -object when { // scalastyle:ignore object.name - /** Create a `when` condition block, where whether a block of logic is - * executed or not depends on the conditional. - * - * @param cond condition to execute upon - * @param block logic that runs only if `cond` is true - * - * @example - * {{{ - * when ( myData === UInt(3) ) { - * // Some logic to run when myData equals 3. - * } .elsewhen ( myData === UInt(1) ) { - * // Some logic to run when myData equals 1. - * } .otherwise { - * // Some logic to run when myData is neither 3 nor 1. - * } - * }}} - */ - def apply(cond: Bool)(block: => Unit)(implicit sourceInfo: SourceInfo): WhenContext = { - new WhenContext(sourceInfo, cond, !cond, block) - } -} - -/** Internal mechanism for generating a when. Because of the way FIRRTL - * commands are emitted, generating a FIRRTL elsewhen or nested whens inside - * elses would be difficult. Instead, this keeps track of the negative of the - * previous conditions, so when an elsewhen or otherwise is used, it checks - * that both the condition is true and all the previous conditions have been - * false. - */ -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)(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)(implicit sourceInfo: SourceInfo): Unit = - new WhenContext(sourceInfo, prevCond, null, block) - - pushCommand(WhenBegin(sourceInfo, cond.ref)) - block - pushCommand(WhenEnd(sourceInfo)) -} diff --git a/chiselFrontend/src/main/scala/chisel/internal/Builder.scala b/chiselFrontend/src/main/scala/chisel/internal/Builder.scala deleted file mode 100644 index 01628105..00000000 --- a/chiselFrontend/src/main/scala/chisel/internal/Builder.scala +++ /dev/null @@ -1,129 +0,0 @@ -// See LICENSE for license details. - -package chisel.internal - -import scala.util.DynamicVariable -import scala.collection.mutable.{ArrayBuffer, HashMap} - -import chisel._ -import core._ -import firrtl._ - -private[chisel] class Namespace(parent: Option[Namespace], keywords: Set[String]) { - private val names = collection.mutable.HashMap[String, Long]() - for (keyword <- keywords) - names(keyword) = 1 - - private def rename(n: String): String = { - val index = names.getOrElse(n, 1L) - val tryName = s"${n}_${index}" - names(n) = index + 1 - if (this contains tryName) rename(n) else tryName - } - - def contains(elem: String): Boolean = { - names.contains(elem) || parent.map(_ contains elem).getOrElse(false) - } - - def name(elem: String): String = { - if (this contains elem) { - name(rename(elem)) - } else { - names(elem) = 1 - elem - } - } - - def child(kws: Set[String]): Namespace = new Namespace(Some(this), kws) - def child: Namespace = child(Set()) -} - -private[chisel] class IdGen { - private var counter = -1L - def next: Long = { - counter += 1 - counter - } -} - -private[chisel] trait HasId { - private[chisel] def _onModuleClose {} // scalastyle:ignore method.name - private[chisel] val _parent = Builder.dynamicContext.currentModule - _parent.foreach(_.addId(this)) - - private[chisel] val _id = Builder.idGen.next - override def hashCode: Int = _id.toInt - override def equals(that: Any): Boolean = that match { - case x: HasId => _id == x._id - case _ => false - } - - // Facilities for 'suggesting' a name to this. - // Post-name hooks called to carry the suggestion to other candidates as needed - private var suggested_name: Option[String] = None - private val postname_hooks = scala.collection.mutable.ListBuffer.empty[String=>Unit] - // Only takes the first suggestion! - def suggestName(name: =>String): this.type = { - if(suggested_name.isEmpty) suggested_name = Some(name) - for(hook <- postname_hooks) { hook(name) } - this - } - private[chisel] def addPostnameHook(hook: String=>Unit): Unit = postname_hooks += hook - - // Uses a namespace to convert suggestion into a true name - // Will not do any naming if the reference already assigned. - // (e.g. tried to suggest a name to part of a Bundle) - private[chisel] def forceName(default: =>String, namespace: Namespace): Unit = - if(_ref.isEmpty) { - val candidate_name = suggested_name.getOrElse(default) - val available_name = namespace.name(candidate_name) - setRef(Ref(available_name)) - } - - private var _ref: Option[Arg] = None - private[chisel] def setRef(imm: Arg): Unit = _ref = Some(imm) - private[chisel] def setRef(parent: HasId, name: String): Unit = setRef(Slot(Node(parent), name)) - private[chisel] def setRef(parent: HasId, index: Int): Unit = setRef(Index(Node(parent), ILit(index))) - private[chisel] def setRef(parent: HasId, index: UInt): Unit = setRef(Index(Node(parent), index.ref)) - private[chisel] def getRef: Arg = _ref.get -} - -private[chisel] class DynamicContext { - val idGen = new IdGen - val globalNamespace = new Namespace(None, Set()) - val components = ArrayBuffer[Component]() - var currentModule: Option[Module] = None - val errors = new ErrorLog -} - -private[chisel] object Builder { - // All global mutable state must be referenced via dynamicContextVar!! - private val dynamicContextVar = new DynamicVariable[Option[DynamicContext]](None) - - def dynamicContext: DynamicContext = - dynamicContextVar.value getOrElse (new DynamicContext) - def idGen: IdGen = dynamicContext.idGen - def globalNamespace: Namespace = dynamicContext.globalNamespace - def components: ArrayBuffer[Component] = dynamicContext.components - - def pushCommand[T <: Command](c: T): T = { - dynamicContext.currentModule.foreach(_._commands += c) - c - } - def pushOp[T <: Data](cmd: DefPrim[T]): T = pushCommand(cmd).id - - def errors: ErrorLog = dynamicContext.errors - def error(m: => String): Unit = errors.error(m) - - def build[T <: Module](f: => T): Circuit = { - dynamicContextVar.withValue(Some(new DynamicContext)) { - errors.info("Elaborating design...") - val mod = f - mod.forceName(mod.name, globalNamespace) - errors.checkpoint() - errors.info("Done elaborating.") - - Circuit(components.last.name, components) - } - } -} diff --git a/chiselFrontend/src/main/scala/chisel/internal/Error.scala b/chiselFrontend/src/main/scala/chisel/internal/Error.scala deleted file mode 100644 index f0481dc4..00000000 --- a/chiselFrontend/src/main/scala/chisel/internal/Error.scala +++ /dev/null @@ -1,91 +0,0 @@ -// See LICENSE for license details. - -package chisel.internal - -import scala.collection.mutable.ArrayBuffer - -import chisel.core._ - -class ChiselException(message: String, cause: Throwable) extends Exception(message, cause) - -private[chisel] object throwException { - def apply(s: String, t: Throwable = null): Nothing = - throw new ChiselException(s, t) -} - -/** Records and reports runtime errors and warnings. */ -private[chisel] class ErrorLog { - def hasErrors: Boolean = errors.exists(_.isFatal) - - /** Log an error message */ - def error(m: => String): Unit = - errors += new Error(m, getUserLineNumber) - - /** Log a warning message */ - def warning(m: => String): Unit = - errors += new Warning(m, getUserLineNumber) - - /** Emit an informational message */ - def info(m: String): Unit = - println(new Info("[%2.3f] %s".format(elapsedTime/1e3, m), None)) // scalastyle:ignore regex - - /** Prints error messages generated by Chisel at runtime. */ - def report(): Unit = errors foreach println // scalastyle:ignore regex - - /** Throw an exception if any errors have yet occurred. */ - def checkpoint(): Unit = if(hasErrors) { - import Console._ - throwException(errors.map(_ + "\n").reduce(_ + _) + - UNDERLINED + "CODE HAS " + errors.filter(_.isFatal).length + RESET + - UNDERLINED + " " + RED + "ERRORS" + RESET + - UNDERLINED + " and " + errors.filterNot(_.isFatal).length + RESET + - UNDERLINED + " " + YELLOW + "WARNINGS" + RESET) - } - - private def findFirstUserFrame(stack: Array[StackTraceElement]): Option[StackTraceElement] = { - def isUserCode(ste: StackTraceElement): Boolean = { - def isUserModule(c: Class[_]): Boolean = - c != null && (c == classOf[Module] || isUserModule(c.getSuperclass)) - isUserModule(Class.forName(ste.getClassName)) - } - - stack.indexWhere(isUserCode) match { - case x if x < 0 => None - case x => Some(stack(x)) - } - } - - private def getUserLineNumber = - findFirstUserFrame(Thread.currentThread().getStackTrace) - - private val errors = ArrayBuffer[LogEntry]() - - private val startTime = System.currentTimeMillis - private def elapsedTime: Long = System.currentTimeMillis - startTime -} - -private abstract class LogEntry(msg: => String, line: Option[StackTraceElement]) { - def isFatal: Boolean = false - def format: String - - override def toString: String = line match { - case Some(l) => s"${format} ${l.getFileName}:${l.getLineNumber}: ${msg} in class ${l.getClassName}" - case None => s"${format} ${msg}" - } - - protected def tag(name: String, color: String): String = - s"[${color}${name}${Console.RESET}]" -} - -private class Error(msg: => String, line: Option[StackTraceElement]) extends LogEntry(msg, line) { - override def isFatal: Boolean = true - def format: String = tag("error", Console.RED) -} - -private class Warning(msg: => String, line: Option[StackTraceElement]) extends LogEntry(msg, line) { - def format: String = tag("warn", Console.YELLOW) -} - -private class Info(msg: => String, line: Option[StackTraceElement]) extends LogEntry(msg, line) { - def format: String = tag("info", Console.MAGENTA) -} diff --git a/chiselFrontend/src/main/scala/chisel/internal/SourceInfo.scala b/chiselFrontend/src/main/scala/chisel/internal/SourceInfo.scala deleted file mode 100644 index c20bd130..00000000 --- a/chiselFrontend/src/main/scala/chisel/internal/SourceInfo.scala +++ /dev/null @@ -1,51 +0,0 @@ -// 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/IR.scala b/chiselFrontend/src/main/scala/chisel/internal/firrtl/IR.scala deleted file mode 100644 index 70e9938b..00000000 --- a/chiselFrontend/src/main/scala/chisel/internal/firrtl/IR.scala +++ /dev/null @@ -1,190 +0,0 @@ -// See LICENSE for license details. - -package chisel.internal.firrtl - -import chisel._ -import core._ -import chisel.internal._ -import chisel.internal.sourceinfo.{SourceInfo, NoSourceInfo} - -case class PrimOp(val name: String) { - override def toString: String = name -} - -object PrimOp { - val AddOp = PrimOp("add") - val SubOp = PrimOp("sub") - val TailOp = PrimOp("tail") - val HeadOp = PrimOp("head") - val TimesOp = PrimOp("mul") - val DivideOp = PrimOp("div") - val RemOp = PrimOp("rem") - val ShiftLeftOp = PrimOp("shl") - val ShiftRightOp = PrimOp("shr") - val DynamicShiftLeftOp = PrimOp("dshl") - val DynamicShiftRightOp = PrimOp("dshr") - val BitAndOp = PrimOp("and") - val BitOrOp = PrimOp("or") - val BitXorOp = PrimOp("xor") - val BitNotOp = PrimOp("not") - val ConcatOp = PrimOp("cat") - val BitsExtractOp = PrimOp("bits") - val LessOp = PrimOp("lt") - val LessEqOp = PrimOp("leq") - val GreaterOp = PrimOp("gt") - val GreaterEqOp = PrimOp("geq") - val EqualOp = PrimOp("eq") - val PadOp = PrimOp("pad") - val NotEqualOp = PrimOp("neq") - val NegOp = PrimOp("neg") - val MultiplexOp = PrimOp("mux") - val XorReduceOp = PrimOp("xorr") - val ConvertOp = PrimOp("cvt") - val AsUIntOp = PrimOp("asUInt") - val AsSIntOp = PrimOp("asSInt") -} - -abstract class Arg { - def fullName(ctx: Component): String = name - def name: String -} - -case class Node(id: HasId) extends Arg { - override def fullName(ctx: Component): String = id.getRef.fullName(ctx) - def name: String = id.getRef.name -} - -abstract class LitArg(val num: BigInt, widthArg: Width) extends Arg { - private[chisel] def forcedWidth = widthArg.known - private[chisel] def width: Width = if (forcedWidth) widthArg else Width(minWidth) - - protected def minWidth: Int - if (forcedWidth) { - require(widthArg.get >= minWidth, - s"The literal value ${num} was elaborated with a specificed width of ${widthArg.get} bits, but at least ${minWidth} bits are required.") - } -} - -case class ILit(n: BigInt) extends Arg { - def name: String = n.toString -} - -case class ULit(n: BigInt, w: Width) extends LitArg(n, w) { - def name: String = "UInt" + width + "(\"h0" + num.toString(16) + "\")" - def minWidth: Int = 1 max n.bitLength - - require(n >= 0, s"UInt literal ${n} is negative") -} - -case class SLit(n: BigInt, w: Width) extends LitArg(n, w) { - def name: String = { - val unsigned = if (n < 0) (BigInt(1) << width.get) + n else n - s"asSInt(${ULit(unsigned, width).name})" - } - def minWidth: Int = 1 + n.bitLength -} - -case class Ref(name: String) extends Arg -case class ModuleIO(mod: Module, name: String) extends Arg { - override def fullName(ctx: Component): String = - if (mod eq ctx.id) name else s"${mod.getRef.name}.$name" -} -case class Slot(imm: Node, name: String) extends Arg { - override def fullName(ctx: Component): String = - if (imm.fullName(ctx).isEmpty) name else s"${imm.fullName(ctx)}.${name}" -} -case class Index(imm: Arg, value: Arg) extends Arg { - def name: String = s"[$value]" - override def fullName(ctx: Component): String = s"${imm.fullName(ctx)}[${value.fullName(ctx)}]" -} - -object Width { - def apply(x: Int): Width = KnownWidth(x) - def apply(): Width = UnknownWidth() -} - -sealed abstract class Width { - type W = Int - def max(that: Width): Width = this.op(that, _ max _) - def + (that: Width): Width = this.op(that, _ + _) - def + (that: Int): Width = this.op(this, (a, b) => a + that) - def shiftRight(that: Int): Width = this.op(this, (a, b) => 0 max (a - that)) - def dynamicShiftLeft(that: Width): Width = - this.op(that, (a, b) => a + (1 << b) - 1) - - def known: Boolean - def get: W - protected def op(that: Width, f: (W, W) => W): Width -} - -sealed case class UnknownWidth() extends Width { - def known: Boolean = false - def get: Int = None.get - def op(that: Width, f: (W, W) => W): Width = this - override def toString: String = "" -} - -sealed case class KnownWidth(value: Int) extends Width { - require(value >= 0) - def known: Boolean = true - def get: Int = value - def op(that: Width, f: (W, W) => W): Width = that match { - case KnownWidth(x) => KnownWidth(f(value, x)) - case _ => that - } - override def toString: String = s"<${value.toString}>" -} - -sealed abstract class MemPortDirection(name: String) { - override def toString: String = name -} -object MemPortDirection { - object READ extends MemPortDirection("read") - object WRITE extends MemPortDirection("write") - object RDWR extends MemPortDirection("rdwr") - object INFER extends MemPortDirection("infer") -} - -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](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(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) = { - require(x.toInt >= 0) - if (x == '"' || x == '\\') { - s"\\${x}" - } else if (x == '\n') { - "\\n" - } else { - require(x.toInt >= 32) // TODO \xNN once FIRRTL issue #59 is resolved - x - } - } - formatIn.map(escaped _).mkString - } -} - -case class Circuit(name: String, components: Seq[Component]) diff --git a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala new file mode 100644 index 00000000..38a42fea --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala @@ -0,0 +1,377 @@ +// See LICENSE for license details. + +package chisel.core + +import scala.collection.immutable.ListMap +import scala.collection.mutable.{ArrayBuffer, HashSet, LinkedHashMap} +import scala.language.experimental.macros + +import chisel.internal._ +import chisel.internal.Builder.pushCommand +import chisel.internal.firrtl._ +import chisel.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, VecTransform, SourceInfoTransform} + +/** 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[core] 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] = 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)) + 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] = 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 + * 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] = 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 + * 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] = 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 + * 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)(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])(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])(implicit sourceInfo: SourceInfo): Unit = this := that.asInstanceOf[Data] + + override def := (that: Data)(implicit sourceInfo: SourceInfo): 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])(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])(implicit sourceInfo: SourceInfo): 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)(DeprecatedSourceInfo) + + 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] 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 + + @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 = 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 = 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 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 = 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. + */ + 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 = 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 = 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. + * + * 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 = 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. + * + * 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)(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)(implicit sourceInfo: SourceInfo): 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[core] 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[core] 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[core] object Bundle { + val keywords = List("flip", "asInput", "asOutput", "cloneType", "toBits") +} diff --git a/chiselFrontend/src/main/scala/chisel3/core/Assert.scala b/chiselFrontend/src/main/scala/chisel3/core/Assert.scala new file mode 100644 index 00000000..00cb00f4 --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel3/core/Assert.scala @@ -0,0 +1,73 @@ +// See LICENSE for license details. + +package chisel.core + +import scala.reflect.macros.blackbox.Context +import scala.language.experimental.macros + +import chisel.internal._ +import chisel.internal.Builder.pushCommand +import chisel.internal.firrtl._ +import chisel.internal.sourceinfo.SourceInfo + +object assert { // scalastyle:ignore object.name + /** Checks for a condition to be valid in the circuit at all times. If the + * condition evaluates to false, the circuit simulation stops with an error. + * + * 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 assert make the standard Module assumptions (single clock + * and single reset). + * + * @param cond condition, assertion fires (simulation fails) when false + * @param message optional message to print when the assertion fires + * + * @note currently cannot be used in core Chisel / libraries because macro + * defs need to be compiled first and the SBT project is not set up to do + * that + */ + // 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)(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))($sourceInfo)" + } + + 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)($sourceInfo)" + } + + 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(sourceInfo, Node(Builder.dynamicContext.currentModule.get.clock), 1)) + } + } + + /** An elaboration-time assertion, otherwise the same as the above run-time + * assertion. */ + def apply(cond: Boolean, message: => String) { + Predef.assert(cond, message) + } + + /** A workaround for default-value overloading problems in Scala, just + * 'assert(cond, "")' */ + def apply(cond: Boolean) { + Predef.assert(cond, "") + } +} diff --git a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala new file mode 100644 index 00000000..38e71f8d --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala @@ -0,0 +1,756 @@ +// See LICENSE for license details. + +package chisel.core + +import scala.language.experimental.macros + +import chisel.internal._ +import chisel.internal.Builder.pushOp +import chisel.internal.firrtl._ +import chisel.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, SourceInfoTransform, SourceInfoWhiteboxTransform, + UIntTransform, MuxTransform} +import chisel.internal.firrtl.PrimOp._ + +/** Element is a leaf data type: it cannot contain other Data objects. Example + * uses are for representing primitive data types, like integers and bits. + */ +abstract class Element(dirArg: Direction, val width: Width) extends Data(dirArg) + +/** A data type for values represented by a single bitvector. Provides basic + * bitwise operations. + */ +sealed abstract class Bits(dirArg: Direction, width: Width, override val litArg: Option[LitArg]) + extends Element(dirArg, width) { + // TODO: perhaps make this concrete? + // Arguments for: self-checking code (can't do arithmetic on bits) + // Arguments against: generates down to a FIRRTL UInt anyways + + private[chisel] def fromInt(x: BigInt, w: Int): this.type + + private[chisel] def flatten: IndexedSeq[Bits] = IndexedSeq(this) + + def cloneType: this.type = cloneTypeWidth(width) + + 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 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(sourceInfo, UInt(width = w), TailOp, n) + } + + + 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(sourceInfo, UInt(width = n), HeadOp, n) + } + + /** Returns the specified bit on this wire as a [[Bool]], statically + * addressed. + */ + 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(sourceInfo, Bool(), BitsExtractOp, this.ref, ILit(x), ILit(x))) + } + } + + /** Returns the specified bit on this wire as a [[Bool]], statically + * addressed. + * + * @note convenience method allowing direct use of Ints without implicits + */ + 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 = 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. + * + * @example + * {{{ + * myBits = 0x5 = 0b101 + * myBits(1,0) => 0b01 // extracts the two least significant bits + * }}} + */ + 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)") + } + val w = x - y + 1 + if (isLit()) { + UInt((litValue >> y) & ((BigInt(1) << w) - 1), w) + } else { + 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 = macro SourceInfoTransform.xyArg + + final def do_apply(x: BigInt, y: BigInt)(implicit sourceInfo: SourceInfo): UInt = + apply(x.toInt, y.toInt) + + private[core] def unop[T <: Data](sourceInfo: SourceInfo, dest: T, op: PrimOp): T = + pushOp(DefPrim(sourceInfo, dest, op, this.ref)) + private[core] def binop[T <: Data](sourceInfo: SourceInfo, dest: T, op: PrimOp, other: BigInt): T = + pushOp(DefPrim(sourceInfo, dest, op, this.ref, ILit(other))) + private[core] def binop[T <: Data](sourceInfo: SourceInfo, dest: T, op: PrimOp, other: Bits): T = + pushOp(DefPrim(sourceInfo, dest, op, this.ref, other.ref)) + + private[core] def compop(sourceInfo: SourceInfo, op: PrimOp, other: Bits): Bool = + pushOp(DefPrim(sourceInfo, Bool(), op, this.ref, other.ref)) + private[core] 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 + */ + 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? + 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. + */ + 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. + */ + final def << (that: UInt): Bits = macro SourceInfoWhiteboxTransform.thatArg + + def do_<< (that: UInt)(implicit sourceInfo: SourceInfo): Bits + + /** Shift right operation */ + // REVIEW TODO: redundant + 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. + */ + 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. + */ + 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. + */ + 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 + */ + 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 + */ + final def asUInt(): UInt = macro SourceInfoTransform.noArg + + def do_asUInt(implicit sourceInfo: SourceInfo): UInt + + /** Reinterpret cast to Bits. */ + 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 = do_asSInt(DeprecatedSourceInfo) + @deprecated("Use asUInt, which makes the reinterpret cast more explicit", "chisel3") + final def toUInt(): UInt = do_asUInt(DeprecatedSourceInfo) + + final def toBool(): Bool = macro SourceInfoTransform.noArg + + 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. + */ + 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 = do_asUInt(DeprecatedSourceInfo) + + override def do_fromBits(that: Bits)(implicit sourceInfo: SourceInfo): this.type = { + val res = Wire(this, null).asInstanceOf[this.type] + res := that + res + } +} + +/** Provides a set of operations to create UInt types and literals. + * Identical in functionality to the UInt companion object. + */ +object Bits extends UIntFactory + +// REVIEW TODO: Further discussion needed on what Num actually is. +/** Abstract trait defining operations available on numeric-like wire data + * types. + */ +abstract trait Num[T <: Data] { + // def << (b: T): T + // def >> (b: T): T + //def unary_-(): T + + // REVIEW TODO: double check ops conventions against FIRRTL + + /** Outputs the sum of `this` and `b`. The resulting width is the max of the + * operands plus 1 (should not overflow). + */ + 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. + * + * @note can generate a single-cycle multiplier, which can result in + * significant cycle time and area costs + */ + 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 + */ + final def / (that: T): T = macro SourceInfoTransform.thatArg + + 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). + */ + final def - (that: T): T = macro SourceInfoTransform.thatArg + + def do_- (that: T)(implicit sourceInfo: SourceInfo): T + + /** Outputs true if `this` < `b`. + */ + final def < (that: T): Bool = macro SourceInfoTransform.thatArg + + def do_< (that: T)(implicit sourceInfo: SourceInfo): Bool + + /** Outputs true if `this` <= `b`. + */ + final def <= (that: T): Bool = macro SourceInfoTransform.thatArg + + def do_<= (that: T)(implicit sourceInfo: SourceInfo): Bool + + /** Outputs true if `this` > `b`. + */ + final def > (that: T): Bool = macro SourceInfoTransform.thatArg + + def do_> (that: T)(implicit sourceInfo: SourceInfo): Bool + + /** Outputs true if `this` >= `b`. + */ + 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. + */ + 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. + */ + 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. + * Defines arithmetic operations between other integer types. + */ +sealed class UInt private[core] (dir: Direction, width: Width, lit: Option[ULit] = None) + extends Bits(dir, width, lit) with Num[UInt] { + private[core] override def cloneTypeWidth(w: Width): this.type = + new UInt(dir, w).asInstanceOf[this.type] + private[chisel] def toType = s"UInt$width" + + override private[chisel] def fromInt(value: BigInt, width: Int): this.type = + UInt(value, width).asInstanceOf[this.type] + + 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 + 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 do_unary_~ (implicit sourceInfo: SourceInfo): UInt = + unop(sourceInfo, UInt(width = width), BitNotOp) + + // REVIEW TODO: Can this be defined on Bits? + 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)) + } + + /** 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. + 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). + */ + 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. +private[core] sealed trait UIntFactory { + /** Create a UInt type with inferred width. */ + def apply(): UInt = apply(NO_DIR, Width()) + /** Create a UInt type or port with fixed width. */ + def apply(dir: Direction = NO_DIR, width: Int): UInt = apply(dir, Width(width)) + /** Create a UInt port with inferred width. */ + def apply(dir: Direction): UInt = apply(dir, Width()) + + /** Create a UInt literal with inferred width. */ + def apply(value: BigInt): UInt = apply(value, Width()) + /** Create a UInt literal with fixed width. */ + def apply(value: BigInt, width: Int): UInt = apply(value, Width(width)) + /** Create a UInt literal with inferred width. */ + def apply(n: String): UInt = apply(parse(n), parsedWidth(n)) + /** Create a UInt literal with fixed width. */ + def apply(n: String, width: Int): UInt = apply(parse(n), width) + + /** Create a UInt type with specified width. */ + def apply(width: Width): UInt = apply(NO_DIR, width) + /** Create a UInt port with specified width. */ + def apply(dir: Direction, width: Width): UInt = new UInt(dir, width) + /** Create a UInt literal with specified width. */ + def apply(value: BigInt, width: Width): UInt = { + val lit = ULit(value, width) + new UInt(NO_DIR, lit.width, Some(lit)) + } + + private def parse(n: String) = { + val (base, num) = n.splitAt(1) + val radix = base match { + case "x" | "h" => 16 + case "d" => 10 + case "o" => 8 + case "b" => 2 + case _ => Builder.error(s"Invalid base $base"); 2 + } + BigInt(num.filterNot(_ == '_'), radix) + } + + private def parsedWidth(n: String) = + if (n(0) == 'b') { + Width(n.length-1) + } else if (n(0) == 'h') { + Width((n.length-1) * 4) + } else { + Width() + } +} + +object UInt extends UIntFactory + +sealed class SInt private (dir: Direction, width: Width, lit: Option[SLit] = None) + extends Bits(dir, width, lit) with Num[SInt] { + private[core] override def cloneTypeWidth(w: Width): this.type = + new SInt(dir, w).asInstanceOf[this.type] + private[chisel] def toType = s"SInt$width" + + override def := (that: Data)(implicit sourceInfo: SourceInfo): Unit = that match { + case _: SInt => this connect that + case _ => this badConnect that + } + + override private[chisel] def fromInt(value: BigInt, width: Int): this.type = + SInt(value, width).asInstanceOf[this.type] + + 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 */ + 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 */ + final def +% (that: SInt): SInt = macro SourceInfoTransform.thatArg + /** subtract (width +1) operator */ + final def -& (that: SInt): SInt = macro SourceInfoTransform.thatArg + /** subtract (no growth) operator */ + 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 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 { + /** Create an SInt type with inferred width. */ + def apply(): SInt = apply(NO_DIR, Width()) + /** Create an SInt type or port with fixed width. */ + def apply(dir: Direction = NO_DIR, width: Int): SInt = apply(dir, Width(width)) + /** Create an SInt port with inferred width. */ + def apply(dir: Direction): SInt = apply(dir, Width()) + + /** Create an SInt literal with inferred width. */ + def apply(value: BigInt): SInt = apply(value, Width()) + /** Create an SInt literal with fixed width. */ + def apply(value: BigInt, width: Int): SInt = apply(value, Width(width)) + + /** Create an SInt type with specified width. */ + def apply(width: Width): SInt = new SInt(NO_DIR, width) + /** Create an SInt port with specified width. */ + def apply(dir: Direction, width: Width): SInt = new SInt(dir, width) + /** Create an SInt literal with specified width. */ + def apply(value: BigInt, width: Width): SInt = { + val lit = SLit(value, width) + new SInt(NO_DIR, lit.width, Some(lit)) + } +} + +// REVIEW TODO: Why does this extend UInt and not Bits? Does defining airth +// operations on a Bool make sense? +/** A data type for booleans, defined as a single bit indicating true or false. + */ +sealed class Bool(dir: Direction, lit: Option[ULit] = None) extends UInt(dir, Width(1), lit) { + private[core] override def cloneTypeWidth(w: Width): this.type = { + require(!w.known || w.get == 1) + new Bool(dir).asInstanceOf[this.type] + } + + override private[chisel] def fromInt(value: BigInt, width: Int): this.type = { + require((value == 0 || value == 1) && width == 1) + Bool(value == 1).asInstanceOf[this.type] + } + + // REVIEW TODO: Why does this need to exist and have different conventions + // than Bits? + 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 do_unary_~ (implicit sourceInfo: SourceInfo): Bool = + unop(sourceInfo, Bool(), BitNotOp) + + /** Outputs the logical OR of two Bools. + */ + 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 = macro SourceInfoTransform.thatArg + + def do_&& (that: Bool)(implicit sourceInfo: SourceInfo): Bool = this & that +} + +object Bool { + /** Creates an empty Bool. + */ + def apply(dir: Direction = NO_DIR): Bool = new Bool(dir) + + /** Creates Bool literal. + */ + def apply(x: Boolean): Bool = new Bool(NO_DIR, Some(ULit(if (x) 1 else 0, Width(1)))) +} + +object Mux { + /** Creates a mux, whose output is one of the inputs depending on the + * value of the condition. + * + * @param cond condition determining the input to choose + * @param con the value chosen when `cond` is true + * @param alt the value chosen when `cond` is false + * @example + * {{{ + * val muxOut = Mux(data_in === UInt(3), UInt(3, 4), UInt(0, 4)) + * }}} + */ + 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] + case (c: Bool, a: UInt) => doMux(cond, c << 0, a).asInstanceOf[T] + case (c: Bits, a: Bits) => doMux(cond, c, a).asInstanceOf[T] + case _ => doAggregateMux(cond, con, alt) + } + + 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(sourceInfo, d, MultiplexOp, cond.ref, con.ref, alt.ref)) + } + + 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") + doMux(cond, con, alt) + } +} + diff --git a/chiselFrontend/src/main/scala/chisel3/core/BlackBox.scala b/chiselFrontend/src/main/scala/chisel3/core/BlackBox.scala new file mode 100644 index 00000000..2126ebce --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel3/core/BlackBox.scala @@ -0,0 +1,55 @@ +// See LICENSE for license details. + +package chisel.core + +import chisel.internal.Builder.pushCommand +import chisel.internal.firrtl.{ModuleIO, DefInvalid} +import chisel.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 + * to RTL modules defined outside Chisel. + * + * @example + * {{{ + * ... to be written once a spec is finalized ... + * }}} + */ +// REVIEW TODO: make Verilog parameters part of the constructor interface? +abstract class BlackBox extends Module { + // Don't bother taking override_clock|reset, clock/reset locked out anyway + // TODO: actually implement this. + def setVerilogParameters(s: String): Unit = {} + + // The body of a BlackBox is empty, the real logic happens in firrtl/Emitter.scala + // Bypass standard clock, reset, io port declaration by flattening io + // TODO(twigg): ? Really, overrides are bad, should extend BaseModule.... + override private[core] def ports = io.elements.toSeq + + // Do not do reflective naming of internal signals, just name io + override private[core] def setRefs(): this.type = { + for ((name, port) <- ports) { + port.setRef(ModuleIO(this, _namespace.name(name))) + } + // setRef is not called on the actual io. + // There is a risk of user improperly attempting to connect directly with io + // Long term solution will be to define BlackBox IO differently as part of + // it not descending from the (current) Module + this + } + + // Don't setup clock, reset + // Cann't invalide io in one bunch, must invalidate each part separately + override private[core] def setupInParent(implicit sourceInfo: SourceInfo): this.type = _parent match { + case Some(p) => { + // Just init instance inputs + for((_,port) <- ports) pushCommand(DefInvalid(sourceInfo, port.ref)) + this + } + case None => this + } + + // Using null is horrible but these signals SHOULD NEVER be used: + override val clock = null + override val reset = null +} diff --git a/chiselFrontend/src/main/scala/chisel3/core/Data.scala b/chiselFrontend/src/main/scala/chisel3/core/Data.scala new file mode 100644 index 00000000..cae38144 --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel3/core/Data.scala @@ -0,0 +1,156 @@ +// See LICENSE for license details. + +package chisel.core + +import scala.language.experimental.macros + +import chisel.internal._ +import chisel.internal.Builder.pushCommand +import chisel.internal.firrtl._ +import chisel.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, UnlocatableSourceInfo, WireTransform, SourceInfoTransform} + +sealed abstract class Direction(name: String) { + override def toString: String = name + def flip: Direction +} +object INPUT extends Direction("input") { override def flip: Direction = OUTPUT } +object OUTPUT extends Direction("output") { override def flip: Direction = INPUT } +object NO_DIR extends Direction("?") { override def flip: Direction = NO_DIR } + +/** Mixing in this trait flips the direction of an Aggregate. */ +trait Flipped extends Data { + this.overrideDirection(_.flip, !_) +} + +/** This forms the root of the type system for wire data types. The data value + * must be representable as some number (need not be known at Chisel compile + * time) of bits, and must have methods to pack / unpack structured data to / + * from bits. + */ +abstract class Data(dirArg: Direction) extends HasId { + def dir: Direction = dirVar + + // Sucks this is mutable state, but cloneType doesn't take a Direction arg + private var isFlipVar = dirArg == INPUT + private var dirVar = dirArg + private[core] def isFlip = isFlipVar + + private[core] def overrideDirection(newDir: Direction => Direction, + newFlip: Boolean => Boolean): this.type = { + this.isFlipVar = newFlip(this.isFlipVar) + for (field <- this.flatten) + (field: Data).dirVar = newDir((field: Data).dirVar) + this + } + def asInput: this.type = cloneType.overrideDirection(_ => INPUT, _ => true) + def asOutput: this.type = cloneType.overrideDirection(_ => OUTPUT, _ => false) + def flip(): this.type = cloneType.overrideDirection(_.flip, !_) + + private[core] def badConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit = + throwException(s"cannot connect ${this} and ${that}") + private[core] def connect(that: Data)(implicit sourceInfo: SourceInfo): Unit = + pushCommand(Connect(sourceInfo, this.lref, that.ref)) + private[core] def bulkConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit = + pushCommand(BulkConnect(sourceInfo, this.lref, that.lref)) + private[core] def lref: Node = Node(this) + private[chisel] def ref: Arg = if (isLit) litArg.get else lref + private[core] def cloneTypeWidth(width: Width): this.type + private[chisel] def toType: String + + 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 + def isLit(): Boolean = litArg.isDefined + + def width: Width + final def getWidth: Int = width.get + + // While this being in the Data API doesn't really make sense (should be in + // Aggregate, right?) this is because of an implementation limitation: + // cloneWithDirection, which is private and defined here, needs flatten to + // set element directionality. + // Related: directionality is mutable state. A possible solution for both is + // to define directionality relative to the container, but these parent links + // currently don't exist (while this information may be available during + // FIRRTL emission, it would break directionality querying from Chisel, which + // does get used). + private[chisel] def flatten: IndexedSeq[Bits] + + /** Creates an new instance of this type, unpacking the input Bits into + * structured data. + * + * This performs the inverse operation of toBits. + * + * @note does NOT assign to the object this is called on, instead creates + * and returns a NEW object (useful in a clone-and-assign scenario) + * @note does NOT check bit widths, may drop bits during assignment + * @note what fromBits assigs to must have known widths + */ + 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 (that.width.known && that.width.get >= wire.width.get) { + that + } else { + Wire(that.cloneTypeWidth(wire.width), init = that) + } + for (x <- wire.flatten) { + x := bits(i + x.getWidth-1, i) + i += x.getWidth + } + wire.asInstanceOf[this.type] + } + + /** Packs the value of this object as plain Bits. + * + * This performs the inverse operation of fromBits(Bits). + */ + @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 = 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 = + 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 = + do_apply(t, init)(UnlocatableSourceInfo) + + def do_apply[T <: Data](t: T, init: T)(implicit sourceInfo: SourceInfo): T = { + val x = Reg.makeType(t, null.asInstanceOf[T], init) + pushCommand(DefWire(sourceInfo, x)) + pushCommand(DefInvalid(sourceInfo, x.ref)) + if (init != null) { + x := init + } + x + } +} + +object Clock { + def apply(dir: Direction = NO_DIR): Clock = new Clock(dir) +} + +// TODO: Document this. +sealed class Clock(dirArg: Direction) extends Element(dirArg, Width(1)) { + def cloneType: this.type = Clock(dirArg).asInstanceOf[this.type] + private[chisel] override def flatten: IndexedSeq[Bits] = IndexedSeq() + private[core] def cloneTypeWidth(width: Width): this.type = cloneType + private[chisel] def toType = "Clock" + + 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/chisel3/core/Mem.scala b/chiselFrontend/src/main/scala/chisel3/core/Mem.scala new file mode 100644 index 00000000..a2df2910 --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel3/core/Mem.scala @@ -0,0 +1,134 @@ +// See LICENSE for license details. + +package chisel.core + +import scala.language.experimental.macros + +import chisel.internal._ +import chisel.internal.Builder.pushCommand +import chisel.internal.firrtl._ +import chisel.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] = 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] = 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(sourceInfo, mem, mt, size)) // TODO multi-clock + mem + } +} + +sealed abstract class MemBase[T <: Data](t: T, val length: Int) extends HasId with VecLike[T] { + // REVIEW TODO: make accessors (static/dynamic, read/write) combinations consistent. + + /** Creates a read accessor into the memory with static addressing. See the + * class documentation of the memory for more detailed information. + */ + def apply(idx: Int): T = apply(UInt(idx)) + + /** 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(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(UnlocatableSourceInfo, idx, MemPortDirection.READ) + + /** Creates a write accessor into the memory. + * + * @param idx memory element index to write into + * @param data new data to write + */ + def write(idx: UInt, data: T): Unit = { + implicit val sourceInfo = UnlocatableSourceInfo + makePort(UnlocatableSourceInfo, idx, MemPortDirection.WRITE) := data + } + + /** Creates a masked write accessor into the memory. + * + * @param idx memory element index to write into + * @param data new data to write + * @param mask write mask as a Vec of Bool: a write to the Vec element in + * memory is only performed if the corresponding mask index is true. + * + * @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 = { + 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})") + } + if (accessor.length != mask.length) { + Builder.error(s"Mem write mask must contain ${accessor.length} elements (found ${mask.length})") + } + for (((cond, port), datum) <- mask zip accessor zip dataVec) + when (cond) { port := datum } + } + + 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. + * + * Writes take effect on the rising clock edge after the request. Reads are + * combinational (requests will return data on the same cycle). + * Read-after-write hazards are not an issue. + * + * @note when multiple conflicting writes are performed on a Mem element, the + * result is undefined (unlike Vec, where the last assignment wins) + */ +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] = 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] = 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(sourceInfo, mem, mt, size)) // TODO multi-clock + mem + } +} + +/** A sequential-read, sequential-write memory. + * + * Writes take effect on the rising clock edge after the request. Reads return + * data on the rising edge after the request. Read-after-write behavior (when + * a read and write to the same address are requested on the same cycle) is + * undefined. + * + * @note when multiple conflicting writes are performed on a Mem element, the + * result is undefined (unlike Vec, where the last assignment wins) + */ +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/chisel3/core/Module.scala b/chiselFrontend/src/main/scala/chisel3/core/Module.scala new file mode 100644 index 00000000..1de3efe5 --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel3/core/Module.scala @@ -0,0 +1,119 @@ +// See LICENSE for license details. + +package chisel.core + +import scala.collection.mutable.{ArrayBuffer, HashSet} +import scala.language.experimental.macros + +import chisel.internal._ +import chisel.internal.Builder.pushCommand +import chisel.internal.Builder.dynamicContext +import chisel.internal.firrtl._ +import chisel.internal.sourceinfo.{SourceInfo, InstTransform, UnlocatableSourceInfo} + +object Module { + /** A wrapper method that all Module instantiations must be wrapped in + * (necessary to help Chisel track internal state). + * + * @param m the Module being created + * + * @return the input module `m` with Chisel metadata properly set + */ + 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(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(sourceInfo, m, ports)) + m.setupInParent(childSourceInfo) + } +} + +/** Abstract base class for Modules, which behave much like Verilog modules. + * These may contain both logic and state which are written in the Module + * body (constructor). + * + * @note Module instantiations must be wrapped in a Module() call. + */ +abstract class Module( + override_clock: Option[Clock]=None, override_reset: Option[Bool]=None) +extends HasId { + // _clock and _reset can be clock and reset in these 2ary constructors + // once chisel2 compatibility issues are resolved + def this(_clock: Clock) = this(Option(_clock), None) + def this(_reset: Bool) = this(None, Option(_reset)) + def this(_clock: Clock, _reset: Bool) = this(Option(_clock), Option(_reset)) + + private[core] val _namespace = Builder.globalNamespace.child + private[chisel] val _commands = ArrayBuffer[Command]() + private[core] val _ids = ArrayBuffer[HasId]() + dynamicContext.currentModule = Some(this) + + /** Name of the instance. */ + val name = Builder.globalNamespace.name(getClass.getName.split('.').last) + + /** IO for this Module. At the Scala level (pre-FIRRTL transformations), + * connections in and out of a Module may only go through `io` elements. + */ + def io: Bundle + val clock = Clock(INPUT) + val reset = Bool(INPUT) + + private[chisel] def addId(d: HasId) { _ids += d } + + private[core] def ports: Seq[(String,Data)] = Vector( + ("clk", clock), ("reset", reset), ("io", io) + ) + + private[core] def computePorts = for((name, port) <- ports) yield { + val bundleDir = if (port.isFlip) INPUT else OUTPUT + Port(port, if (port.dir == NO_DIR) bundleDir else port.dir) + } + + private[core] 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 + } + } + + private[core] def setRefs(): this.type = { + for ((name, port) <- ports) { + port.setRef(ModuleIO(this, _namespace.name(name))) + } + + // Suggest names to nodes using runtime reflection + val valNames = HashSet[String](getClass.getDeclaredFields.map(_.getName):_*) + def isPublicVal(m: java.lang.reflect.Method) = + m.getParameterTypes.isEmpty && valNames.contains(m.getName) + val methods = getClass.getMethods.sortWith(_.getName > _.getName) + for (m <- methods; if isPublicVal(m)) m.invoke(this) match { + case (id: HasId) => id.suggestName(m.getName) + case _ => + } + + // For Module instances we haven't named, suggest the name of the Module + _ids foreach { + case m: Module => m.suggestName(m.name) + case _ => + } + + // All suggestions are in, force names to every node. + _ids.foreach(_.forceName(default="T", _namespace)) + _ids.foreach(_._onModuleClose) + this + } +} diff --git a/chiselFrontend/src/main/scala/chisel3/core/Printf.scala b/chiselFrontend/src/main/scala/chisel3/core/Printf.scala new file mode 100644 index 00000000..a7970816 --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel3/core/Printf.scala @@ -0,0 +1,36 @@ +// See LICENSE for license details. + +package chisel.core + +import scala.language.experimental.macros + +import chisel.internal._ +import chisel.internal.Builder.pushCommand +import chisel.internal.firrtl._ +import chisel.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[core] 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/chisel3/core/Reg.scala b/chiselFrontend/src/main/scala/chisel3/core/Reg.scala new file mode 100644 index 00000000..78461334 --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel3/core/Reg.scala @@ -0,0 +1,71 @@ +// See LICENSE for license details. + +package chisel.core + +import chisel.internal._ +import chisel.internal.Builder.pushCommand +import chisel.internal.firrtl._ +import chisel.internal.sourceinfo.{SourceInfo, UnlocatableSourceInfo} + +object Reg { + private[core] def makeType[T <: Data](t: T = null, next: T = null, init: T = null): T = { + if (t ne null) { + t.cloneType + } else if (next ne null) { + next.cloneTypeWidth(Width()) + } else if (init ne null) { + init.litArg match { + // For e.g. Reg(init=UInt(0, k)), fix the Reg's width to k + case Some(lit) if lit.forcedWidth => init.cloneType + case _ => init.cloneTypeWidth(Width()) + } + } else { + throwException("cannot infer type") + } + } + + /** Creates a register with optional next and initialization values. + * + * @param t: data type for the register + * @param next: new value register is to be updated with every cycle (or + * empty to not update unless assigned to using the := operator) + * @param init: initialization value on reset (or empty for uninitialized, + * where the register value persists across a reset) + * + * @note this may result in a type error if called from a type parameterized + * function, since the Scala compiler isn't smart enough to know that null + * 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 = + // 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()). + // Implicit conversions to Option (or similar) types were also considered, + // but Scala's type inferencer and implicit insertion isn't smart enough + // to resolve all use cases. If the type inferencer / implicit resolution + // system improves, this may be changed. + val x = makeType(t, next, init) + val clock = Node(x._parent.get.clock) // TODO multi-clock + if (init == null) { + pushCommand(DefReg(sourceInfo, x, clock)) + } else { + pushCommand(DefRegInit(sourceInfo, x, clock, Node(x._parent.get.reset), init.ref)) + } + if (next != null) { + x := next + } + x + } +} diff --git a/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala b/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala new file mode 100644 index 00000000..e31119a5 --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala @@ -0,0 +1,59 @@ +// See LICENSE for license details. + +package chisel.core + +import scala.language.experimental.macros + +import chisel.internal.sourceinfo.{SourceInfo, SourceInfoTransform} + +private[chisel] object SeqUtils { + /** Equivalent to Cat(r(n-1), ..., r(0)) */ + 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 { + val left = asUInt(in.slice(0, in.length/2)) + val right = asUInt(in.slice(in.length/2, in.length)) + right ## left + } + } + + /** Counts the number of true Bools in a Seq */ + 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) { + in.head + } else { + count(in.slice(0, in.size/2)) + (UInt(0) ## count(in.slice(in.size/2, in.size))) + } + } + + /** Returns data value corresponding to first true predicate */ + def priorityMux[T <: Data](in: Seq[(Bool, T)]): T = macro SourceInfoTransform.inArg + + def do_priorityMux[T <: Data](in: Seq[(Bool, T)])(implicit sourceInfo: SourceInfo): T = { + if (in.size == 1) { + in.head._2 + } else { + Mux(in.head._1, in.head._2, priorityMux(in.tail)) + } + } + + /** Returns data value corresponding to lone true predicate */ + 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 { + val masked = for ((s, i) <- in) yield Mux(s, i.toBits, Bits(0)) + val width = in.map(_._2.width).reduce(_ max _) + in.head._2.cloneTypeWidth(width).fromBits(masked.reduceLeft(_|_)) + } + } +} diff --git a/chiselFrontend/src/main/scala/chisel3/core/When.scala b/chiselFrontend/src/main/scala/chisel3/core/When.scala new file mode 100644 index 00000000..5d484313 --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel3/core/When.scala @@ -0,0 +1,59 @@ +// See LICENSE for license details. + +package chisel.core + +import scala.language.experimental.macros + +import chisel.internal._ +import chisel.internal.Builder.pushCommand +import chisel.internal.firrtl._ +import chisel.internal.sourceinfo.{SourceInfo} + +object when { // scalastyle:ignore object.name + /** Create a `when` condition block, where whether a block of logic is + * executed or not depends on the conditional. + * + * @param cond condition to execute upon + * @param block logic that runs only if `cond` is true + * + * @example + * {{{ + * when ( myData === UInt(3) ) { + * // Some logic to run when myData equals 3. + * } .elsewhen ( myData === UInt(1) ) { + * // Some logic to run when myData equals 1. + * } .otherwise { + * // Some logic to run when myData is neither 3 nor 1. + * } + * }}} + */ + def apply(cond: Bool)(block: => Unit)(implicit sourceInfo: SourceInfo): WhenContext = { + new WhenContext(sourceInfo, cond, !cond, block) + } +} + +/** Internal mechanism for generating a when. Because of the way FIRRTL + * commands are emitted, generating a FIRRTL elsewhen or nested whens inside + * elses would be difficult. Instead, this keeps track of the negative of the + * previous conditions, so when an elsewhen or otherwise is used, it checks + * that both the condition is true and all the previous conditions have been + * false. + */ +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)(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)(implicit sourceInfo: SourceInfo): Unit = + new WhenContext(sourceInfo, prevCond, null, block) + + pushCommand(WhenBegin(sourceInfo, cond.ref)) + block + pushCommand(WhenEnd(sourceInfo)) +} diff --git a/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala b/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala new file mode 100644 index 00000000..01628105 --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala @@ -0,0 +1,129 @@ +// See LICENSE for license details. + +package chisel.internal + +import scala.util.DynamicVariable +import scala.collection.mutable.{ArrayBuffer, HashMap} + +import chisel._ +import core._ +import firrtl._ + +private[chisel] class Namespace(parent: Option[Namespace], keywords: Set[String]) { + private val names = collection.mutable.HashMap[String, Long]() + for (keyword <- keywords) + names(keyword) = 1 + + private def rename(n: String): String = { + val index = names.getOrElse(n, 1L) + val tryName = s"${n}_${index}" + names(n) = index + 1 + if (this contains tryName) rename(n) else tryName + } + + def contains(elem: String): Boolean = { + names.contains(elem) || parent.map(_ contains elem).getOrElse(false) + } + + def name(elem: String): String = { + if (this contains elem) { + name(rename(elem)) + } else { + names(elem) = 1 + elem + } + } + + def child(kws: Set[String]): Namespace = new Namespace(Some(this), kws) + def child: Namespace = child(Set()) +} + +private[chisel] class IdGen { + private var counter = -1L + def next: Long = { + counter += 1 + counter + } +} + +private[chisel] trait HasId { + private[chisel] def _onModuleClose {} // scalastyle:ignore method.name + private[chisel] val _parent = Builder.dynamicContext.currentModule + _parent.foreach(_.addId(this)) + + private[chisel] val _id = Builder.idGen.next + override def hashCode: Int = _id.toInt + override def equals(that: Any): Boolean = that match { + case x: HasId => _id == x._id + case _ => false + } + + // Facilities for 'suggesting' a name to this. + // Post-name hooks called to carry the suggestion to other candidates as needed + private var suggested_name: Option[String] = None + private val postname_hooks = scala.collection.mutable.ListBuffer.empty[String=>Unit] + // Only takes the first suggestion! + def suggestName(name: =>String): this.type = { + if(suggested_name.isEmpty) suggested_name = Some(name) + for(hook <- postname_hooks) { hook(name) } + this + } + private[chisel] def addPostnameHook(hook: String=>Unit): Unit = postname_hooks += hook + + // Uses a namespace to convert suggestion into a true name + // Will not do any naming if the reference already assigned. + // (e.g. tried to suggest a name to part of a Bundle) + private[chisel] def forceName(default: =>String, namespace: Namespace): Unit = + if(_ref.isEmpty) { + val candidate_name = suggested_name.getOrElse(default) + val available_name = namespace.name(candidate_name) + setRef(Ref(available_name)) + } + + private var _ref: Option[Arg] = None + private[chisel] def setRef(imm: Arg): Unit = _ref = Some(imm) + private[chisel] def setRef(parent: HasId, name: String): Unit = setRef(Slot(Node(parent), name)) + private[chisel] def setRef(parent: HasId, index: Int): Unit = setRef(Index(Node(parent), ILit(index))) + private[chisel] def setRef(parent: HasId, index: UInt): Unit = setRef(Index(Node(parent), index.ref)) + private[chisel] def getRef: Arg = _ref.get +} + +private[chisel] class DynamicContext { + val idGen = new IdGen + val globalNamespace = new Namespace(None, Set()) + val components = ArrayBuffer[Component]() + var currentModule: Option[Module] = None + val errors = new ErrorLog +} + +private[chisel] object Builder { + // All global mutable state must be referenced via dynamicContextVar!! + private val dynamicContextVar = new DynamicVariable[Option[DynamicContext]](None) + + def dynamicContext: DynamicContext = + dynamicContextVar.value getOrElse (new DynamicContext) + def idGen: IdGen = dynamicContext.idGen + def globalNamespace: Namespace = dynamicContext.globalNamespace + def components: ArrayBuffer[Component] = dynamicContext.components + + def pushCommand[T <: Command](c: T): T = { + dynamicContext.currentModule.foreach(_._commands += c) + c + } + def pushOp[T <: Data](cmd: DefPrim[T]): T = pushCommand(cmd).id + + def errors: ErrorLog = dynamicContext.errors + def error(m: => String): Unit = errors.error(m) + + def build[T <: Module](f: => T): Circuit = { + dynamicContextVar.withValue(Some(new DynamicContext)) { + errors.info("Elaborating design...") + val mod = f + mod.forceName(mod.name, globalNamespace) + errors.checkpoint() + errors.info("Done elaborating.") + + Circuit(components.last.name, components) + } + } +} diff --git a/chiselFrontend/src/main/scala/chisel3/internal/Error.scala b/chiselFrontend/src/main/scala/chisel3/internal/Error.scala new file mode 100644 index 00000000..f0481dc4 --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel3/internal/Error.scala @@ -0,0 +1,91 @@ +// See LICENSE for license details. + +package chisel.internal + +import scala.collection.mutable.ArrayBuffer + +import chisel.core._ + +class ChiselException(message: String, cause: Throwable) extends Exception(message, cause) + +private[chisel] object throwException { + def apply(s: String, t: Throwable = null): Nothing = + throw new ChiselException(s, t) +} + +/** Records and reports runtime errors and warnings. */ +private[chisel] class ErrorLog { + def hasErrors: Boolean = errors.exists(_.isFatal) + + /** Log an error message */ + def error(m: => String): Unit = + errors += new Error(m, getUserLineNumber) + + /** Log a warning message */ + def warning(m: => String): Unit = + errors += new Warning(m, getUserLineNumber) + + /** Emit an informational message */ + def info(m: String): Unit = + println(new Info("[%2.3f] %s".format(elapsedTime/1e3, m), None)) // scalastyle:ignore regex + + /** Prints error messages generated by Chisel at runtime. */ + def report(): Unit = errors foreach println // scalastyle:ignore regex + + /** Throw an exception if any errors have yet occurred. */ + def checkpoint(): Unit = if(hasErrors) { + import Console._ + throwException(errors.map(_ + "\n").reduce(_ + _) + + UNDERLINED + "CODE HAS " + errors.filter(_.isFatal).length + RESET + + UNDERLINED + " " + RED + "ERRORS" + RESET + + UNDERLINED + " and " + errors.filterNot(_.isFatal).length + RESET + + UNDERLINED + " " + YELLOW + "WARNINGS" + RESET) + } + + private def findFirstUserFrame(stack: Array[StackTraceElement]): Option[StackTraceElement] = { + def isUserCode(ste: StackTraceElement): Boolean = { + def isUserModule(c: Class[_]): Boolean = + c != null && (c == classOf[Module] || isUserModule(c.getSuperclass)) + isUserModule(Class.forName(ste.getClassName)) + } + + stack.indexWhere(isUserCode) match { + case x if x < 0 => None + case x => Some(stack(x)) + } + } + + private def getUserLineNumber = + findFirstUserFrame(Thread.currentThread().getStackTrace) + + private val errors = ArrayBuffer[LogEntry]() + + private val startTime = System.currentTimeMillis + private def elapsedTime: Long = System.currentTimeMillis - startTime +} + +private abstract class LogEntry(msg: => String, line: Option[StackTraceElement]) { + def isFatal: Boolean = false + def format: String + + override def toString: String = line match { + case Some(l) => s"${format} ${l.getFileName}:${l.getLineNumber}: ${msg} in class ${l.getClassName}" + case None => s"${format} ${msg}" + } + + protected def tag(name: String, color: String): String = + s"[${color}${name}${Console.RESET}]" +} + +private class Error(msg: => String, line: Option[StackTraceElement]) extends LogEntry(msg, line) { + override def isFatal: Boolean = true + def format: String = tag("error", Console.RED) +} + +private class Warning(msg: => String, line: Option[StackTraceElement]) extends LogEntry(msg, line) { + def format: String = tag("warn", Console.YELLOW) +} + +private class Info(msg: => String, line: Option[StackTraceElement]) extends LogEntry(msg, line) { + def format: String = tag("info", Console.MAGENTA) +} diff --git a/chiselFrontend/src/main/scala/chisel3/internal/SourceInfo.scala b/chiselFrontend/src/main/scala/chisel3/internal/SourceInfo.scala new file mode 100644 index 00000000..c20bd130 --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel3/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/chisel3/internal/firrtl/IR.scala b/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala new file mode 100644 index 00000000..70e9938b --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala @@ -0,0 +1,190 @@ +// See LICENSE for license details. + +package chisel.internal.firrtl + +import chisel._ +import core._ +import chisel.internal._ +import chisel.internal.sourceinfo.{SourceInfo, NoSourceInfo} + +case class PrimOp(val name: String) { + override def toString: String = name +} + +object PrimOp { + val AddOp = PrimOp("add") + val SubOp = PrimOp("sub") + val TailOp = PrimOp("tail") + val HeadOp = PrimOp("head") + val TimesOp = PrimOp("mul") + val DivideOp = PrimOp("div") + val RemOp = PrimOp("rem") + val ShiftLeftOp = PrimOp("shl") + val ShiftRightOp = PrimOp("shr") + val DynamicShiftLeftOp = PrimOp("dshl") + val DynamicShiftRightOp = PrimOp("dshr") + val BitAndOp = PrimOp("and") + val BitOrOp = PrimOp("or") + val BitXorOp = PrimOp("xor") + val BitNotOp = PrimOp("not") + val ConcatOp = PrimOp("cat") + val BitsExtractOp = PrimOp("bits") + val LessOp = PrimOp("lt") + val LessEqOp = PrimOp("leq") + val GreaterOp = PrimOp("gt") + val GreaterEqOp = PrimOp("geq") + val EqualOp = PrimOp("eq") + val PadOp = PrimOp("pad") + val NotEqualOp = PrimOp("neq") + val NegOp = PrimOp("neg") + val MultiplexOp = PrimOp("mux") + val XorReduceOp = PrimOp("xorr") + val ConvertOp = PrimOp("cvt") + val AsUIntOp = PrimOp("asUInt") + val AsSIntOp = PrimOp("asSInt") +} + +abstract class Arg { + def fullName(ctx: Component): String = name + def name: String +} + +case class Node(id: HasId) extends Arg { + override def fullName(ctx: Component): String = id.getRef.fullName(ctx) + def name: String = id.getRef.name +} + +abstract class LitArg(val num: BigInt, widthArg: Width) extends Arg { + private[chisel] def forcedWidth = widthArg.known + private[chisel] def width: Width = if (forcedWidth) widthArg else Width(minWidth) + + protected def minWidth: Int + if (forcedWidth) { + require(widthArg.get >= minWidth, + s"The literal value ${num} was elaborated with a specificed width of ${widthArg.get} bits, but at least ${minWidth} bits are required.") + } +} + +case class ILit(n: BigInt) extends Arg { + def name: String = n.toString +} + +case class ULit(n: BigInt, w: Width) extends LitArg(n, w) { + def name: String = "UInt" + width + "(\"h0" + num.toString(16) + "\")" + def minWidth: Int = 1 max n.bitLength + + require(n >= 0, s"UInt literal ${n} is negative") +} + +case class SLit(n: BigInt, w: Width) extends LitArg(n, w) { + def name: String = { + val unsigned = if (n < 0) (BigInt(1) << width.get) + n else n + s"asSInt(${ULit(unsigned, width).name})" + } + def minWidth: Int = 1 + n.bitLength +} + +case class Ref(name: String) extends Arg +case class ModuleIO(mod: Module, name: String) extends Arg { + override def fullName(ctx: Component): String = + if (mod eq ctx.id) name else s"${mod.getRef.name}.$name" +} +case class Slot(imm: Node, name: String) extends Arg { + override def fullName(ctx: Component): String = + if (imm.fullName(ctx).isEmpty) name else s"${imm.fullName(ctx)}.${name}" +} +case class Index(imm: Arg, value: Arg) extends Arg { + def name: String = s"[$value]" + override def fullName(ctx: Component): String = s"${imm.fullName(ctx)}[${value.fullName(ctx)}]" +} + +object Width { + def apply(x: Int): Width = KnownWidth(x) + def apply(): Width = UnknownWidth() +} + +sealed abstract class Width { + type W = Int + def max(that: Width): Width = this.op(that, _ max _) + def + (that: Width): Width = this.op(that, _ + _) + def + (that: Int): Width = this.op(this, (a, b) => a + that) + def shiftRight(that: Int): Width = this.op(this, (a, b) => 0 max (a - that)) + def dynamicShiftLeft(that: Width): Width = + this.op(that, (a, b) => a + (1 << b) - 1) + + def known: Boolean + def get: W + protected def op(that: Width, f: (W, W) => W): Width +} + +sealed case class UnknownWidth() extends Width { + def known: Boolean = false + def get: Int = None.get + def op(that: Width, f: (W, W) => W): Width = this + override def toString: String = "" +} + +sealed case class KnownWidth(value: Int) extends Width { + require(value >= 0) + def known: Boolean = true + def get: Int = value + def op(that: Width, f: (W, W) => W): Width = that match { + case KnownWidth(x) => KnownWidth(f(value, x)) + case _ => that + } + override def toString: String = s"<${value.toString}>" +} + +sealed abstract class MemPortDirection(name: String) { + override def toString: String = name +} +object MemPortDirection { + object READ extends MemPortDirection("read") + object WRITE extends MemPortDirection("write") + object RDWR extends MemPortDirection("rdwr") + object INFER extends MemPortDirection("infer") +} + +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](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(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) = { + require(x.toInt >= 0) + if (x == '"' || x == '\\') { + s"\\${x}" + } else if (x == '\n') { + "\\n" + } else { + require(x.toInt >= 32) // TODO \xNN once FIRRTL issue #59 is resolved + x + } + } + formatIn.map(escaped _).mkString + } +} + +case class Circuit(name: String, components: Seq[Component]) diff --git a/coreMacros/src/main/scala/chisel/internal/sourceinfo/SourceInfoTransform.scala b/coreMacros/src/main/scala/chisel/internal/sourceinfo/SourceInfoTransform.scala deleted file mode 100644 index 10b677b6..00000000 --- a/coreMacros/src/main/scala/chisel/internal/sourceinfo/SourceInfoTransform.scala +++ /dev/null @@ -1,156 +0,0 @@ -// See LICENSE for license details. - -// This file transform macro definitions to explicitly add implicit source info to Chisel method -// calls. - -package chisel.internal.sourceinfo - -import scala.language.experimental.macros -import scala.reflect.macros.blackbox.Context -import scala.reflect.macros.whitebox - - -/** Transforms a function call so that it can both provide implicit-style source information and - * have a chained apply call. Without macros, only one is possible, since having a implicit - * argument in the definition will cause the compiler to interpret a chained apply as an - * explicit implicit argument and give type errors. - * - * Instead of an implicit argument, the public-facing function no longer takes a SourceInfo at all. - * The macro transforms the public-facing function into a call to an internal function that takes - * an explicit SourceInfo by inserting an implicitly[SourceInfo] as the explicit argument. - */ -trait SourceInfoTransformMacro { - val c: Context - import c.universe._ - def thisObj = c.prefix.tree - def implicitSourceInfo = q"implicitly[_root_.chisel.internal.sourceinfo.SourceInfo]" -} - -class WireTransform(val c: Context) extends SourceInfoTransformMacro { - import c.universe._ - def apply[T: c.WeakTypeTag](t: c.Tree): c.Tree = { - val tpe = weakTypeOf[T] - q"$thisObj.do_apply($t, null.asInstanceOf[$tpe])($implicitSourceInfo)" - } -} - -class UIntTransform(val c: Context) extends SourceInfoTransformMacro { - import c.universe._ - def bitset(off: c.Tree, dat: c.Tree): c.Tree = { - q"$thisObj.do_bitSet($off, $dat)($implicitSourceInfo)" - } -} - -// Module instantiation transform -class InstTransform(val c: Context) extends SourceInfoTransformMacro { - import c.universe._ - def apply[T: c.WeakTypeTag](bc: c.Tree): c.Tree = { - q"$thisObj.do_apply($bc)($implicitSourceInfo)" - } -} - -class MemTransform(val c: Context) extends SourceInfoTransformMacro { - import c.universe._ - def apply[T: c.WeakTypeTag](size: c.Tree, t: c.Tree): c.Tree = { - q"$thisObj.do_apply($size, $t)($implicitSourceInfo)" - } -} - -class RegTransform(val c: Context) extends SourceInfoTransformMacro { - import c.universe._ - def apply[T: c.WeakTypeTag](t: c.Tree): c.Tree = { - val tpe = weakTypeOf[T] - q"$thisObj.do_apply($t, null.asInstanceOf[$tpe], null.asInstanceOf[$tpe])($implicitSourceInfo)" - } -} - -class MuxTransform(val c: Context) extends SourceInfoTransformMacro { - import c.universe._ - def apply[T: c.WeakTypeTag](cond: c.Tree, con: c.Tree, alt: c.Tree): c.Tree = { - val tpe = weakTypeOf[T] - q"$thisObj.do_apply[$tpe]($cond, $con, $alt)($implicitSourceInfo)" - } -} - -class VecTransform(val c: Context) extends SourceInfoTransformMacro { - import c.universe._ - def apply_elts(elts: c.Tree): c.Tree = { - q"$thisObj.do_apply($elts)($implicitSourceInfo)" - } - def apply_elt0(elt0: c.Tree, elts: c.Tree*): c.Tree = { - q"$thisObj.do_apply($elt0, ..$elts)($implicitSourceInfo)" - } - def tabulate(n: c.Tree)(gen: c.Tree): c.Tree = { - q"$thisObj.do_tabulate($n)($gen)($implicitSourceInfo)" - } - def fill(n: c.Tree)(gen: c.Tree): c.Tree = { - q"$thisObj.do_fill($n)($gen)($implicitSourceInfo)" - } - def contains(x: c.Tree)(ev: c.Tree): c.Tree = { - q"$thisObj.do_contains($x)($implicitSourceInfo, $ev)" - } -} - -/** "Automatic" source information transform / insertion macros, which generate the function name - * based on the macro invocation (instead of explicitly writing out every transform). - */ -abstract class AutoSourceTransform extends SourceInfoTransformMacro { - import c.universe._ - /** Returns the TermName of the transformed function, which is the applied function name with do_ - * prepended. - */ - def doFuncTerm = { - val funcName = c.macroApplication match { - case q"$_.$funcName[..$_](...$_)" => funcName - case _ => throw new Exception(s"Chisel Internal Error: Could not resolve function name from macro application: ${showCode(c.macroApplication)}") - } - TermName("do_" + funcName) - } -} - -class SourceInfoTransform(val c: Context) extends AutoSourceTransform { - import c.universe._ - - def noArg(): c.Tree = { - q"$thisObj.$doFuncTerm($implicitSourceInfo)" - } - - def thatArg(that: c.Tree): c.Tree = { - q"$thisObj.$doFuncTerm($that)($implicitSourceInfo)" - } - - def nArg(n: c.Tree): c.Tree = { - q"$thisObj.$doFuncTerm($n)($implicitSourceInfo)" - } - - def pArg(p: c.Tree): c.Tree = { - q"$thisObj.$doFuncTerm($p)($implicitSourceInfo)" - } - - def inArg(in: c.Tree): c.Tree = { - q"$thisObj.$doFuncTerm($in)($implicitSourceInfo)" - } - - def xArg(x: c.Tree): c.Tree = { - q"$thisObj.$doFuncTerm($x)($implicitSourceInfo)" - } - - def xyArg(x: c.Tree, y: c.Tree): c.Tree = { - q"$thisObj.$doFuncTerm($x, $y)($implicitSourceInfo)" - } -} - -/** Special whitebox version of the blackbox SourceInfoTransform, used when fun things need to happen to satisfy the - * type system while preventing the use of macro overrides. - */ -class SourceInfoWhiteboxTransform(val c: whitebox.Context) extends AutoSourceTransform { - import c.universe._ - - def noArg(): c.Tree = { - q"$thisObj.$doFuncTerm($implicitSourceInfo)" - } - - def thatArg(that: c.Tree): c.Tree = { - q"$thisObj.$doFuncTerm($that)($implicitSourceInfo)" - } -} diff --git a/coreMacros/src/main/scala/chisel3/internal/sourceinfo/SourceInfoTransform.scala b/coreMacros/src/main/scala/chisel3/internal/sourceinfo/SourceInfoTransform.scala new file mode 100644 index 00000000..10b677b6 --- /dev/null +++ b/coreMacros/src/main/scala/chisel3/internal/sourceinfo/SourceInfoTransform.scala @@ -0,0 +1,156 @@ +// See LICENSE for license details. + +// This file transform macro definitions to explicitly add implicit source info to Chisel method +// calls. + +package chisel.internal.sourceinfo + +import scala.language.experimental.macros +import scala.reflect.macros.blackbox.Context +import scala.reflect.macros.whitebox + + +/** Transforms a function call so that it can both provide implicit-style source information and + * have a chained apply call. Without macros, only one is possible, since having a implicit + * argument in the definition will cause the compiler to interpret a chained apply as an + * explicit implicit argument and give type errors. + * + * Instead of an implicit argument, the public-facing function no longer takes a SourceInfo at all. + * The macro transforms the public-facing function into a call to an internal function that takes + * an explicit SourceInfo by inserting an implicitly[SourceInfo] as the explicit argument. + */ +trait SourceInfoTransformMacro { + val c: Context + import c.universe._ + def thisObj = c.prefix.tree + def implicitSourceInfo = q"implicitly[_root_.chisel.internal.sourceinfo.SourceInfo]" +} + +class WireTransform(val c: Context) extends SourceInfoTransformMacro { + import c.universe._ + def apply[T: c.WeakTypeTag](t: c.Tree): c.Tree = { + val tpe = weakTypeOf[T] + q"$thisObj.do_apply($t, null.asInstanceOf[$tpe])($implicitSourceInfo)" + } +} + +class UIntTransform(val c: Context) extends SourceInfoTransformMacro { + import c.universe._ + def bitset(off: c.Tree, dat: c.Tree): c.Tree = { + q"$thisObj.do_bitSet($off, $dat)($implicitSourceInfo)" + } +} + +// Module instantiation transform +class InstTransform(val c: Context) extends SourceInfoTransformMacro { + import c.universe._ + def apply[T: c.WeakTypeTag](bc: c.Tree): c.Tree = { + q"$thisObj.do_apply($bc)($implicitSourceInfo)" + } +} + +class MemTransform(val c: Context) extends SourceInfoTransformMacro { + import c.universe._ + def apply[T: c.WeakTypeTag](size: c.Tree, t: c.Tree): c.Tree = { + q"$thisObj.do_apply($size, $t)($implicitSourceInfo)" + } +} + +class RegTransform(val c: Context) extends SourceInfoTransformMacro { + import c.universe._ + def apply[T: c.WeakTypeTag](t: c.Tree): c.Tree = { + val tpe = weakTypeOf[T] + q"$thisObj.do_apply($t, null.asInstanceOf[$tpe], null.asInstanceOf[$tpe])($implicitSourceInfo)" + } +} + +class MuxTransform(val c: Context) extends SourceInfoTransformMacro { + import c.universe._ + def apply[T: c.WeakTypeTag](cond: c.Tree, con: c.Tree, alt: c.Tree): c.Tree = { + val tpe = weakTypeOf[T] + q"$thisObj.do_apply[$tpe]($cond, $con, $alt)($implicitSourceInfo)" + } +} + +class VecTransform(val c: Context) extends SourceInfoTransformMacro { + import c.universe._ + def apply_elts(elts: c.Tree): c.Tree = { + q"$thisObj.do_apply($elts)($implicitSourceInfo)" + } + def apply_elt0(elt0: c.Tree, elts: c.Tree*): c.Tree = { + q"$thisObj.do_apply($elt0, ..$elts)($implicitSourceInfo)" + } + def tabulate(n: c.Tree)(gen: c.Tree): c.Tree = { + q"$thisObj.do_tabulate($n)($gen)($implicitSourceInfo)" + } + def fill(n: c.Tree)(gen: c.Tree): c.Tree = { + q"$thisObj.do_fill($n)($gen)($implicitSourceInfo)" + } + def contains(x: c.Tree)(ev: c.Tree): c.Tree = { + q"$thisObj.do_contains($x)($implicitSourceInfo, $ev)" + } +} + +/** "Automatic" source information transform / insertion macros, which generate the function name + * based on the macro invocation (instead of explicitly writing out every transform). + */ +abstract class AutoSourceTransform extends SourceInfoTransformMacro { + import c.universe._ + /** Returns the TermName of the transformed function, which is the applied function name with do_ + * prepended. + */ + def doFuncTerm = { + val funcName = c.macroApplication match { + case q"$_.$funcName[..$_](...$_)" => funcName + case _ => throw new Exception(s"Chisel Internal Error: Could not resolve function name from macro application: ${showCode(c.macroApplication)}") + } + TermName("do_" + funcName) + } +} + +class SourceInfoTransform(val c: Context) extends AutoSourceTransform { + import c.universe._ + + def noArg(): c.Tree = { + q"$thisObj.$doFuncTerm($implicitSourceInfo)" + } + + def thatArg(that: c.Tree): c.Tree = { + q"$thisObj.$doFuncTerm($that)($implicitSourceInfo)" + } + + def nArg(n: c.Tree): c.Tree = { + q"$thisObj.$doFuncTerm($n)($implicitSourceInfo)" + } + + def pArg(p: c.Tree): c.Tree = { + q"$thisObj.$doFuncTerm($p)($implicitSourceInfo)" + } + + def inArg(in: c.Tree): c.Tree = { + q"$thisObj.$doFuncTerm($in)($implicitSourceInfo)" + } + + def xArg(x: c.Tree): c.Tree = { + q"$thisObj.$doFuncTerm($x)($implicitSourceInfo)" + } + + def xyArg(x: c.Tree, y: c.Tree): c.Tree = { + q"$thisObj.$doFuncTerm($x, $y)($implicitSourceInfo)" + } +} + +/** Special whitebox version of the blackbox SourceInfoTransform, used when fun things need to happen to satisfy the + * type system while preventing the use of macro overrides. + */ +class SourceInfoWhiteboxTransform(val c: whitebox.Context) extends AutoSourceTransform { + import c.universe._ + + def noArg(): c.Tree = { + q"$thisObj.$doFuncTerm($implicitSourceInfo)" + } + + def thatArg(that: c.Tree): c.Tree = { + q"$thisObj.$doFuncTerm($that)($implicitSourceInfo)" + } +} diff --git a/src/main/scala/chisel/Driver.scala b/src/main/scala/chisel/Driver.scala deleted file mode 100644 index ba2b1389..00000000 --- a/src/main/scala/chisel/Driver.scala +++ /dev/null @@ -1,132 +0,0 @@ -// See LICENSE for license details. - -package chisel - -import scala.sys.process._ -import java.io._ - -import internal._ -import internal.firrtl._ - -trait BackendCompilationUtilities { - /** Create a temporary directory with the prefix name. Exists here because it doesn't in Java 6. - */ - def createTempDirectory(prefix: String): File = { - val temp = File.createTempFile(prefix, "") - if (!temp.delete()) { - throw new IOException(s"Unable to delete temp file '$temp'") - } - if (!temp.mkdir()) { - throw new IOException(s"Unable to create temp directory '$temp'") - } - temp - } - - def makeHarness(template: String => String, post: String)(f: File): File = { - val prefix = f.toString.split("/").last - val vf = new File(f.toString + post) - val w = new FileWriter(vf) - w.write(template(prefix)) - w.close() - vf - } - - def firrtlToVerilog(prefix: String, dir: File): ProcessBuilder = { - Process( - Seq("firrtl", - "-i", s"$prefix.fir", - "-o", s"$prefix.v", - "-X", "verilog"), - dir) - } - - /** Generates a Verilator invocation to convert Verilog sources to C++ - * simulation sources. - * - * The Verilator prefix will be V$dutFile, and running this will generate - * C++ sources and headers as well as a makefile to compile them. - * - * @param dutFile name of the DUT .v without the .v extension - * @param name of the top-level module in the design - * @param dir output directory - * @param vSources list of additional Verilog sources to compile - * @param cppHarness C++ testharness to compile/link against - */ - def verilogToCpp( - dutFile: String, - topModule: String, - dir: File, - vSources: Seq[File], - cppHarness: File - ): ProcessBuilder = { - val command = Seq("verilator", - "--cc", s"$dutFile.v") ++ - vSources.map(file => Seq("-v", file.toString)).flatten ++ - Seq("--assert", - "-Wno-fatal", - "-Wno-WIDTH", - "-Wno-STMTDLY", - "--trace", - "-O2", - "--top-module", topModule, - "+define+TOP_TYPE=V" + dutFile, - s"+define+PRINTF_COND=!$topModule.reset", - "-CFLAGS", - s"""-Wno-undefined-bool-conversion -O2 -DTOP_TYPE=V$dutFile -include V$dutFile.h""", - "-Mdir", dir.toString, - "--exe", cppHarness.toString) - System.out.println(s"${command.mkString(" ")}") // scalastyle:ignore regex - command - } - - def cppToExe(prefix: String, dir: File): ProcessBuilder = - Seq("make", "-C", dir.toString, "-j", "-f", s"V${prefix}.mk", s"V${prefix}") - - def executeExpectingFailure( - prefix: String, - dir: File, - assertionMsg: String = "Assertion failed"): Boolean = { - var triggered = false - val e = Process(s"./V${prefix}", dir) ! - ProcessLogger(line => { - triggered = triggered || line.contains(assertionMsg) - System.out.println(line) // scalastyle:ignore regex - }) - triggered - } - - def executeExpectingSuccess(prefix: String, dir: File): Boolean = { - !executeExpectingFailure(prefix, dir) - } -} - -object Driver extends BackendCompilationUtilities { - - /** Elaborates the Module specified in the gen function into a Circuit - * - * @param gen a function that creates a Module hierarchy - * @return the resulting Chisel IR in the form of a Circuit (TODO: Should be FIRRTL IR) - */ - def elaborate[T <: Module](gen: () => T): Circuit = Builder.build(Module(gen())) - - def emit[T <: Module](gen: () => T): String = Emitter.emit(elaborate(gen)) - - def dumpFirrtl(ir: Circuit, optName: Option[File]): File = { - val f = optName.getOrElse(new File(ir.name + ".fir")) - val w = new FileWriter(f) - w.write(Emitter.emit(ir)) - w.close() - f - } - - private var target_dir: Option[String] = None - def parseArgs(args: Array[String]): Unit = { - for (i <- 0 until args.size) { - if (args(i) == "--targetDir") { - target_dir = Some(args(i + 1)) - } - } - } - - def targetDir(): String = { target_dir getOrElse new File(".").getCanonicalPath } -} diff --git a/src/main/scala/chisel/compatibility.scala b/src/main/scala/chisel/compatibility.scala deleted file mode 100644 index 56088562..00000000 --- a/src/main/scala/chisel/compatibility.scala +++ /dev/null @@ -1,150 +0,0 @@ -// See LICENSE for license details. - -// Allows legacy users to continue using Chisel (capital C) package name while -// moving to the more standard package naming convention chisel (lowercase c). - -package object Chisel { - type Direction = chisel.core.Direction - val INPUT = chisel.core.INPUT - val OUTPUT = chisel.core.OUTPUT - val NO_DIR = chisel.core.NO_DIR - - type Flipped = chisel.core.Flipped - type Data = chisel.core.Data - val Wire = chisel.core.Wire - val Clock = chisel.core.Clock - type Clock = chisel.core.Clock - - type Aggregate = chisel.core.Aggregate - val Vec = chisel.core.Vec - type Vec[T <: Data] = chisel.core.Vec[T] - type VecLike[T <: Data] = chisel.core.VecLike[T] - type Bundle = chisel.core.Bundle - - val assert = chisel.core.assert - - type Element = chisel.core.Element - type Bits = chisel.core.Bits - val Bits = chisel.core.Bits - type Num[T <: Data] = chisel.core.Num[T] - type UInt = chisel.core.UInt - val UInt = chisel.core.UInt - type SInt = chisel.core.SInt - val SInt = chisel.core.SInt - type Bool = chisel.core.Bool - val Bool = chisel.core.Bool - val Mux = chisel.core.Mux - - type BlackBox = chisel.core.BlackBox - - val Mem = chisel.core.Mem - type MemBase[T <: Data] = chisel.core.MemBase[T] - type Mem[T <: Data] = chisel.core.Mem[T] - val SeqMem = chisel.core.SeqMem - type SeqMem[T <: Data] = chisel.core.SeqMem[T] - - val Module = chisel.core.Module - type Module = chisel.core.Module - - val printf = chisel.core.printf - - val Reg = chisel.core.Reg - - val when = chisel.core.when - type WhenContext = chisel.core.WhenContext - - - type BackendCompilationUtilities = chisel.BackendCompilationUtilities - val Driver = chisel.Driver - type FileSystemUtilities = chisel.compatibility.FileSystemUtilities - val ImplicitConversions = chisel.util.ImplicitConversions - val chiselMain = chisel.compatibility.chiselMain - val throwException = chisel.compatibility.throwException - val debug = chisel.compatibility.debug - - object testers { - type BasicTester = chisel.testers.BasicTester - val TesterDriver = chisel.testers.TesterDriver - } - - - val log2Up = chisel.util.log2Up - val log2Ceil = chisel.util.log2Ceil - val log2Down = chisel.util.log2Down - val log2Floor = chisel.util.log2Floor - val isPow2 = chisel.util.isPow2 - - val BitPat = chisel.util.BitPat - type BitPat = chisel.util.BitPat - - type ArbiterIO[T <: Data] = chisel.util.ArbiterIO[T] - type LockingArbiterLike[T <: Data] = chisel.util.LockingArbiterLike[T] - type LockingRRArbiter[T <: Data] = chisel.util.LockingRRArbiter[T] - type LockingArbiter[T <: Data] = chisel.util.LockingArbiter[T] - type RRArbiter[T <: Data] = chisel.util.RRArbiter[T] - type Arbiter[T <: Data] = chisel.util.Arbiter[T] - - val FillInterleaved = chisel.util.FillInterleaved - val PopCount = chisel.util.PopCount - val Fill = chisel.util.Fill - val Reverse = chisel.util.Reverse - - val Cat = chisel.util.Cat - - val Log2 = chisel.util.Log2 - - val unless = chisel.util.unless - type SwitchContext[T <: Bits] = chisel.util.SwitchContext[T] - val is = chisel.util.is - val switch = chisel.util.switch - - type Counter = chisel.util.Counter - val Counter = chisel.util.Counter - - type DecoupledIO[+T <: Data] = chisel.util.DecoupledIO[T] - val Decoupled = chisel.util.Decoupled - type EnqIO[T <: Data] = chisel.util.EnqIO[T] - type DeqIO[T <: Data] = chisel.util.DeqIO[T] - type DecoupledIOC[+T <: Data] = chisel.util.DecoupledIOC[T] - type QueueIO[T <: Data] = chisel.util.QueueIO[T] - type Queue[T <: Data] = chisel.util.Queue[T] - val Queue = chisel.util.Queue - - val Enum = chisel.util.Enum - - val LFSR16 = chisel.util.LFSR16 - - val ListLookup = chisel.util.ListLookup - val Lookup = chisel.util.Lookup - - val Mux1H = chisel.util.Mux1H - val PriorityMux = chisel.util.PriorityMux - val MuxLookup = chisel.util.MuxLookup - val MuxCase = chisel.util.MuxCase - - val OHToUInt = chisel.util.OHToUInt - val PriorityEncoder = chisel.util.PriorityEncoder - val UIntToOH = chisel.util.UIntToOH - val PriorityEncoderOH = chisel.util.PriorityEncoderOH - - val RegNext = chisel.util.RegNext - val RegInit = chisel.util.RegInit - val RegEnable = chisel.util.RegEnable - val ShiftRegister = chisel.util.ShiftRegister - - type ValidIO[+T <: Data] = chisel.util.ValidIO[T] - val Valid = chisel.util.Valid - val Pipe = chisel.util.Pipe - type Pipe[T <: Data] = chisel.util.Pipe[T] - - - import chisel.internal.firrtl.Width - implicit def fromBigIntToLiteral(x: BigInt): chisel.fromBigIntToLiteral = - new chisel.fromBigIntToLiteral(x) - implicit def fromIntToLiteral(x: Int): chisel.fromIntToLiteral= - new chisel.fromIntToLiteral(x) - implicit def fromStringToLiteral(x: String): chisel.fromStringToLiteral= - new chisel.fromStringToLiteral(x) - implicit def fromBooleanToLiteral(x: Boolean): chisel.fromBooleanToLiteral= - new chisel.fromBooleanToLiteral(x) -} diff --git a/src/main/scala/chisel/compatibility/FileSystemUtilities.scala b/src/main/scala/chisel/compatibility/FileSystemUtilities.scala deleted file mode 100644 index d12e627d..00000000 --- a/src/main/scala/chisel/compatibility/FileSystemUtilities.scala +++ /dev/null @@ -1,12 +0,0 @@ -// See LICENSE for license details. - -package chisel.compatibility - -import chisel._ - -@deprecated("FileSystemUtilities doesn't exist in chisel3", "3.0.0") -trait FileSystemUtilities { - def createOutputFile(name: String): java.io.FileWriter = { - new java.io.FileWriter(Driver.targetDir + "/" + name) - } -} diff --git a/src/main/scala/chisel/compatibility/Main.scala b/src/main/scala/chisel/compatibility/Main.scala deleted file mode 100644 index 9072bfcf..00000000 --- a/src/main/scala/chisel/compatibility/Main.scala +++ /dev/null @@ -1,19 +0,0 @@ -// See LICENSE for license details. - -package chisel.compatibility - -import java.io.File - -import chisel._ - -@deprecated("chiselMain doesn't exist in Chisel3", "3.0") object chiselMain { - def apply[T <: Module](args: Array[String], gen: () => T): Unit = - Predef.assert(false, "No more chiselMain in Chisel3") - - def run[T <: Module] (args: Array[String], gen: () => T): Unit = { - val circuit = Driver.elaborate(gen) - Driver.parseArgs(args) - val output_file = new File(Driver.targetDir + "/" + circuit.name + ".fir") - Driver.dumpFirrtl(circuit, Option(output_file)) - } -} diff --git a/src/main/scala/chisel/compatibility/debug.scala b/src/main/scala/chisel/compatibility/debug.scala deleted file mode 100644 index 8850c76b..00000000 --- a/src/main/scala/chisel/compatibility/debug.scala +++ /dev/null @@ -1,8 +0,0 @@ -package chisel.compatibility - -import chisel.core._ - -@deprecated("debug doesn't do anything in Chisel3 as no pruning happens in the frontend", "chisel3") -object debug { // scalastyle:ignore object.name - def apply (arg: Data): Data = arg -} diff --git a/src/main/scala/chisel/compatibility/throwException.scala b/src/main/scala/chisel/compatibility/throwException.scala deleted file mode 100644 index 3b9fd06e..00000000 --- a/src/main/scala/chisel/compatibility/throwException.scala +++ /dev/null @@ -1,14 +0,0 @@ -// See LICENSE for license details. - -package chisel.compatibility - -import chisel._ - -@deprecated("throwException doesn't exist in Chisel3", "3.0.0") -@throws(classOf[Exception]) -object throwException { - def apply(s: String, t: Throwable = null) = { - val xcpt = new Exception(s, t) - throw xcpt - } -} diff --git a/src/main/scala/chisel/internal/firrtl/Emitter.scala b/src/main/scala/chisel/internal/firrtl/Emitter.scala deleted file mode 100644 index e48eb226..00000000 --- a/src/main/scala/chisel/internal/firrtl/Emitter.scala +++ /dev/null @@ -1,112 +0,0 @@ -// See LICENSE for license details. - -package chisel.internal.firrtl -import chisel._ -import chisel.internal.sourceinfo.{NoSourceInfo, SourceLine} - -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 = { - val firrtlLine = 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() - s"skip" - } - e.sourceInfo match { - case SourceLine(filename, line, col) => s"${firrtlLine} @[${filename} ${line}:${col}] " - case _: NoSourceInfo => firrtlLine - } - } - - // 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/src/main/scala/chisel/package.scala b/src/main/scala/chisel/package.scala deleted file mode 100644 index f7ed6b13..00000000 --- a/src/main/scala/chisel/package.scala +++ /dev/null @@ -1,82 +0,0 @@ -package object chisel { - import scala.language.experimental.macros - - import internal.firrtl.Width - import internal.sourceinfo.{SourceInfo, SourceInfoTransform} - import util.BitPat - - - type Direction = chisel.core.Direction - val INPUT = chisel.core.INPUT - val OUTPUT = chisel.core.OUTPUT - val NO_DIR = chisel.core.NO_DIR - type Flipped = chisel.core.Flipped - type Data = chisel.core.Data - val Wire = chisel.core.Wire - val Clock = chisel.core.Clock - type Clock = chisel.core.Clock - - type Aggregate = chisel.core.Aggregate - val Vec = chisel.core.Vec - type Vec[T <: Data] = chisel.core.Vec[T] - type VecLike[T <: Data] = chisel.core.VecLike[T] - type Bundle = chisel.core.Bundle - - val assert = chisel.core.assert - - type Element = chisel.core.Element - type Bits = chisel.core.Bits - val Bits = chisel.core.Bits - type Num[T <: Data] = chisel.core.Num[T] - type UInt = chisel.core.UInt - val UInt = chisel.core.UInt - type SInt = chisel.core.SInt - val SInt = chisel.core.SInt - type Bool = chisel.core.Bool - val Bool = chisel.core.Bool - val Mux = chisel.core.Mux - - type BlackBox = chisel.core.BlackBox - - val Mem = chisel.core.Mem - type MemBase[T <: Data] = chisel.core.MemBase[T] - type Mem[T <: Data] = chisel.core.Mem[T] - val SeqMem = chisel.core.SeqMem - type SeqMem[T <: Data] = chisel.core.SeqMem[T] - - val Module = chisel.core.Module - type Module = chisel.core.Module - - val printf = chisel.core.printf - - val Reg = chisel.core.Reg - - val when = chisel.core.when - type WhenContext = chisel.core.WhenContext - - - implicit class fromBigIntToLiteral(val x: BigInt) extends AnyVal { - def U: UInt = UInt(x, Width()) - def S: SInt = SInt(x, Width()) - } - implicit class fromIntToLiteral(val x: Int) extends AnyVal { - def U: UInt = UInt(BigInt(x), Width()) - def S: SInt = SInt(BigInt(x), Width()) - } - implicit class fromStringToLiteral(val x: String) extends AnyVal { - def U: UInt = UInt(x) - } - implicit class fromBooleanToLiteral(val x: Boolean) extends AnyVal { - def B: Bool = Bool(x) - } - - implicit class fromUIntToBitPatComparable(val x: UInt) extends AnyVal { - 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 === x - def do_!= (that: BitPat)(implicit sourceInfo: SourceInfo): Bool = that != x - def do_=/= (that: BitPat)(implicit sourceInfo: SourceInfo): Bool = that =/= x - } -} diff --git a/src/main/scala/chisel/testers/BasicTester.scala b/src/main/scala/chisel/testers/BasicTester.scala deleted file mode 100644 index 36ff7c52..00000000 --- a/src/main/scala/chisel/testers/BasicTester.scala +++ /dev/null @@ -1,38 +0,0 @@ -// See LICENSE for license details. - -package chisel.testers -import chisel._ - -import scala.language.experimental.macros - -import internal._ -import internal.Builder.pushCommand -import internal.firrtl._ -import internal.sourceinfo.SourceInfo - -class BasicTester extends Module { - // The testbench has no IOs, rather it should communicate using printf, assert, and stop. - val io = new Bundle() - - def popCount(n: Long): Int = n.toBinaryString.count(_=='1') - - /** Ends the test reporting success. - * - * 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. - */ - def stop()(implicit sourceInfo: SourceInfo) { - // TODO: rewrite this using library-style SourceInfo passing. - when (!reset) { - pushCommand(Stop(sourceInfo, Node(clock), 0)) - } - } - - /** The finish method provides a hook that subclasses of BasicTester can use to - * alter a circuit after their constructor has been called. - * For example, a specialized tester subclassing BasicTester could override finish in order to - * add flow control logic for a decoupled io port of a device under test - */ - def finish(): Unit = {} -} diff --git a/src/main/scala/chisel/testers/TesterDriver.scala b/src/main/scala/chisel/testers/TesterDriver.scala deleted file mode 100644 index 5c0275e0..00000000 --- a/src/main/scala/chisel/testers/TesterDriver.scala +++ /dev/null @@ -1,69 +0,0 @@ -// See LICENSE for license details. - -package chisel.testers - -import chisel._ -import scala.io.Source -import scala.sys.process._ -import java.io._ - -object TesterDriver extends BackendCompilationUtilities { - /** Copy the contents of a resource to a destination file. - */ - def copyResourceToFile(name: String, file: File) { - val in = getClass().getResourceAsStream(name) - if (in == null) { - throw new FileNotFoundException(s"Resource '$name'") - } - val out = new FileOutputStream(file) - Iterator.continually(in.read).takeWhile(-1 !=).foreach(out.write) - out.close() - } - - /** For use with modules that should successfully be elaborated by the - * frontend, and which can be turned into executables with assertions. */ - def execute(t: () => BasicTester, additionalVResources: Seq[String] = Seq()): Boolean = { - // Invoke the chisel compiler to get the circuit's IR - val circuit = Driver.elaborate(finishWrapper(t)) - - // Set up a bunch of file handlers based on a random temp filename, - // plus the quirks of Verilator's naming conventions - val target = circuit.name - - val path = createTempDirectory(target) - val fname = new File(path, target) - - // For now, dump the IR out to a file - Driver.dumpFirrtl(circuit, Some(new File(fname.toString + ".fir"))) - - // Copy CPP harness and other Verilog sources from resources into files - val cppHarness = new File(path, "top.cpp") - copyResourceToFile("/top.cpp", cppHarness) - val additionalVFiles = additionalVResources.map((name: String) => { - val mangledResourceName = name.replace("/", "_") - val out = new File(path, mangledResourceName) - copyResourceToFile(name, out) - out - }) - - // Use sys.Process to invoke a bunch of backend stuff, then run the resulting exe - if ((firrtlToVerilog(target, path) #&& - verilogToCpp(target, target, path, additionalVFiles, cppHarness) #&& - cppToExe(target, path)).! == 0) { - executeExpectingSuccess(target, path) - } else { - false - } - } - /** - * Calls the finish method of an BasicTester or a class that extends it. - * The finish method is a hook for code that augments the circuit built in the constructor. - */ - def finishWrapper(test: () => BasicTester): () => BasicTester = { - () => { - val tester = test() - tester.finish() - tester - } - } -} diff --git a/src/main/scala/chisel/util/Arbiter.scala b/src/main/scala/chisel/util/Arbiter.scala deleted file mode 100644 index 3723f2a9..00000000 --- a/src/main/scala/chisel/util/Arbiter.scala +++ /dev/null @@ -1,119 +0,0 @@ -// See LICENSE for license details. - -/** Arbiters in all shapes and sizes. - */ - -package chisel.util - -import chisel._ - -/** An I/O bundle for the Arbiter */ -class ArbiterIO[T <: Data](gen: T, n: Int) extends Bundle { - val in = Vec(n, Decoupled(gen)).flip - val out = Decoupled(gen) - val chosen = UInt(OUTPUT, log2Up(n)) -} - -/** Arbiter Control determining which producer has access */ -private object ArbiterCtrl -{ - def apply(request: Seq[Bool]): Seq[Bool] = request.length match { - case 0 => Seq() - case 1 => Seq(Bool(true)) - case _ => Bool(true) +: request.tail.init.scanLeft(request.head)(_ || _).map(!_) - } -} - -abstract class LockingArbiterLike[T <: Data](gen: T, n: Int, count: Int, needsLock: Option[T => Bool]) extends Module { - def grant: Seq[Bool] - def choice: UInt - val io = new ArbiterIO(gen, n) - - io.chosen := choice - io.out.valid := io.in(io.chosen).valid - io.out.bits := io.in(io.chosen).bits - - if (count > 1) { - val lockCount = Counter(count) - val lockIdx = Reg(UInt()) - val locked = lockCount.value =/= UInt(0) - val wantsLock = needsLock.map(_(io.out.bits)).getOrElse(Bool(true)) - - when (io.out.fire() && wantsLock) { - lockIdx := io.chosen - lockCount.inc() - } - - when (locked) { io.chosen := lockIdx } - for ((in, (g, i)) <- io.in zip grant.zipWithIndex) - in.ready := Mux(locked, lockIdx === UInt(i), g) && io.out.ready - } else { - for ((in, g) <- io.in zip grant) - in.ready := g && io.out.ready - } -} - -class LockingRRArbiter[T <: Data](gen: T, n: Int, count: Int, needsLock: Option[T => Bool] = None) - extends LockingArbiterLike[T](gen, n, count, needsLock) { - lazy val lastGrant = RegEnable(io.chosen, io.out.fire()) - lazy val grantMask = (0 until n).map(UInt(_) > lastGrant) - lazy val validMask = io.in zip grantMask map { case (in, g) => in.valid && g } - - override def grant: Seq[Bool] = { - val ctrl = ArbiterCtrl((0 until n).map(i => validMask(i)) ++ io.in.map(_.valid)) - (0 until n).map(i => ctrl(i) && grantMask(i) || ctrl(i + n)) - } - - override lazy val choice = Wire(init=UInt(n-1)) - for (i <- n-2 to 0 by -1) - when (io.in(i).valid) { choice := UInt(i) } - for (i <- n-1 to 1 by -1) - when (validMask(i)) { choice := UInt(i) } -} - -class LockingArbiter[T <: Data](gen: T, n: Int, count: Int, needsLock: Option[T => Bool] = None) - extends LockingArbiterLike[T](gen, n, count, needsLock) { - def grant: Seq[Bool] = ArbiterCtrl(io.in.map(_.valid)) - - override lazy val choice = Wire(init=UInt(n-1)) - for (i <- n-2 to 0 by -1) - when (io.in(i).valid) { choice := UInt(i) } -} - -/** Hardware module that is used to sequence n producers into 1 consumer. - Producers are chosen in round robin order. - - Example usage: - val arb = new RRArbiter(2, UInt()) - arb.io.in(0) <> producer0.io.out - arb.io.in(1) <> producer1.io.out - consumer.io.in <> arb.io.out - */ -class RRArbiter[T <: Data](gen:T, n: Int) extends LockingRRArbiter[T](gen, n, 1) - -/** Hardware module that is used to sequence n producers into 1 consumer. - Priority is given to lower producer - - Example usage: - val arb = Module(new Arbiter(2, UInt())) - arb.io.in(0) <> producer0.io.out - arb.io.in(1) <> producer1.io.out - consumer.io.in <> arb.io.out - */ -class Arbiter[T <: Data](gen: T, n: Int) extends Module { - val io = new ArbiterIO(gen, n) - - io.chosen := UInt(n-1) - io.out.bits := io.in(n-1).bits - for (i <- n-2 to 0 by -1) { - when (io.in(i).valid) { - io.chosen := UInt(i) - io.out.bits := io.in(i).bits - } - } - - val grant = ArbiterCtrl(io.in.map(_.valid)) - for ((in, g) <- io.in zip grant) - in.ready := g && io.out.ready - io.out.valid := !grant.last || io.in.last.valid -} diff --git a/src/main/scala/chisel/util/BitPat.scala b/src/main/scala/chisel/util/BitPat.scala deleted file mode 100644 index 13bbe1b0..00000000 --- a/src/main/scala/chisel/util/BitPat.scala +++ /dev/null @@ -1,89 +0,0 @@ -// See LICENSE for license details. - -package chisel.util - -import scala.language.experimental.macros - -import chisel._ -import chisel.internal.sourceinfo.{SourceInfo, SourceInfoTransform} - -object BitPat { - /** Parses a bit pattern string into (bits, mask, width). - * - * @return bits the literal value, with don't cares being 0 - * @return mask the mask bits, with don't cares being 0 and cares being 1 - * @return width the number of bits in the literal, including values and - * don't cares. - */ - private def parse(x: String): (BigInt, BigInt, Int) = { - // Notes: - // While Verilog Xs also handle octal and hex cases, there isn't a - // compelling argument and no one has asked for it. - // If ? parsing is to be exposed, the return API needs further scrutiny - // (especially with things like mask polarity). - require(x.head == 'b', "BitPats must be in binary and be prefixed with 'b'") - var bits = BigInt(0) - var mask = BigInt(0) - for (d <- x.tail) { - if (d != '_') { - require("01?".contains(d), "Literal: " + x + " contains illegal character: " + d) - mask = (mask << 1) + (if (d == '?') 0 else 1) - bits = (bits << 1) + (if (d == '1') 1 else 0) - } - } - (bits, mask, x.length - 1) - } - - /** Creates a [[BitPat]] literal from a string. - * - * @param n the literal value as a string, in binary, prefixed with 'b' - * @note legal characters are '0', '1', and '?', as well as '_' as white - * space (which are ignored) - */ - def apply(n: String): BitPat = { - val (bits, mask, width) = parse(n) - new BitPat(bits, mask, width) - } - - /** Creates a [[BitPat]] of all don't cares of the specified bitwidth. */ - def dontCare(width: Int): BitPat = BitPat("b" + ("?" * width)) - - @deprecated("Use BitPat.dontCare", "chisel3") - def DC(width: Int): BitPat = dontCare(width) // scalastyle:ignore method.name - - /** Allows BitPats to be used where a UInt is expected. - * - * @note the BitPat must not have don't care bits (will error out otherwise) - */ - def bitPatToUInt(x: BitPat): UInt = { - require(x.mask == (BigInt(1) << x.getWidth) - 1) - UInt(x.value, x.getWidth) - } - - /** Allows UInts to be used where a BitPat is expected, useful for when an - * interface is defined with BitPats but not all cases need the partial - * matching capability. - * - * @note the UInt must be a literal - */ - def apply(x: UInt): BitPat = { - require(x.isLit) - BitPat("b" + x.litValue.toString(2)) - } -} - -// TODO: Break out of Core? (this doesn't involve FIRRTL generation) -/** Bit patterns are literals with masks, used to represent values with don't - * cares. Equality comparisons will ignore don't care bits (for example, - * BitPat(0b10?1) === UInt(0b1001) and UInt(0b1011)). - */ -sealed class BitPat(val value: BigInt, val mask: BigInt, width: Int) { - def getWidth: Int = width - 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/src/main/scala/chisel/util/Bitwise.scala b/src/main/scala/chisel/util/Bitwise.scala deleted file mode 100644 index d7d62ea3..00000000 --- a/src/main/scala/chisel/util/Bitwise.scala +++ /dev/null @@ -1,74 +0,0 @@ -// See LICENSE for license details. - -/** Miscellaneous circuit generators operating on bits. - */ - -package chisel.util - -import chisel._ -import chisel.core.SeqUtils - -object FillInterleaved -{ - def apply(n: Int, in: UInt): UInt = apply(n, in.toBools) - def apply(n: Int, in: Seq[Bool]): UInt = Vec(in.map(Fill(n, _))).toBits -} - -/** Returns the number of bits set (i.e value is 1) in the input signal. - */ -object PopCount -{ - def apply(in: Iterable[Bool]): UInt = SeqUtils.count(in.toSeq) - def apply(in: Bits): UInt = apply((0 until in.getWidth).map(in(_))) -} - -/** Fill fans out a UInt to multiple copies */ -object Fill { - /** Fan out x n times */ - def apply(n: Int, x: UInt): UInt = { - n match { - case 0 => UInt(width=0) - case 1 => x - case y if n > 1 => - val p2 = Array.ofDim[UInt](log2Up(n + 1)) - p2(0) = x - for (i <- 1 until p2.length) - p2(i) = Cat(p2(i-1), p2(i-1)) - Cat((0 until log2Up(y + 1)).filter(i => (y & (1 << i)) != 0).map(p2(_))) - case _ => throw new IllegalArgumentException(s"n (=$n) must be nonnegative integer.") - } - } - /** Fan out x n times */ - def apply(n: Int, x: Bool): UInt = - if (n > 1) { - UInt(0,n) - x - } else { - apply(n, x: UInt) - } -} - -/** Litte/big bit endian convertion: reverse the order of the bits in a UInt. -*/ -object Reverse -{ - private def doit(in: UInt, length: Int): UInt = { - if (length == 1) { - in - } else if (isPow2(length) && length >= 8 && length <= 64) { - // This esoterica improves simulation performance - var res = in - var shift = length >> 1 - var mask = UInt((BigInt(1) << length) - 1, length) - do { - mask = mask ^ (mask(length-shift-1,0) << shift) - res = ((res >> shift) & mask) | ((res(length-shift-1,0) << shift) & ~mask) - shift = shift >> 1 - } while (shift > 0) - res - } else { - val half = (1 << log2Up(length))/2 - Cat(doit(in(half-1,0), half), doit(in(length-1,half), length-half)) - } - } - def apply(in: UInt): UInt = doit(in, in.getWidth) -} diff --git a/src/main/scala/chisel/util/Cat.scala b/src/main/scala/chisel/util/Cat.scala deleted file mode 100644 index b47da706..00000000 --- a/src/main/scala/chisel/util/Cat.scala +++ /dev/null @@ -1,21 +0,0 @@ -// See LICENSE for license details. - -package chisel.util - -import chisel._ -import chisel.core.SeqUtils - -object Cat { - /** Combine data elements together - * @param a Data to combine with - * @param r any number of other Data elements to be combined in order - * @return A UInt which is all of the bits combined together - */ - def apply[T <: Bits](a: T, r: T*): UInt = apply(a :: r.toList) - - /** Combine data elements together - * @param r any number of other Data elements to be combined in order - * @return A UInt which is all of the bits combined together - */ - def apply[T <: Bits](r: Seq[T]): UInt = SeqUtils.asUInt(r.reverse) -} diff --git a/src/main/scala/chisel/util/CircuitMath.scala b/src/main/scala/chisel/util/CircuitMath.scala deleted file mode 100644 index c3b94fdb..00000000 --- a/src/main/scala/chisel/util/CircuitMath.scala +++ /dev/null @@ -1,28 +0,0 @@ -// See LICENSE for license details. - -/** Circuit-land math operations. - */ - -package chisel.util - -import chisel._ - -/** Compute Log2 with truncation of a UInt in hardware using a Mux Tree - * An alternative interpretation is it computes the minimum number of bits needed to represent x - * @example - * {{{ data_out := Log2(data_in) }}} - * @note Truncation is used so Log2(UInt(12412)) = 13*/ -object Log2 { - /** Compute the Log2 on the least significant n bits of x */ - def apply(x: Bits, width: Int): UInt = { - if (width < 2) { - UInt(0) - } else if (width == 2) { - x(1) - } else { - Mux(x(width-1), UInt(width-1), apply(x, width-1)) - } - } - - def apply(x: Bits): UInt = apply(x, x.getWidth) -} diff --git a/src/main/scala/chisel/util/Conditional.scala b/src/main/scala/chisel/util/Conditional.scala deleted file mode 100644 index 01c12799..00000000 --- a/src/main/scala/chisel/util/Conditional.scala +++ /dev/null @@ -1,73 +0,0 @@ -// See LICENSE for license details. - -/** Conditional blocks. - */ - -package chisel.util - -import scala.language.reflectiveCalls -import scala.language.experimental.macros -import scala.reflect.runtime.universe._ -import scala.reflect.macros.blackbox._ - -import chisel._ - -/** This is identical to [[Chisel.when when]] with the condition inverted */ -object unless { // scalastyle:ignore object.name - def apply(c: Bool)(block: => Unit) { - when (!c) { block } - } -} - -class SwitchContext[T <: Bits](cond: T) { - def is(v: Iterable[T])(block: => Unit) { - if (!v.isEmpty) when (v.map(_.asUInt === cond.asUInt).reduce(_||_)) { block } - } - def is(v: T)(block: => Unit) { is(Seq(v))(block) } - def is(v: T, vr: T*)(block: => Unit) { is(v :: vr.toList)(block) } -} - -/** An object for separate cases in [[Chisel.switch switch]] - * It is equivalent to a [[Chisel.when$ when]] block comparing to the condition - * Use outside of a switch statement is illegal */ -object is { // scalastyle:ignore object.name - // Begin deprecation of non-type-parameterized is statements. - def apply(v: Iterable[Bits])(block: => Unit) { - require(false, "The 'is' keyword may not be used outside of a switch.") - } - - def apply(v: Bits)(block: => Unit) { - require(false, "The 'is' keyword may not be used outside of a switch.") - } - - def apply(v: Bits, vr: Bits*)(block: => Unit) { - require(false, "The 'is' keyword may not be used outside of a switch.") - } -} - -/** Conditional logic to form a switch block - * @example - * {{{ ... // default values here - * switch ( myState ) { - * is( state1 ) { - * ... // some logic here - * } - * is( state2 ) { - * ... // some logic here - * } - * } }}}*/ -object switch { // scalastyle:ignore object.name - def apply[T <: Bits](cond: T)(x: => Unit): Unit = macro impl - def impl(c: Context)(cond: c.Tree)(x: c.Tree): c.Tree = { import c.universe._ - val sc = c.universe.internal.reificationSupport.freshTermName("sc") - def extractIsStatement(tree: Tree): List[c.universe.Tree] = tree match { - // TODO: remove when Chisel compatibility package is removed - case q"Chisel.`package`.is.apply( ..$params )( ..$body )" => List(q"$sc.is( ..$params )( ..$body )") - case q"chisel.util.is.apply( ..$params )( ..$body )" => List(q"$sc.is( ..$params )( ..$body )") - case b => throw new Exception(s"Cannot include blocks that do not begin with is() in switch.") - } - val q"..$body" = x - val ises = body.flatMap(extractIsStatement(_)) - q"""{ val $sc = new SwitchContext($cond); ..$ises }""" - } -} diff --git a/src/main/scala/chisel/util/Counter.scala b/src/main/scala/chisel/util/Counter.scala deleted file mode 100644 index 1c0b0203..00000000 --- a/src/main/scala/chisel/util/Counter.scala +++ /dev/null @@ -1,46 +0,0 @@ -// See LICENSE for license details. - -package chisel.util - -import chisel._ - -/** A counter module - * @param n number of counts before the counter resets (or one more than the - * maximum output value of the counter), need not be a power of two - */ -class Counter(val n: Int) { - require(n >= 0) - val value = if (n > 1) Reg(init=UInt(0, log2Up(n))) else UInt(0) - /** Increment the counter, returning whether the counter currently is at the - * maximum and will wrap. The incremented value is registered and will be - * visible on the next cycle. - */ - def inc(): Bool = { - if (n > 1) { - val wrap = value === UInt(n-1) - value := value + UInt(1) - if (!isPow2(n)) { - when (wrap) { value := UInt(0) } - } - wrap - } else { - Bool(true) - } - } -} - -/** Counter Object - * Example Usage: - * {{{ val countOn = Bool(true) // increment counter every clock cycle - * val myCounter = Counter(countOn, n) - * when ( myCounter.value === UInt(3) ) { ... } }}}*/ -object Counter -{ - def apply(n: Int): Counter = new Counter(n) - def apply(cond: Bool, n: Int): (UInt, Bool) = { - val c = new Counter(n) - var wrap: Bool = null - when (cond) { wrap = c.inc() } - (c.value, cond && wrap) - } -} diff --git a/src/main/scala/chisel/util/Decoupled.scala b/src/main/scala/chisel/util/Decoupled.scala deleted file mode 100644 index 89b0e39d..00000000 --- a/src/main/scala/chisel/util/Decoupled.scala +++ /dev/null @@ -1,185 +0,0 @@ -// See LICENSE for license details. - -/** Wrappers for ready-valid (Decoupled) interfaces and associated circuit generators using them. - */ - -package chisel.util - -import chisel._ - -/** An I/O Bundle with simple handshaking using valid and ready signals for data 'bits'*/ -class DecoupledIO[+T <: Data](gen: T) extends Bundle -{ - val ready = Bool(INPUT) - val valid = Bool(OUTPUT) - val bits = gen.cloneType.asOutput - def fire(dummy: Int = 0): Bool = ready && valid - override def cloneType: this.type = new DecoupledIO(gen).asInstanceOf[this.type] -} - -/** Adds a ready-valid handshaking protocol to any interface. - * The standard used is that the consumer uses the flipped interface. - */ -object Decoupled { - def apply[T <: Data](gen: T): DecoupledIO[T] = new DecoupledIO(gen) -} - -/** An I/O bundle for enqueuing data with valid/ready handshaking - * Initialization must be handled, if necessary, by the parent circuit - */ -class EnqIO[T <: Data](gen: T) extends DecoupledIO(gen) -{ - /** push dat onto the output bits of this interface to let the consumer know it has happened. - * @param dat the values to assign to bits. - * @return dat. - */ - def enq(dat: T): T = { valid := Bool(true); bits := dat; dat } - - /** Initialize this Bundle. Valid is set to false, and all bits are set to zero. - * NOTE: This method of initialization is still being discussed and could change in the - * future. - */ - def init(): Unit = { - valid := Bool(false) - for (io <- bits.flatten) - io := UInt(0) - } - override def cloneType: this.type = { new EnqIO(gen).asInstanceOf[this.type]; } -} - -/** An I/O bundle for dequeuing data with valid/ready handshaking. - * Initialization must be handled, if necessary, by the parent circuit - */ -class DeqIO[T <: Data](gen: T) extends DecoupledIO(gen) with Flipped -{ - /** Assert ready on this port and return the associated data bits. - * This is typically used when valid has been asserted by the producer side. - * @param b ignored - * @return the data for this device, - */ - def deq(b: Boolean = false): T = { ready := Bool(true); bits } - - /** Initialize this Bundle. - * NOTE: This method of initialization is still being discussed and could change in the - * future. - */ - def init(): Unit = { - ready := Bool(false) - } - override def cloneType: this.type = { new DeqIO(gen).asInstanceOf[this.type]; } -} - -/** An I/O bundle for dequeuing data with valid/ready handshaking */ -class DecoupledIOC[+T <: Data](gen: T) extends Bundle -{ - val ready = Bool(INPUT) - val valid = Bool(OUTPUT) - val bits = gen.cloneType.asOutput -} - -/** An I/O Bundle for Queues - * @param gen The type of data to queue - * @param entries The max number of entries in the queue */ -class QueueIO[T <: Data](gen: T, entries: Int) extends Bundle -{ - /** I/O to enqueue data, is [[Chisel.DecoupledIO]] flipped */ - val enq = Decoupled(gen.cloneType).flip() - /** I/O to enqueue data, is [[Chisel.DecoupledIO]]*/ - val deq = Decoupled(gen.cloneType) - /** The current amount of data in the queue */ - val count = UInt(OUTPUT, log2Up(entries + 1)) -} - -/** A hardware module implementing a Queue - * @param gen The type of data to queue - * @param entries The max number of entries in the queue - * @param pipe True if a single entry queue can run at full throughput (like a pipeline). The ''ready'' signals are - * combinationally coupled. - * @param flow True if the inputs can be consumed on the same cycle (the inputs "flow" through the queue immediately). - * The ''valid'' signals are coupled. - * - * Example usage: - * {{{ val q = new Queue(UInt(), 16) - * q.io.enq <> producer.io.out - * consumer.io.in <> q.io.deq }}} - */ -class Queue[T <: Data](gen: T, val entries: Int, - pipe: Boolean = false, - flow: Boolean = false, - override_reset: Option[Bool] = None) -extends Module(override_reset=override_reset) { - def this(gen: T, entries: Int, pipe: Boolean, flow: Boolean, _reset: Bool) = - this(gen, entries, pipe, flow, Some(_reset)) - - val io = new QueueIO(gen, entries) - - val ram = Mem(entries, gen) - val enq_ptr = Counter(entries) - val deq_ptr = Counter(entries) - val maybe_full = Reg(init=Bool(false)) - - val ptr_match = enq_ptr.value === deq_ptr.value - val empty = ptr_match && !maybe_full - val full = ptr_match && maybe_full - val do_enq = Wire(init=io.enq.fire()) - val do_deq = Wire(init=io.deq.fire()) - - when (do_enq) { - ram(enq_ptr.value) := io.enq.bits - enq_ptr.inc() - } - when (do_deq) { - deq_ptr.inc() - } - when (do_enq != do_deq) { - maybe_full := do_enq - } - - io.deq.valid := !empty - io.enq.ready := !full - io.deq.bits := ram(deq_ptr.value) - - if (flow) { - when (io.enq.valid) { io.deq.valid := Bool(true) } - when (empty) { - io.deq.bits := io.enq.bits - do_deq := Bool(false) - when (io.deq.ready) { do_enq := Bool(false) } - } - } - - if (pipe) { - when (io.deq.ready) { io.enq.ready := Bool(true) } - } - - val ptr_diff = enq_ptr.value - deq_ptr.value - if (isPow2(entries)) { - io.count := Cat(maybe_full && ptr_match, ptr_diff) - } else { - io.count := Mux(ptr_match, - Mux(maybe_full, - UInt(entries), UInt(0)), - Mux(deq_ptr.value > enq_ptr.value, - UInt(entries) + ptr_diff, ptr_diff)) - } -} - -/** Generic hardware queue. Required parameter entries controls - the depth of the queues. The width of the queue is determined - from the inputs. - - Example usage: - {{{ val q = Queue(Decoupled(UInt()), 16) - q.io.enq <> producer.io.out - consumer.io.in <> q.io.deq }}} - */ -object Queue -{ - def apply[T <: Data](enq: DecoupledIO[T], entries: Int = 2, pipe: Boolean = false): DecoupledIO[T] = { - val q = Module(new Queue(enq.bits.cloneType, entries, pipe)) - q.io.enq.valid := enq.valid // not using <> so that override is allowed - q.io.enq.bits := enq.bits - enq.ready := q.io.enq.ready - TransitName(q.io.deq, q) - } -} diff --git a/src/main/scala/chisel/util/Enum.scala b/src/main/scala/chisel/util/Enum.scala deleted file mode 100644 index 8babcd23..00000000 --- a/src/main/scala/chisel/util/Enum.scala +++ /dev/null @@ -1,23 +0,0 @@ -// See LICENSE for license details. - -/** Enum generators, allowing circuit constants to have more meaningful names. - */ - -package chisel.util - -import chisel._ - -object Enum { - /** Returns a sequence of Bits subtypes with values from 0 until n. Helper method. */ - private def createValues[T <: Bits](nodeType: T, n: Int): Seq[T] = - (0 until n).map(x => nodeType.fromInt(x, log2Up(n))) - - /** create n enum values of given type */ - def apply[T <: Bits](nodeType: T, n: Int): List[T] = createValues(nodeType, n).toList - - /** create enum values of given type and names */ - def apply[T <: Bits](nodeType: T, l: Symbol *): Map[Symbol, T] = (l zip createValues(nodeType, l.length)).toMap - - /** create enum values of given type and names */ - def apply[T <: Bits](nodeType: T, l: List[Symbol]): Map[Symbol, T] = (l zip createValues(nodeType, l.length)).toMap -} diff --git a/src/main/scala/chisel/util/ImplicitConversions.scala b/src/main/scala/chisel/util/ImplicitConversions.scala deleted file mode 100644 index 846c0cbd..00000000 --- a/src/main/scala/chisel/util/ImplicitConversions.scala +++ /dev/null @@ -1,10 +0,0 @@ -// See LICENSE for license details. - -package chisel.util - -import chisel._ - -object ImplicitConversions { - implicit def intToUInt(x: Int): UInt = UInt(x) - implicit def booleanToBool(x: Boolean): Bool = Bool(x) -} diff --git a/src/main/scala/chisel/util/LFSR.scala b/src/main/scala/chisel/util/LFSR.scala deleted file mode 100644 index f70630bf..00000000 --- a/src/main/scala/chisel/util/LFSR.scala +++ /dev/null @@ -1,24 +0,0 @@ -// See LICENSE for license details. - -/** LFSRs in all shapes and sizes. - */ - -package chisel.util - -import chisel._ - -// scalastyle:off magic.number -/** linear feedback shift register - */ -object LFSR16 -{ - def apply(increment: Bool = Bool(true)): UInt = - { - val width = 16 - val lfsr = Reg(init=UInt(1, width)) - when (increment) { lfsr := Cat(lfsr(0)^lfsr(2)^lfsr(3)^lfsr(5), lfsr(width-1,1)) } - lfsr - } -} -// scalastyle:on magic.number - diff --git a/src/main/scala/chisel/util/Lookup.scala b/src/main/scala/chisel/util/Lookup.scala deleted file mode 100644 index d32d9aec..00000000 --- a/src/main/scala/chisel/util/Lookup.scala +++ /dev/null @@ -1,19 +0,0 @@ -// See LICENSE for license details. - -package chisel.util - -import chisel._ - -object ListLookup { - def apply[T <: Data](addr: UInt, default: List[T], mapping: Array[(BitPat, List[T])]): List[T] = { - val map = mapping.map(m => (m._1 === addr, m._2)) - default.zipWithIndex map { case (d, i) => - map.foldRight(d)((m, n) => Mux(m._1, m._2(i), n)) - } - } -} - -object Lookup { - def apply[T <: Bits](addr: UInt, default: T, mapping: Seq[(BitPat, T)]): T = - ListLookup(addr, List(default), mapping.map(m => (m._1, List(m._2))).toArray).head -} diff --git a/src/main/scala/chisel/util/Math.scala b/src/main/scala/chisel/util/Math.scala deleted file mode 100644 index 69464d15..00000000 --- a/src/main/scala/chisel/util/Math.scala +++ /dev/null @@ -1,44 +0,0 @@ -// See LICENSE for license details. - -/** Scala-land math helper functions, like logs. - */ - -package chisel.util - -import chisel._ - -/** Compute the log2 rounded up with min value of 1 */ -object log2Up { - def apply(in: BigInt): Int = { - require(in >= 0) - 1 max (in-1).bitLength - } - def apply(in: Int): Int = apply(BigInt(in)) -} - -/** Compute the log2 rounded up */ -object log2Ceil { - def apply(in: BigInt): Int = { - require(in > 0) - (in-1).bitLength - } - def apply(in: Int): Int = apply(BigInt(in)) -} - -/** Compute the log2 rounded down with min value of 1 */ -object log2Down { - def apply(in: BigInt): Int = log2Up(in) - (if (isPow2(in)) 0 else 1) - def apply(in: Int): Int = apply(BigInt(in)) -} - -/** Compute the log2 rounded down */ -object log2Floor { - def apply(in: BigInt): Int = log2Ceil(in) - (if (isPow2(in)) 0 else 1) - def apply(in: Int): Int = apply(BigInt(in)) -} - -/** Check if an Integer is a power of 2 */ -object isPow2 { - def apply(in: BigInt): Boolean = in > 0 && ((in & (in-1)) == 0) - def apply(in: Int): Boolean = apply(BigInt(in)) -} diff --git a/src/main/scala/chisel/util/Mux.scala b/src/main/scala/chisel/util/Mux.scala deleted file mode 100644 index 6f074a7e..00000000 --- a/src/main/scala/chisel/util/Mux.scala +++ /dev/null @@ -1,64 +0,0 @@ -// See LICENSE for license details. - -/** Mux circuit generators. - */ - -package chisel.util - -import chisel._ -import chisel.core.SeqUtils - -/** Builds a Mux tree out of the input signal vector using a one hot encoded - select signal. Returns the output of the Mux tree. - */ -object Mux1H -{ - def apply[T <: Data](sel: Seq[Bool], in: Seq[T]): T = - apply(sel zip in) - def apply[T <: Data](in: Iterable[(Bool, T)]): T = SeqUtils.oneHotMux(in) - def apply[T <: Data](sel: UInt, in: Seq[T]): T = - apply((0 until in.size).map(sel(_)), in) - def apply(sel: UInt, in: UInt): Bool = (sel & in).orR -} - -/** Builds a Mux tree under the assumption that multiple select signals - can be enabled. Priority is given to the first select signal. - - Returns the output of the Mux tree. - */ -object PriorityMux -{ - def apply[T <: Data](in: Seq[(Bool, T)]): T = SeqUtils.priorityMux(in) - def apply[T <: Data](sel: Seq[Bool], in: Seq[T]): T = apply(sel zip in) - def apply[T <: Data](sel: Bits, in: Seq[T]): T = apply((0 until in.size).map(sel(_)), in) -} - -/** MuxLookup creates a cascade of n Muxs to search for a key value */ -object MuxLookup { - /** @param key a key to search for - * @param default a default value if nothing is found - * @param mapping a sequence to search of keys and values - * @return the value found or the default if not - */ - def apply[S <: UInt, T <: Bits] (key: S, default: T, mapping: Seq[(S, T)]): T = { - var res = default - for ((k, v) <- mapping.reverse) - res = Mux(k === key, v, res) - res - } - -} - -/** MuxCase returns the first value that is enabled in a map of values */ -object MuxCase { - /** @param default the default value if none are enabled - * @param mapping a set of data values with associated enables - * @return the first value in mapping that is enabled */ - def apply[T <: Bits] (default: T, mapping: Seq[(Bool, T)]): T = { - var res = default - for ((t, v) <- mapping.reverse){ - res = Mux(t, v, res) - } - res - } -} diff --git a/src/main/scala/chisel/util/OneHot.scala b/src/main/scala/chisel/util/OneHot.scala deleted file mode 100644 index ef21c65d..00000000 --- a/src/main/scala/chisel/util/OneHot.scala +++ /dev/null @@ -1,64 +0,0 @@ -// See LICENSE for license details. - -/** Circuit generators for working with one-hot representations. - */ - -package chisel.util - -import chisel._ - -/** Converts from One Hot Encoding to a UInt indicating which bit is active - * This is the inverse of [[Chisel.UIntToOH UIntToOH]]*/ -object OHToUInt { - def apply(in: Seq[Bool]): UInt = apply(Vec(in)) - def apply(in: Vec[Bool]): UInt = apply(in.toBits, in.size) - def apply(in: Bits): UInt = apply(in, in.getWidth) - - def apply(in: Bits, width: Int): UInt = { - if (width <= 2) { - Log2(in, width) - } else { - val mid = 1 << (log2Up(width)-1) - val hi = in(width-1, mid) - val lo = in(mid-1, 0) - Cat(hi.orR, apply(hi | lo, mid)) - } - } -} - -/** @return the bit position of the trailing 1 in the input vector - * with the assumption that multiple bits of the input bit vector can be set - * @example {{{ data_out := PriorityEncoder(data_in) }}} - */ -object PriorityEncoder { - def apply(in: Seq[Bool]): UInt = PriorityMux(in, (0 until in.size).map(UInt(_))) - def apply(in: Bits): UInt = apply(in.toBools) -} - -/** Returns the one hot encoding of the input UInt. - */ -object UIntToOH -{ - def apply(in: UInt, width: Int = -1): UInt = - if (width == -1) { - UInt(1) << in - } else { - (UInt(1) << in(log2Up(width)-1,0))(width-1,0) - } -} - -/** Returns a bit vector in which only the least-significant 1 bit in - the input vector, if any, is set. - */ -object PriorityEncoderOH -{ - private def encode(in: Seq[Bool]): UInt = { - val outs = Seq.tabulate(in.size)(i => UInt(BigInt(1) << i, in.size)) - PriorityMux(in :+ Bool(true), outs :+ UInt(0, in.size)) - } - def apply(in: Seq[Bool]): Seq[Bool] = { - val enc = encode(in) - Seq.tabulate(in.size)(enc(_)) - } - def apply(in: Bits): UInt = encode((0 until in.getWidth).map(i => in(i))) -} diff --git a/src/main/scala/chisel/util/Reg.scala b/src/main/scala/chisel/util/Reg.scala deleted file mode 100644 index 1b40646d..00000000 --- a/src/main/scala/chisel/util/Reg.scala +++ /dev/null @@ -1,57 +0,0 @@ -// See LICENSE for license details. - -/** Variations and helpers for registers. - */ - -package chisel.util - -import chisel._ - -object RegNext { - - def apply[T <: Data](next: T): T = Reg[T](null.asInstanceOf[T], next, null.asInstanceOf[T]) - - def apply[T <: Data](next: T, init: T): T = Reg[T](null.asInstanceOf[T], next, init) - -} - -object RegInit { - - def apply[T <: Data](init: T): T = Reg[T](null.asInstanceOf[T], null.asInstanceOf[T], init) - -} - -/** A register with an Enable signal */ -object RegEnable -{ - def apply[T <: Data](updateData: T, enable: Bool): T = { - val r = Reg(updateData) - when (enable) { r := updateData } - r - } - def apply[T <: Data](updateData: T, resetData: T, enable: Bool): T = { - val r = RegInit(resetData) - when (enable) { r := updateData } - r - } -} - -/** Returns the n-cycle delayed version of the input signal. - */ -object ShiftRegister -{ - /** @param in input to delay - * @param n number of cycles to delay - * @param en enable the shift */ - def apply[T <: Data](in: T, n: Int, en: Bool = Bool(true)): T = - { - // The order of tests reflects the expected use cases. - if (n == 1) { - RegEnable(in, en) - } else if (n != 0) { - RegNext(apply(in, n-1, en)) - } else { - in - } - } -} diff --git a/src/main/scala/chisel/util/TransitName.scala b/src/main/scala/chisel/util/TransitName.scala deleted file mode 100644 index 04e1995b..00000000 --- a/src/main/scala/chisel/util/TransitName.scala +++ /dev/null @@ -1,22 +0,0 @@ -package chisel.util - -import chisel._ -import internal.HasId - -object TransitName { - // The purpose of this is to allow a library to 'move' a name call to a more - // appropriate place. - // For example, a library factory function may create a module and return - // the io. The only user-exposed field is that given IO, which can't use - // any name supplied by the user. This can add a hook so that the supplied - // name then names the Module. - // See Queue companion object for working example - def apply[T<:HasId](from: T, to: HasId): T = { - from.addPostnameHook((given_name: String) => {to.suggestName(given_name)}) - from - } - def withSuffix[T<:HasId](suffix: String)(from: T, to: HasId): T = { - from.addPostnameHook((given_name: String) => {to.suggestName(given_name+suffix)}) - from - } -} diff --git a/src/main/scala/chisel/util/Valid.scala b/src/main/scala/chisel/util/Valid.scala deleted file mode 100644 index 56ac9abb..00000000 --- a/src/main/scala/chisel/util/Valid.scala +++ /dev/null @@ -1,61 +0,0 @@ -// See LICENSE for license details. - -/** Wrappers for valid interfaces and associated circuit generators using them. - */ - -package chisel.util - -import chisel._ - -/** An I/O Bundle containing data and a signal determining if it is valid */ -class ValidIO[+T <: Data](gen2: T) extends Bundle -{ - val valid = Bool(OUTPUT) - val bits = gen2.cloneType.asOutput - def fire(dummy: Int = 0): Bool = valid - override def cloneType: this.type = new ValidIO(gen2).asInstanceOf[this.type] -} - -/** Adds a valid protocol to any interface. The standard used is - that the consumer uses the flipped interface. -*/ -object Valid { - def apply[T <: Data](gen: T): ValidIO[T] = new ValidIO(gen) -} - -/** A hardware module that delays data coming down the pipeline - by the number of cycles set by the latency parameter. Functionality - is similar to ShiftRegister but this exposes a Pipe interface. - - Example usage: - val pipe = new Pipe(UInt()) - pipe.io.enq <> produce.io.out - consumer.io.in <> pipe.io.deq - */ -object Pipe -{ - def apply[T <: Data](enqValid: Bool, enqBits: T, latency: Int): ValidIO[T] = { - if (latency == 0) { - val out = Wire(Valid(enqBits)) - out.valid <> enqValid - out.bits <> enqBits - out - } else { - val v = Reg(Bool(), next=enqValid, init=Bool(false)) - val b = RegEnable(enqBits, enqValid) - apply(v, b, latency-1) - } - } - def apply[T <: Data](enqValid: Bool, enqBits: T): ValidIO[T] = apply(enqValid, enqBits, 1) - def apply[T <: Data](enq: ValidIO[T], latency: Int = 1): ValidIO[T] = apply(enq.valid, enq.bits, latency) -} - -class Pipe[T <: Data](gen: T, latency: Int = 1) extends Module -{ - val io = new Bundle { - val enq = Valid(gen).flip - val deq = Valid(gen) - } - - io.deq <> Pipe(io.enq, latency) -} diff --git a/src/main/scala/chisel3/Driver.scala b/src/main/scala/chisel3/Driver.scala new file mode 100644 index 00000000..ba2b1389 --- /dev/null +++ b/src/main/scala/chisel3/Driver.scala @@ -0,0 +1,132 @@ +// See LICENSE for license details. + +package chisel + +import scala.sys.process._ +import java.io._ + +import internal._ +import internal.firrtl._ + +trait BackendCompilationUtilities { + /** Create a temporary directory with the prefix name. Exists here because it doesn't in Java 6. + */ + def createTempDirectory(prefix: String): File = { + val temp = File.createTempFile(prefix, "") + if (!temp.delete()) { + throw new IOException(s"Unable to delete temp file '$temp'") + } + if (!temp.mkdir()) { + throw new IOException(s"Unable to create temp directory '$temp'") + } + temp + } + + def makeHarness(template: String => String, post: String)(f: File): File = { + val prefix = f.toString.split("/").last + val vf = new File(f.toString + post) + val w = new FileWriter(vf) + w.write(template(prefix)) + w.close() + vf + } + + def firrtlToVerilog(prefix: String, dir: File): ProcessBuilder = { + Process( + Seq("firrtl", + "-i", s"$prefix.fir", + "-o", s"$prefix.v", + "-X", "verilog"), + dir) + } + + /** Generates a Verilator invocation to convert Verilog sources to C++ + * simulation sources. + * + * The Verilator prefix will be V$dutFile, and running this will generate + * C++ sources and headers as well as a makefile to compile them. + * + * @param dutFile name of the DUT .v without the .v extension + * @param name of the top-level module in the design + * @param dir output directory + * @param vSources list of additional Verilog sources to compile + * @param cppHarness C++ testharness to compile/link against + */ + def verilogToCpp( + dutFile: String, + topModule: String, + dir: File, + vSources: Seq[File], + cppHarness: File + ): ProcessBuilder = { + val command = Seq("verilator", + "--cc", s"$dutFile.v") ++ + vSources.map(file => Seq("-v", file.toString)).flatten ++ + Seq("--assert", + "-Wno-fatal", + "-Wno-WIDTH", + "-Wno-STMTDLY", + "--trace", + "-O2", + "--top-module", topModule, + "+define+TOP_TYPE=V" + dutFile, + s"+define+PRINTF_COND=!$topModule.reset", + "-CFLAGS", + s"""-Wno-undefined-bool-conversion -O2 -DTOP_TYPE=V$dutFile -include V$dutFile.h""", + "-Mdir", dir.toString, + "--exe", cppHarness.toString) + System.out.println(s"${command.mkString(" ")}") // scalastyle:ignore regex + command + } + + def cppToExe(prefix: String, dir: File): ProcessBuilder = + Seq("make", "-C", dir.toString, "-j", "-f", s"V${prefix}.mk", s"V${prefix}") + + def executeExpectingFailure( + prefix: String, + dir: File, + assertionMsg: String = "Assertion failed"): Boolean = { + var triggered = false + val e = Process(s"./V${prefix}", dir) ! + ProcessLogger(line => { + triggered = triggered || line.contains(assertionMsg) + System.out.println(line) // scalastyle:ignore regex + }) + triggered + } + + def executeExpectingSuccess(prefix: String, dir: File): Boolean = { + !executeExpectingFailure(prefix, dir) + } +} + +object Driver extends BackendCompilationUtilities { + + /** Elaborates the Module specified in the gen function into a Circuit + * + * @param gen a function that creates a Module hierarchy + * @return the resulting Chisel IR in the form of a Circuit (TODO: Should be FIRRTL IR) + */ + def elaborate[T <: Module](gen: () => T): Circuit = Builder.build(Module(gen())) + + def emit[T <: Module](gen: () => T): String = Emitter.emit(elaborate(gen)) + + def dumpFirrtl(ir: Circuit, optName: Option[File]): File = { + val f = optName.getOrElse(new File(ir.name + ".fir")) + val w = new FileWriter(f) + w.write(Emitter.emit(ir)) + w.close() + f + } + + private var target_dir: Option[String] = None + def parseArgs(args: Array[String]): Unit = { + for (i <- 0 until args.size) { + if (args(i) == "--targetDir") { + target_dir = Some(args(i + 1)) + } + } + } + + def targetDir(): String = { target_dir getOrElse new File(".").getCanonicalPath } +} diff --git a/src/main/scala/chisel3/compatibility.scala b/src/main/scala/chisel3/compatibility.scala new file mode 100644 index 00000000..56088562 --- /dev/null +++ b/src/main/scala/chisel3/compatibility.scala @@ -0,0 +1,150 @@ +// See LICENSE for license details. + +// Allows legacy users to continue using Chisel (capital C) package name while +// moving to the more standard package naming convention chisel (lowercase c). + +package object Chisel { + type Direction = chisel.core.Direction + val INPUT = chisel.core.INPUT + val OUTPUT = chisel.core.OUTPUT + val NO_DIR = chisel.core.NO_DIR + + type Flipped = chisel.core.Flipped + type Data = chisel.core.Data + val Wire = chisel.core.Wire + val Clock = chisel.core.Clock + type Clock = chisel.core.Clock + + type Aggregate = chisel.core.Aggregate + val Vec = chisel.core.Vec + type Vec[T <: Data] = chisel.core.Vec[T] + type VecLike[T <: Data] = chisel.core.VecLike[T] + type Bundle = chisel.core.Bundle + + val assert = chisel.core.assert + + type Element = chisel.core.Element + type Bits = chisel.core.Bits + val Bits = chisel.core.Bits + type Num[T <: Data] = chisel.core.Num[T] + type UInt = chisel.core.UInt + val UInt = chisel.core.UInt + type SInt = chisel.core.SInt + val SInt = chisel.core.SInt + type Bool = chisel.core.Bool + val Bool = chisel.core.Bool + val Mux = chisel.core.Mux + + type BlackBox = chisel.core.BlackBox + + val Mem = chisel.core.Mem + type MemBase[T <: Data] = chisel.core.MemBase[T] + type Mem[T <: Data] = chisel.core.Mem[T] + val SeqMem = chisel.core.SeqMem + type SeqMem[T <: Data] = chisel.core.SeqMem[T] + + val Module = chisel.core.Module + type Module = chisel.core.Module + + val printf = chisel.core.printf + + val Reg = chisel.core.Reg + + val when = chisel.core.when + type WhenContext = chisel.core.WhenContext + + + type BackendCompilationUtilities = chisel.BackendCompilationUtilities + val Driver = chisel.Driver + type FileSystemUtilities = chisel.compatibility.FileSystemUtilities + val ImplicitConversions = chisel.util.ImplicitConversions + val chiselMain = chisel.compatibility.chiselMain + val throwException = chisel.compatibility.throwException + val debug = chisel.compatibility.debug + + object testers { + type BasicTester = chisel.testers.BasicTester + val TesterDriver = chisel.testers.TesterDriver + } + + + val log2Up = chisel.util.log2Up + val log2Ceil = chisel.util.log2Ceil + val log2Down = chisel.util.log2Down + val log2Floor = chisel.util.log2Floor + val isPow2 = chisel.util.isPow2 + + val BitPat = chisel.util.BitPat + type BitPat = chisel.util.BitPat + + type ArbiterIO[T <: Data] = chisel.util.ArbiterIO[T] + type LockingArbiterLike[T <: Data] = chisel.util.LockingArbiterLike[T] + type LockingRRArbiter[T <: Data] = chisel.util.LockingRRArbiter[T] + type LockingArbiter[T <: Data] = chisel.util.LockingArbiter[T] + type RRArbiter[T <: Data] = chisel.util.RRArbiter[T] + type Arbiter[T <: Data] = chisel.util.Arbiter[T] + + val FillInterleaved = chisel.util.FillInterleaved + val PopCount = chisel.util.PopCount + val Fill = chisel.util.Fill + val Reverse = chisel.util.Reverse + + val Cat = chisel.util.Cat + + val Log2 = chisel.util.Log2 + + val unless = chisel.util.unless + type SwitchContext[T <: Bits] = chisel.util.SwitchContext[T] + val is = chisel.util.is + val switch = chisel.util.switch + + type Counter = chisel.util.Counter + val Counter = chisel.util.Counter + + type DecoupledIO[+T <: Data] = chisel.util.DecoupledIO[T] + val Decoupled = chisel.util.Decoupled + type EnqIO[T <: Data] = chisel.util.EnqIO[T] + type DeqIO[T <: Data] = chisel.util.DeqIO[T] + type DecoupledIOC[+T <: Data] = chisel.util.DecoupledIOC[T] + type QueueIO[T <: Data] = chisel.util.QueueIO[T] + type Queue[T <: Data] = chisel.util.Queue[T] + val Queue = chisel.util.Queue + + val Enum = chisel.util.Enum + + val LFSR16 = chisel.util.LFSR16 + + val ListLookup = chisel.util.ListLookup + val Lookup = chisel.util.Lookup + + val Mux1H = chisel.util.Mux1H + val PriorityMux = chisel.util.PriorityMux + val MuxLookup = chisel.util.MuxLookup + val MuxCase = chisel.util.MuxCase + + val OHToUInt = chisel.util.OHToUInt + val PriorityEncoder = chisel.util.PriorityEncoder + val UIntToOH = chisel.util.UIntToOH + val PriorityEncoderOH = chisel.util.PriorityEncoderOH + + val RegNext = chisel.util.RegNext + val RegInit = chisel.util.RegInit + val RegEnable = chisel.util.RegEnable + val ShiftRegister = chisel.util.ShiftRegister + + type ValidIO[+T <: Data] = chisel.util.ValidIO[T] + val Valid = chisel.util.Valid + val Pipe = chisel.util.Pipe + type Pipe[T <: Data] = chisel.util.Pipe[T] + + + import chisel.internal.firrtl.Width + implicit def fromBigIntToLiteral(x: BigInt): chisel.fromBigIntToLiteral = + new chisel.fromBigIntToLiteral(x) + implicit def fromIntToLiteral(x: Int): chisel.fromIntToLiteral= + new chisel.fromIntToLiteral(x) + implicit def fromStringToLiteral(x: String): chisel.fromStringToLiteral= + new chisel.fromStringToLiteral(x) + implicit def fromBooleanToLiteral(x: Boolean): chisel.fromBooleanToLiteral= + new chisel.fromBooleanToLiteral(x) +} diff --git a/src/main/scala/chisel3/compatibility/FileSystemUtilities.scala b/src/main/scala/chisel3/compatibility/FileSystemUtilities.scala new file mode 100644 index 00000000..d12e627d --- /dev/null +++ b/src/main/scala/chisel3/compatibility/FileSystemUtilities.scala @@ -0,0 +1,12 @@ +// See LICENSE for license details. + +package chisel.compatibility + +import chisel._ + +@deprecated("FileSystemUtilities doesn't exist in chisel3", "3.0.0") +trait FileSystemUtilities { + def createOutputFile(name: String): java.io.FileWriter = { + new java.io.FileWriter(Driver.targetDir + "/" + name) + } +} diff --git a/src/main/scala/chisel3/compatibility/Main.scala b/src/main/scala/chisel3/compatibility/Main.scala new file mode 100644 index 00000000..9072bfcf --- /dev/null +++ b/src/main/scala/chisel3/compatibility/Main.scala @@ -0,0 +1,19 @@ +// See LICENSE for license details. + +package chisel.compatibility + +import java.io.File + +import chisel._ + +@deprecated("chiselMain doesn't exist in Chisel3", "3.0") object chiselMain { + def apply[T <: Module](args: Array[String], gen: () => T): Unit = + Predef.assert(false, "No more chiselMain in Chisel3") + + def run[T <: Module] (args: Array[String], gen: () => T): Unit = { + val circuit = Driver.elaborate(gen) + Driver.parseArgs(args) + val output_file = new File(Driver.targetDir + "/" + circuit.name + ".fir") + Driver.dumpFirrtl(circuit, Option(output_file)) + } +} diff --git a/src/main/scala/chisel3/compatibility/debug.scala b/src/main/scala/chisel3/compatibility/debug.scala new file mode 100644 index 00000000..8850c76b --- /dev/null +++ b/src/main/scala/chisel3/compatibility/debug.scala @@ -0,0 +1,8 @@ +package chisel.compatibility + +import chisel.core._ + +@deprecated("debug doesn't do anything in Chisel3 as no pruning happens in the frontend", "chisel3") +object debug { // scalastyle:ignore object.name + def apply (arg: Data): Data = arg +} diff --git a/src/main/scala/chisel3/compatibility/throwException.scala b/src/main/scala/chisel3/compatibility/throwException.scala new file mode 100644 index 00000000..3b9fd06e --- /dev/null +++ b/src/main/scala/chisel3/compatibility/throwException.scala @@ -0,0 +1,14 @@ +// See LICENSE for license details. + +package chisel.compatibility + +import chisel._ + +@deprecated("throwException doesn't exist in Chisel3", "3.0.0") +@throws(classOf[Exception]) +object throwException { + def apply(s: String, t: Throwable = null) = { + val xcpt = new Exception(s, t) + throw xcpt + } +} diff --git a/src/main/scala/chisel3/internal/firrtl/Emitter.scala b/src/main/scala/chisel3/internal/firrtl/Emitter.scala new file mode 100644 index 00000000..e48eb226 --- /dev/null +++ b/src/main/scala/chisel3/internal/firrtl/Emitter.scala @@ -0,0 +1,112 @@ +// See LICENSE for license details. + +package chisel.internal.firrtl +import chisel._ +import chisel.internal.sourceinfo.{NoSourceInfo, SourceLine} + +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 = { + val firrtlLine = 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() + s"skip" + } + e.sourceInfo match { + case SourceLine(filename, line, col) => s"${firrtlLine} @[${filename} ${line}:${col}] " + case _: NoSourceInfo => firrtlLine + } + } + + // 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/src/main/scala/chisel3/package.scala b/src/main/scala/chisel3/package.scala new file mode 100644 index 00000000..f7ed6b13 --- /dev/null +++ b/src/main/scala/chisel3/package.scala @@ -0,0 +1,82 @@ +package object chisel { + import scala.language.experimental.macros + + import internal.firrtl.Width + import internal.sourceinfo.{SourceInfo, SourceInfoTransform} + import util.BitPat + + + type Direction = chisel.core.Direction + val INPUT = chisel.core.INPUT + val OUTPUT = chisel.core.OUTPUT + val NO_DIR = chisel.core.NO_DIR + type Flipped = chisel.core.Flipped + type Data = chisel.core.Data + val Wire = chisel.core.Wire + val Clock = chisel.core.Clock + type Clock = chisel.core.Clock + + type Aggregate = chisel.core.Aggregate + val Vec = chisel.core.Vec + type Vec[T <: Data] = chisel.core.Vec[T] + type VecLike[T <: Data] = chisel.core.VecLike[T] + type Bundle = chisel.core.Bundle + + val assert = chisel.core.assert + + type Element = chisel.core.Element + type Bits = chisel.core.Bits + val Bits = chisel.core.Bits + type Num[T <: Data] = chisel.core.Num[T] + type UInt = chisel.core.UInt + val UInt = chisel.core.UInt + type SInt = chisel.core.SInt + val SInt = chisel.core.SInt + type Bool = chisel.core.Bool + val Bool = chisel.core.Bool + val Mux = chisel.core.Mux + + type BlackBox = chisel.core.BlackBox + + val Mem = chisel.core.Mem + type MemBase[T <: Data] = chisel.core.MemBase[T] + type Mem[T <: Data] = chisel.core.Mem[T] + val SeqMem = chisel.core.SeqMem + type SeqMem[T <: Data] = chisel.core.SeqMem[T] + + val Module = chisel.core.Module + type Module = chisel.core.Module + + val printf = chisel.core.printf + + val Reg = chisel.core.Reg + + val when = chisel.core.when + type WhenContext = chisel.core.WhenContext + + + implicit class fromBigIntToLiteral(val x: BigInt) extends AnyVal { + def U: UInt = UInt(x, Width()) + def S: SInt = SInt(x, Width()) + } + implicit class fromIntToLiteral(val x: Int) extends AnyVal { + def U: UInt = UInt(BigInt(x), Width()) + def S: SInt = SInt(BigInt(x), Width()) + } + implicit class fromStringToLiteral(val x: String) extends AnyVal { + def U: UInt = UInt(x) + } + implicit class fromBooleanToLiteral(val x: Boolean) extends AnyVal { + def B: Bool = Bool(x) + } + + implicit class fromUIntToBitPatComparable(val x: UInt) extends AnyVal { + 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 === x + def do_!= (that: BitPat)(implicit sourceInfo: SourceInfo): Bool = that != x + def do_=/= (that: BitPat)(implicit sourceInfo: SourceInfo): Bool = that =/= x + } +} diff --git a/src/main/scala/chisel3/testers/BasicTester.scala b/src/main/scala/chisel3/testers/BasicTester.scala new file mode 100644 index 00000000..36ff7c52 --- /dev/null +++ b/src/main/scala/chisel3/testers/BasicTester.scala @@ -0,0 +1,38 @@ +// See LICENSE for license details. + +package chisel.testers +import chisel._ + +import scala.language.experimental.macros + +import internal._ +import internal.Builder.pushCommand +import internal.firrtl._ +import internal.sourceinfo.SourceInfo + +class BasicTester extends Module { + // The testbench has no IOs, rather it should communicate using printf, assert, and stop. + val io = new Bundle() + + def popCount(n: Long): Int = n.toBinaryString.count(_=='1') + + /** Ends the test reporting success. + * + * 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. + */ + def stop()(implicit sourceInfo: SourceInfo) { + // TODO: rewrite this using library-style SourceInfo passing. + when (!reset) { + pushCommand(Stop(sourceInfo, Node(clock), 0)) + } + } + + /** The finish method provides a hook that subclasses of BasicTester can use to + * alter a circuit after their constructor has been called. + * For example, a specialized tester subclassing BasicTester could override finish in order to + * add flow control logic for a decoupled io port of a device under test + */ + def finish(): Unit = {} +} diff --git a/src/main/scala/chisel3/testers/TesterDriver.scala b/src/main/scala/chisel3/testers/TesterDriver.scala new file mode 100644 index 00000000..5c0275e0 --- /dev/null +++ b/src/main/scala/chisel3/testers/TesterDriver.scala @@ -0,0 +1,69 @@ +// See LICENSE for license details. + +package chisel.testers + +import chisel._ +import scala.io.Source +import scala.sys.process._ +import java.io._ + +object TesterDriver extends BackendCompilationUtilities { + /** Copy the contents of a resource to a destination file. + */ + def copyResourceToFile(name: String, file: File) { + val in = getClass().getResourceAsStream(name) + if (in == null) { + throw new FileNotFoundException(s"Resource '$name'") + } + val out = new FileOutputStream(file) + Iterator.continually(in.read).takeWhile(-1 !=).foreach(out.write) + out.close() + } + + /** For use with modules that should successfully be elaborated by the + * frontend, and which can be turned into executables with assertions. */ + def execute(t: () => BasicTester, additionalVResources: Seq[String] = Seq()): Boolean = { + // Invoke the chisel compiler to get the circuit's IR + val circuit = Driver.elaborate(finishWrapper(t)) + + // Set up a bunch of file handlers based on a random temp filename, + // plus the quirks of Verilator's naming conventions + val target = circuit.name + + val path = createTempDirectory(target) + val fname = new File(path, target) + + // For now, dump the IR out to a file + Driver.dumpFirrtl(circuit, Some(new File(fname.toString + ".fir"))) + + // Copy CPP harness and other Verilog sources from resources into files + val cppHarness = new File(path, "top.cpp") + copyResourceToFile("/top.cpp", cppHarness) + val additionalVFiles = additionalVResources.map((name: String) => { + val mangledResourceName = name.replace("/", "_") + val out = new File(path, mangledResourceName) + copyResourceToFile(name, out) + out + }) + + // Use sys.Process to invoke a bunch of backend stuff, then run the resulting exe + if ((firrtlToVerilog(target, path) #&& + verilogToCpp(target, target, path, additionalVFiles, cppHarness) #&& + cppToExe(target, path)).! == 0) { + executeExpectingSuccess(target, path) + } else { + false + } + } + /** + * Calls the finish method of an BasicTester or a class that extends it. + * The finish method is a hook for code that augments the circuit built in the constructor. + */ + def finishWrapper(test: () => BasicTester): () => BasicTester = { + () => { + val tester = test() + tester.finish() + tester + } + } +} diff --git a/src/main/scala/chisel3/util/Arbiter.scala b/src/main/scala/chisel3/util/Arbiter.scala new file mode 100644 index 00000000..3723f2a9 --- /dev/null +++ b/src/main/scala/chisel3/util/Arbiter.scala @@ -0,0 +1,119 @@ +// See LICENSE for license details. + +/** Arbiters in all shapes and sizes. + */ + +package chisel.util + +import chisel._ + +/** An I/O bundle for the Arbiter */ +class ArbiterIO[T <: Data](gen: T, n: Int) extends Bundle { + val in = Vec(n, Decoupled(gen)).flip + val out = Decoupled(gen) + val chosen = UInt(OUTPUT, log2Up(n)) +} + +/** Arbiter Control determining which producer has access */ +private object ArbiterCtrl +{ + def apply(request: Seq[Bool]): Seq[Bool] = request.length match { + case 0 => Seq() + case 1 => Seq(Bool(true)) + case _ => Bool(true) +: request.tail.init.scanLeft(request.head)(_ || _).map(!_) + } +} + +abstract class LockingArbiterLike[T <: Data](gen: T, n: Int, count: Int, needsLock: Option[T => Bool]) extends Module { + def grant: Seq[Bool] + def choice: UInt + val io = new ArbiterIO(gen, n) + + io.chosen := choice + io.out.valid := io.in(io.chosen).valid + io.out.bits := io.in(io.chosen).bits + + if (count > 1) { + val lockCount = Counter(count) + val lockIdx = Reg(UInt()) + val locked = lockCount.value =/= UInt(0) + val wantsLock = needsLock.map(_(io.out.bits)).getOrElse(Bool(true)) + + when (io.out.fire() && wantsLock) { + lockIdx := io.chosen + lockCount.inc() + } + + when (locked) { io.chosen := lockIdx } + for ((in, (g, i)) <- io.in zip grant.zipWithIndex) + in.ready := Mux(locked, lockIdx === UInt(i), g) && io.out.ready + } else { + for ((in, g) <- io.in zip grant) + in.ready := g && io.out.ready + } +} + +class LockingRRArbiter[T <: Data](gen: T, n: Int, count: Int, needsLock: Option[T => Bool] = None) + extends LockingArbiterLike[T](gen, n, count, needsLock) { + lazy val lastGrant = RegEnable(io.chosen, io.out.fire()) + lazy val grantMask = (0 until n).map(UInt(_) > lastGrant) + lazy val validMask = io.in zip grantMask map { case (in, g) => in.valid && g } + + override def grant: Seq[Bool] = { + val ctrl = ArbiterCtrl((0 until n).map(i => validMask(i)) ++ io.in.map(_.valid)) + (0 until n).map(i => ctrl(i) && grantMask(i) || ctrl(i + n)) + } + + override lazy val choice = Wire(init=UInt(n-1)) + for (i <- n-2 to 0 by -1) + when (io.in(i).valid) { choice := UInt(i) } + for (i <- n-1 to 1 by -1) + when (validMask(i)) { choice := UInt(i) } +} + +class LockingArbiter[T <: Data](gen: T, n: Int, count: Int, needsLock: Option[T => Bool] = None) + extends LockingArbiterLike[T](gen, n, count, needsLock) { + def grant: Seq[Bool] = ArbiterCtrl(io.in.map(_.valid)) + + override lazy val choice = Wire(init=UInt(n-1)) + for (i <- n-2 to 0 by -1) + when (io.in(i).valid) { choice := UInt(i) } +} + +/** Hardware module that is used to sequence n producers into 1 consumer. + Producers are chosen in round robin order. + + Example usage: + val arb = new RRArbiter(2, UInt()) + arb.io.in(0) <> producer0.io.out + arb.io.in(1) <> producer1.io.out + consumer.io.in <> arb.io.out + */ +class RRArbiter[T <: Data](gen:T, n: Int) extends LockingRRArbiter[T](gen, n, 1) + +/** Hardware module that is used to sequence n producers into 1 consumer. + Priority is given to lower producer + + Example usage: + val arb = Module(new Arbiter(2, UInt())) + arb.io.in(0) <> producer0.io.out + arb.io.in(1) <> producer1.io.out + consumer.io.in <> arb.io.out + */ +class Arbiter[T <: Data](gen: T, n: Int) extends Module { + val io = new ArbiterIO(gen, n) + + io.chosen := UInt(n-1) + io.out.bits := io.in(n-1).bits + for (i <- n-2 to 0 by -1) { + when (io.in(i).valid) { + io.chosen := UInt(i) + io.out.bits := io.in(i).bits + } + } + + val grant = ArbiterCtrl(io.in.map(_.valid)) + for ((in, g) <- io.in zip grant) + in.ready := g && io.out.ready + io.out.valid := !grant.last || io.in.last.valid +} diff --git a/src/main/scala/chisel3/util/BitPat.scala b/src/main/scala/chisel3/util/BitPat.scala new file mode 100644 index 00000000..13bbe1b0 --- /dev/null +++ b/src/main/scala/chisel3/util/BitPat.scala @@ -0,0 +1,89 @@ +// See LICENSE for license details. + +package chisel.util + +import scala.language.experimental.macros + +import chisel._ +import chisel.internal.sourceinfo.{SourceInfo, SourceInfoTransform} + +object BitPat { + /** Parses a bit pattern string into (bits, mask, width). + * + * @return bits the literal value, with don't cares being 0 + * @return mask the mask bits, with don't cares being 0 and cares being 1 + * @return width the number of bits in the literal, including values and + * don't cares. + */ + private def parse(x: String): (BigInt, BigInt, Int) = { + // Notes: + // While Verilog Xs also handle octal and hex cases, there isn't a + // compelling argument and no one has asked for it. + // If ? parsing is to be exposed, the return API needs further scrutiny + // (especially with things like mask polarity). + require(x.head == 'b', "BitPats must be in binary and be prefixed with 'b'") + var bits = BigInt(0) + var mask = BigInt(0) + for (d <- x.tail) { + if (d != '_') { + require("01?".contains(d), "Literal: " + x + " contains illegal character: " + d) + mask = (mask << 1) + (if (d == '?') 0 else 1) + bits = (bits << 1) + (if (d == '1') 1 else 0) + } + } + (bits, mask, x.length - 1) + } + + /** Creates a [[BitPat]] literal from a string. + * + * @param n the literal value as a string, in binary, prefixed with 'b' + * @note legal characters are '0', '1', and '?', as well as '_' as white + * space (which are ignored) + */ + def apply(n: String): BitPat = { + val (bits, mask, width) = parse(n) + new BitPat(bits, mask, width) + } + + /** Creates a [[BitPat]] of all don't cares of the specified bitwidth. */ + def dontCare(width: Int): BitPat = BitPat("b" + ("?" * width)) + + @deprecated("Use BitPat.dontCare", "chisel3") + def DC(width: Int): BitPat = dontCare(width) // scalastyle:ignore method.name + + /** Allows BitPats to be used where a UInt is expected. + * + * @note the BitPat must not have don't care bits (will error out otherwise) + */ + def bitPatToUInt(x: BitPat): UInt = { + require(x.mask == (BigInt(1) << x.getWidth) - 1) + UInt(x.value, x.getWidth) + } + + /** Allows UInts to be used where a BitPat is expected, useful for when an + * interface is defined with BitPats but not all cases need the partial + * matching capability. + * + * @note the UInt must be a literal + */ + def apply(x: UInt): BitPat = { + require(x.isLit) + BitPat("b" + x.litValue.toString(2)) + } +} + +// TODO: Break out of Core? (this doesn't involve FIRRTL generation) +/** Bit patterns are literals with masks, used to represent values with don't + * cares. Equality comparisons will ignore don't care bits (for example, + * BitPat(0b10?1) === UInt(0b1001) and UInt(0b1011)). + */ +sealed class BitPat(val value: BigInt, val mask: BigInt, width: Int) { + def getWidth: Int = width + 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/src/main/scala/chisel3/util/Bitwise.scala b/src/main/scala/chisel3/util/Bitwise.scala new file mode 100644 index 00000000..d7d62ea3 --- /dev/null +++ b/src/main/scala/chisel3/util/Bitwise.scala @@ -0,0 +1,74 @@ +// See LICENSE for license details. + +/** Miscellaneous circuit generators operating on bits. + */ + +package chisel.util + +import chisel._ +import chisel.core.SeqUtils + +object FillInterleaved +{ + def apply(n: Int, in: UInt): UInt = apply(n, in.toBools) + def apply(n: Int, in: Seq[Bool]): UInt = Vec(in.map(Fill(n, _))).toBits +} + +/** Returns the number of bits set (i.e value is 1) in the input signal. + */ +object PopCount +{ + def apply(in: Iterable[Bool]): UInt = SeqUtils.count(in.toSeq) + def apply(in: Bits): UInt = apply((0 until in.getWidth).map(in(_))) +} + +/** Fill fans out a UInt to multiple copies */ +object Fill { + /** Fan out x n times */ + def apply(n: Int, x: UInt): UInt = { + n match { + case 0 => UInt(width=0) + case 1 => x + case y if n > 1 => + val p2 = Array.ofDim[UInt](log2Up(n + 1)) + p2(0) = x + for (i <- 1 until p2.length) + p2(i) = Cat(p2(i-1), p2(i-1)) + Cat((0 until log2Up(y + 1)).filter(i => (y & (1 << i)) != 0).map(p2(_))) + case _ => throw new IllegalArgumentException(s"n (=$n) must be nonnegative integer.") + } + } + /** Fan out x n times */ + def apply(n: Int, x: Bool): UInt = + if (n > 1) { + UInt(0,n) - x + } else { + apply(n, x: UInt) + } +} + +/** Litte/big bit endian convertion: reverse the order of the bits in a UInt. +*/ +object Reverse +{ + private def doit(in: UInt, length: Int): UInt = { + if (length == 1) { + in + } else if (isPow2(length) && length >= 8 && length <= 64) { + // This esoterica improves simulation performance + var res = in + var shift = length >> 1 + var mask = UInt((BigInt(1) << length) - 1, length) + do { + mask = mask ^ (mask(length-shift-1,0) << shift) + res = ((res >> shift) & mask) | ((res(length-shift-1,0) << shift) & ~mask) + shift = shift >> 1 + } while (shift > 0) + res + } else { + val half = (1 << log2Up(length))/2 + Cat(doit(in(half-1,0), half), doit(in(length-1,half), length-half)) + } + } + def apply(in: UInt): UInt = doit(in, in.getWidth) +} diff --git a/src/main/scala/chisel3/util/Cat.scala b/src/main/scala/chisel3/util/Cat.scala new file mode 100644 index 00000000..b47da706 --- /dev/null +++ b/src/main/scala/chisel3/util/Cat.scala @@ -0,0 +1,21 @@ +// See LICENSE for license details. + +package chisel.util + +import chisel._ +import chisel.core.SeqUtils + +object Cat { + /** Combine data elements together + * @param a Data to combine with + * @param r any number of other Data elements to be combined in order + * @return A UInt which is all of the bits combined together + */ + def apply[T <: Bits](a: T, r: T*): UInt = apply(a :: r.toList) + + /** Combine data elements together + * @param r any number of other Data elements to be combined in order + * @return A UInt which is all of the bits combined together + */ + def apply[T <: Bits](r: Seq[T]): UInt = SeqUtils.asUInt(r.reverse) +} diff --git a/src/main/scala/chisel3/util/CircuitMath.scala b/src/main/scala/chisel3/util/CircuitMath.scala new file mode 100644 index 00000000..c3b94fdb --- /dev/null +++ b/src/main/scala/chisel3/util/CircuitMath.scala @@ -0,0 +1,28 @@ +// See LICENSE for license details. + +/** Circuit-land math operations. + */ + +package chisel.util + +import chisel._ + +/** Compute Log2 with truncation of a UInt in hardware using a Mux Tree + * An alternative interpretation is it computes the minimum number of bits needed to represent x + * @example + * {{{ data_out := Log2(data_in) }}} + * @note Truncation is used so Log2(UInt(12412)) = 13*/ +object Log2 { + /** Compute the Log2 on the least significant n bits of x */ + def apply(x: Bits, width: Int): UInt = { + if (width < 2) { + UInt(0) + } else if (width == 2) { + x(1) + } else { + Mux(x(width-1), UInt(width-1), apply(x, width-1)) + } + } + + def apply(x: Bits): UInt = apply(x, x.getWidth) +} diff --git a/src/main/scala/chisel3/util/Conditional.scala b/src/main/scala/chisel3/util/Conditional.scala new file mode 100644 index 00000000..01c12799 --- /dev/null +++ b/src/main/scala/chisel3/util/Conditional.scala @@ -0,0 +1,73 @@ +// See LICENSE for license details. + +/** Conditional blocks. + */ + +package chisel.util + +import scala.language.reflectiveCalls +import scala.language.experimental.macros +import scala.reflect.runtime.universe._ +import scala.reflect.macros.blackbox._ + +import chisel._ + +/** This is identical to [[Chisel.when when]] with the condition inverted */ +object unless { // scalastyle:ignore object.name + def apply(c: Bool)(block: => Unit) { + when (!c) { block } + } +} + +class SwitchContext[T <: Bits](cond: T) { + def is(v: Iterable[T])(block: => Unit) { + if (!v.isEmpty) when (v.map(_.asUInt === cond.asUInt).reduce(_||_)) { block } + } + def is(v: T)(block: => Unit) { is(Seq(v))(block) } + def is(v: T, vr: T*)(block: => Unit) { is(v :: vr.toList)(block) } +} + +/** An object for separate cases in [[Chisel.switch switch]] + * It is equivalent to a [[Chisel.when$ when]] block comparing to the condition + * Use outside of a switch statement is illegal */ +object is { // scalastyle:ignore object.name + // Begin deprecation of non-type-parameterized is statements. + def apply(v: Iterable[Bits])(block: => Unit) { + require(false, "The 'is' keyword may not be used outside of a switch.") + } + + def apply(v: Bits)(block: => Unit) { + require(false, "The 'is' keyword may not be used outside of a switch.") + } + + def apply(v: Bits, vr: Bits*)(block: => Unit) { + require(false, "The 'is' keyword may not be used outside of a switch.") + } +} + +/** Conditional logic to form a switch block + * @example + * {{{ ... // default values here + * switch ( myState ) { + * is( state1 ) { + * ... // some logic here + * } + * is( state2 ) { + * ... // some logic here + * } + * } }}}*/ +object switch { // scalastyle:ignore object.name + def apply[T <: Bits](cond: T)(x: => Unit): Unit = macro impl + def impl(c: Context)(cond: c.Tree)(x: c.Tree): c.Tree = { import c.universe._ + val sc = c.universe.internal.reificationSupport.freshTermName("sc") + def extractIsStatement(tree: Tree): List[c.universe.Tree] = tree match { + // TODO: remove when Chisel compatibility package is removed + case q"Chisel.`package`.is.apply( ..$params )( ..$body )" => List(q"$sc.is( ..$params )( ..$body )") + case q"chisel.util.is.apply( ..$params )( ..$body )" => List(q"$sc.is( ..$params )( ..$body )") + case b => throw new Exception(s"Cannot include blocks that do not begin with is() in switch.") + } + val q"..$body" = x + val ises = body.flatMap(extractIsStatement(_)) + q"""{ val $sc = new SwitchContext($cond); ..$ises }""" + } +} diff --git a/src/main/scala/chisel3/util/Counter.scala b/src/main/scala/chisel3/util/Counter.scala new file mode 100644 index 00000000..1c0b0203 --- /dev/null +++ b/src/main/scala/chisel3/util/Counter.scala @@ -0,0 +1,46 @@ +// See LICENSE for license details. + +package chisel.util + +import chisel._ + +/** A counter module + * @param n number of counts before the counter resets (or one more than the + * maximum output value of the counter), need not be a power of two + */ +class Counter(val n: Int) { + require(n >= 0) + val value = if (n > 1) Reg(init=UInt(0, log2Up(n))) else UInt(0) + /** Increment the counter, returning whether the counter currently is at the + * maximum and will wrap. The incremented value is registered and will be + * visible on the next cycle. + */ + def inc(): Bool = { + if (n > 1) { + val wrap = value === UInt(n-1) + value := value + UInt(1) + if (!isPow2(n)) { + when (wrap) { value := UInt(0) } + } + wrap + } else { + Bool(true) + } + } +} + +/** Counter Object + * Example Usage: + * {{{ val countOn = Bool(true) // increment counter every clock cycle + * val myCounter = Counter(countOn, n) + * when ( myCounter.value === UInt(3) ) { ... } }}}*/ +object Counter +{ + def apply(n: Int): Counter = new Counter(n) + def apply(cond: Bool, n: Int): (UInt, Bool) = { + val c = new Counter(n) + var wrap: Bool = null + when (cond) { wrap = c.inc() } + (c.value, cond && wrap) + } +} diff --git a/src/main/scala/chisel3/util/Decoupled.scala b/src/main/scala/chisel3/util/Decoupled.scala new file mode 100644 index 00000000..89b0e39d --- /dev/null +++ b/src/main/scala/chisel3/util/Decoupled.scala @@ -0,0 +1,185 @@ +// See LICENSE for license details. + +/** Wrappers for ready-valid (Decoupled) interfaces and associated circuit generators using them. + */ + +package chisel.util + +import chisel._ + +/** An I/O Bundle with simple handshaking using valid and ready signals for data 'bits'*/ +class DecoupledIO[+T <: Data](gen: T) extends Bundle +{ + val ready = Bool(INPUT) + val valid = Bool(OUTPUT) + val bits = gen.cloneType.asOutput + def fire(dummy: Int = 0): Bool = ready && valid + override def cloneType: this.type = new DecoupledIO(gen).asInstanceOf[this.type] +} + +/** Adds a ready-valid handshaking protocol to any interface. + * The standard used is that the consumer uses the flipped interface. + */ +object Decoupled { + def apply[T <: Data](gen: T): DecoupledIO[T] = new DecoupledIO(gen) +} + +/** An I/O bundle for enqueuing data with valid/ready handshaking + * Initialization must be handled, if necessary, by the parent circuit + */ +class EnqIO[T <: Data](gen: T) extends DecoupledIO(gen) +{ + /** push dat onto the output bits of this interface to let the consumer know it has happened. + * @param dat the values to assign to bits. + * @return dat. + */ + def enq(dat: T): T = { valid := Bool(true); bits := dat; dat } + + /** Initialize this Bundle. Valid is set to false, and all bits are set to zero. + * NOTE: This method of initialization is still being discussed and could change in the + * future. + */ + def init(): Unit = { + valid := Bool(false) + for (io <- bits.flatten) + io := UInt(0) + } + override def cloneType: this.type = { new EnqIO(gen).asInstanceOf[this.type]; } +} + +/** An I/O bundle for dequeuing data with valid/ready handshaking. + * Initialization must be handled, if necessary, by the parent circuit + */ +class DeqIO[T <: Data](gen: T) extends DecoupledIO(gen) with Flipped +{ + /** Assert ready on this port and return the associated data bits. + * This is typically used when valid has been asserted by the producer side. + * @param b ignored + * @return the data for this device, + */ + def deq(b: Boolean = false): T = { ready := Bool(true); bits } + + /** Initialize this Bundle. + * NOTE: This method of initialization is still being discussed and could change in the + * future. + */ + def init(): Unit = { + ready := Bool(false) + } + override def cloneType: this.type = { new DeqIO(gen).asInstanceOf[this.type]; } +} + +/** An I/O bundle for dequeuing data with valid/ready handshaking */ +class DecoupledIOC[+T <: Data](gen: T) extends Bundle +{ + val ready = Bool(INPUT) + val valid = Bool(OUTPUT) + val bits = gen.cloneType.asOutput +} + +/** An I/O Bundle for Queues + * @param gen The type of data to queue + * @param entries The max number of entries in the queue */ +class QueueIO[T <: Data](gen: T, entries: Int) extends Bundle +{ + /** I/O to enqueue data, is [[Chisel.DecoupledIO]] flipped */ + val enq = Decoupled(gen.cloneType).flip() + /** I/O to enqueue data, is [[Chisel.DecoupledIO]]*/ + val deq = Decoupled(gen.cloneType) + /** The current amount of data in the queue */ + val count = UInt(OUTPUT, log2Up(entries + 1)) +} + +/** A hardware module implementing a Queue + * @param gen The type of data to queue + * @param entries The max number of entries in the queue + * @param pipe True if a single entry queue can run at full throughput (like a pipeline). The ''ready'' signals are + * combinationally coupled. + * @param flow True if the inputs can be consumed on the same cycle (the inputs "flow" through the queue immediately). + * The ''valid'' signals are coupled. + * + * Example usage: + * {{{ val q = new Queue(UInt(), 16) + * q.io.enq <> producer.io.out + * consumer.io.in <> q.io.deq }}} + */ +class Queue[T <: Data](gen: T, val entries: Int, + pipe: Boolean = false, + flow: Boolean = false, + override_reset: Option[Bool] = None) +extends Module(override_reset=override_reset) { + def this(gen: T, entries: Int, pipe: Boolean, flow: Boolean, _reset: Bool) = + this(gen, entries, pipe, flow, Some(_reset)) + + val io = new QueueIO(gen, entries) + + val ram = Mem(entries, gen) + val enq_ptr = Counter(entries) + val deq_ptr = Counter(entries) + val maybe_full = Reg(init=Bool(false)) + + val ptr_match = enq_ptr.value === deq_ptr.value + val empty = ptr_match && !maybe_full + val full = ptr_match && maybe_full + val do_enq = Wire(init=io.enq.fire()) + val do_deq = Wire(init=io.deq.fire()) + + when (do_enq) { + ram(enq_ptr.value) := io.enq.bits + enq_ptr.inc() + } + when (do_deq) { + deq_ptr.inc() + } + when (do_enq != do_deq) { + maybe_full := do_enq + } + + io.deq.valid := !empty + io.enq.ready := !full + io.deq.bits := ram(deq_ptr.value) + + if (flow) { + when (io.enq.valid) { io.deq.valid := Bool(true) } + when (empty) { + io.deq.bits := io.enq.bits + do_deq := Bool(false) + when (io.deq.ready) { do_enq := Bool(false) } + } + } + + if (pipe) { + when (io.deq.ready) { io.enq.ready := Bool(true) } + } + + val ptr_diff = enq_ptr.value - deq_ptr.value + if (isPow2(entries)) { + io.count := Cat(maybe_full && ptr_match, ptr_diff) + } else { + io.count := Mux(ptr_match, + Mux(maybe_full, + UInt(entries), UInt(0)), + Mux(deq_ptr.value > enq_ptr.value, + UInt(entries) + ptr_diff, ptr_diff)) + } +} + +/** Generic hardware queue. Required parameter entries controls + the depth of the queues. The width of the queue is determined + from the inputs. + + Example usage: + {{{ val q = Queue(Decoupled(UInt()), 16) + q.io.enq <> producer.io.out + consumer.io.in <> q.io.deq }}} + */ +object Queue +{ + def apply[T <: Data](enq: DecoupledIO[T], entries: Int = 2, pipe: Boolean = false): DecoupledIO[T] = { + val q = Module(new Queue(enq.bits.cloneType, entries, pipe)) + q.io.enq.valid := enq.valid // not using <> so that override is allowed + q.io.enq.bits := enq.bits + enq.ready := q.io.enq.ready + TransitName(q.io.deq, q) + } +} diff --git a/src/main/scala/chisel3/util/Enum.scala b/src/main/scala/chisel3/util/Enum.scala new file mode 100644 index 00000000..8babcd23 --- /dev/null +++ b/src/main/scala/chisel3/util/Enum.scala @@ -0,0 +1,23 @@ +// See LICENSE for license details. + +/** Enum generators, allowing circuit constants to have more meaningful names. + */ + +package chisel.util + +import chisel._ + +object Enum { + /** Returns a sequence of Bits subtypes with values from 0 until n. Helper method. */ + private def createValues[T <: Bits](nodeType: T, n: Int): Seq[T] = + (0 until n).map(x => nodeType.fromInt(x, log2Up(n))) + + /** create n enum values of given type */ + def apply[T <: Bits](nodeType: T, n: Int): List[T] = createValues(nodeType, n).toList + + /** create enum values of given type and names */ + def apply[T <: Bits](nodeType: T, l: Symbol *): Map[Symbol, T] = (l zip createValues(nodeType, l.length)).toMap + + /** create enum values of given type and names */ + def apply[T <: Bits](nodeType: T, l: List[Symbol]): Map[Symbol, T] = (l zip createValues(nodeType, l.length)).toMap +} diff --git a/src/main/scala/chisel3/util/ImplicitConversions.scala b/src/main/scala/chisel3/util/ImplicitConversions.scala new file mode 100644 index 00000000..846c0cbd --- /dev/null +++ b/src/main/scala/chisel3/util/ImplicitConversions.scala @@ -0,0 +1,10 @@ +// See LICENSE for license details. + +package chisel.util + +import chisel._ + +object ImplicitConversions { + implicit def intToUInt(x: Int): UInt = UInt(x) + implicit def booleanToBool(x: Boolean): Bool = Bool(x) +} diff --git a/src/main/scala/chisel3/util/LFSR.scala b/src/main/scala/chisel3/util/LFSR.scala new file mode 100644 index 00000000..f70630bf --- /dev/null +++ b/src/main/scala/chisel3/util/LFSR.scala @@ -0,0 +1,24 @@ +// See LICENSE for license details. + +/** LFSRs in all shapes and sizes. + */ + +package chisel.util + +import chisel._ + +// scalastyle:off magic.number +/** linear feedback shift register + */ +object LFSR16 +{ + def apply(increment: Bool = Bool(true)): UInt = + { + val width = 16 + val lfsr = Reg(init=UInt(1, width)) + when (increment) { lfsr := Cat(lfsr(0)^lfsr(2)^lfsr(3)^lfsr(5), lfsr(width-1,1)) } + lfsr + } +} +// scalastyle:on magic.number + diff --git a/src/main/scala/chisel3/util/Lookup.scala b/src/main/scala/chisel3/util/Lookup.scala new file mode 100644 index 00000000..d32d9aec --- /dev/null +++ b/src/main/scala/chisel3/util/Lookup.scala @@ -0,0 +1,19 @@ +// See LICENSE for license details. + +package chisel.util + +import chisel._ + +object ListLookup { + def apply[T <: Data](addr: UInt, default: List[T], mapping: Array[(BitPat, List[T])]): List[T] = { + val map = mapping.map(m => (m._1 === addr, m._2)) + default.zipWithIndex map { case (d, i) => + map.foldRight(d)((m, n) => Mux(m._1, m._2(i), n)) + } + } +} + +object Lookup { + def apply[T <: Bits](addr: UInt, default: T, mapping: Seq[(BitPat, T)]): T = + ListLookup(addr, List(default), mapping.map(m => (m._1, List(m._2))).toArray).head +} diff --git a/src/main/scala/chisel3/util/Math.scala b/src/main/scala/chisel3/util/Math.scala new file mode 100644 index 00000000..69464d15 --- /dev/null +++ b/src/main/scala/chisel3/util/Math.scala @@ -0,0 +1,44 @@ +// See LICENSE for license details. + +/** Scala-land math helper functions, like logs. + */ + +package chisel.util + +import chisel._ + +/** Compute the log2 rounded up with min value of 1 */ +object log2Up { + def apply(in: BigInt): Int = { + require(in >= 0) + 1 max (in-1).bitLength + } + def apply(in: Int): Int = apply(BigInt(in)) +} + +/** Compute the log2 rounded up */ +object log2Ceil { + def apply(in: BigInt): Int = { + require(in > 0) + (in-1).bitLength + } + def apply(in: Int): Int = apply(BigInt(in)) +} + +/** Compute the log2 rounded down with min value of 1 */ +object log2Down { + def apply(in: BigInt): Int = log2Up(in) - (if (isPow2(in)) 0 else 1) + def apply(in: Int): Int = apply(BigInt(in)) +} + +/** Compute the log2 rounded down */ +object log2Floor { + def apply(in: BigInt): Int = log2Ceil(in) - (if (isPow2(in)) 0 else 1) + def apply(in: Int): Int = apply(BigInt(in)) +} + +/** Check if an Integer is a power of 2 */ +object isPow2 { + def apply(in: BigInt): Boolean = in > 0 && ((in & (in-1)) == 0) + def apply(in: Int): Boolean = apply(BigInt(in)) +} diff --git a/src/main/scala/chisel3/util/Mux.scala b/src/main/scala/chisel3/util/Mux.scala new file mode 100644 index 00000000..6f074a7e --- /dev/null +++ b/src/main/scala/chisel3/util/Mux.scala @@ -0,0 +1,64 @@ +// See LICENSE for license details. + +/** Mux circuit generators. + */ + +package chisel.util + +import chisel._ +import chisel.core.SeqUtils + +/** Builds a Mux tree out of the input signal vector using a one hot encoded + select signal. Returns the output of the Mux tree. + */ +object Mux1H +{ + def apply[T <: Data](sel: Seq[Bool], in: Seq[T]): T = + apply(sel zip in) + def apply[T <: Data](in: Iterable[(Bool, T)]): T = SeqUtils.oneHotMux(in) + def apply[T <: Data](sel: UInt, in: Seq[T]): T = + apply((0 until in.size).map(sel(_)), in) + def apply(sel: UInt, in: UInt): Bool = (sel & in).orR +} + +/** Builds a Mux tree under the assumption that multiple select signals + can be enabled. Priority is given to the first select signal. + + Returns the output of the Mux tree. + */ +object PriorityMux +{ + def apply[T <: Data](in: Seq[(Bool, T)]): T = SeqUtils.priorityMux(in) + def apply[T <: Data](sel: Seq[Bool], in: Seq[T]): T = apply(sel zip in) + def apply[T <: Data](sel: Bits, in: Seq[T]): T = apply((0 until in.size).map(sel(_)), in) +} + +/** MuxLookup creates a cascade of n Muxs to search for a key value */ +object MuxLookup { + /** @param key a key to search for + * @param default a default value if nothing is found + * @param mapping a sequence to search of keys and values + * @return the value found or the default if not + */ + def apply[S <: UInt, T <: Bits] (key: S, default: T, mapping: Seq[(S, T)]): T = { + var res = default + for ((k, v) <- mapping.reverse) + res = Mux(k === key, v, res) + res + } + +} + +/** MuxCase returns the first value that is enabled in a map of values */ +object MuxCase { + /** @param default the default value if none are enabled + * @param mapping a set of data values with associated enables + * @return the first value in mapping that is enabled */ + def apply[T <: Bits] (default: T, mapping: Seq[(Bool, T)]): T = { + var res = default + for ((t, v) <- mapping.reverse){ + res = Mux(t, v, res) + } + res + } +} diff --git a/src/main/scala/chisel3/util/OneHot.scala b/src/main/scala/chisel3/util/OneHot.scala new file mode 100644 index 00000000..ef21c65d --- /dev/null +++ b/src/main/scala/chisel3/util/OneHot.scala @@ -0,0 +1,64 @@ +// See LICENSE for license details. + +/** Circuit generators for working with one-hot representations. + */ + +package chisel.util + +import chisel._ + +/** Converts from One Hot Encoding to a UInt indicating which bit is active + * This is the inverse of [[Chisel.UIntToOH UIntToOH]]*/ +object OHToUInt { + def apply(in: Seq[Bool]): UInt = apply(Vec(in)) + def apply(in: Vec[Bool]): UInt = apply(in.toBits, in.size) + def apply(in: Bits): UInt = apply(in, in.getWidth) + + def apply(in: Bits, width: Int): UInt = { + if (width <= 2) { + Log2(in, width) + } else { + val mid = 1 << (log2Up(width)-1) + val hi = in(width-1, mid) + val lo = in(mid-1, 0) + Cat(hi.orR, apply(hi | lo, mid)) + } + } +} + +/** @return the bit position of the trailing 1 in the input vector + * with the assumption that multiple bits of the input bit vector can be set + * @example {{{ data_out := PriorityEncoder(data_in) }}} + */ +object PriorityEncoder { + def apply(in: Seq[Bool]): UInt = PriorityMux(in, (0 until in.size).map(UInt(_))) + def apply(in: Bits): UInt = apply(in.toBools) +} + +/** Returns the one hot encoding of the input UInt. + */ +object UIntToOH +{ + def apply(in: UInt, width: Int = -1): UInt = + if (width == -1) { + UInt(1) << in + } else { + (UInt(1) << in(log2Up(width)-1,0))(width-1,0) + } +} + +/** Returns a bit vector in which only the least-significant 1 bit in + the input vector, if any, is set. + */ +object PriorityEncoderOH +{ + private def encode(in: Seq[Bool]): UInt = { + val outs = Seq.tabulate(in.size)(i => UInt(BigInt(1) << i, in.size)) + PriorityMux(in :+ Bool(true), outs :+ UInt(0, in.size)) + } + def apply(in: Seq[Bool]): Seq[Bool] = { + val enc = encode(in) + Seq.tabulate(in.size)(enc(_)) + } + def apply(in: Bits): UInt = encode((0 until in.getWidth).map(i => in(i))) +} diff --git a/src/main/scala/chisel3/util/Reg.scala b/src/main/scala/chisel3/util/Reg.scala new file mode 100644 index 00000000..1b40646d --- /dev/null +++ b/src/main/scala/chisel3/util/Reg.scala @@ -0,0 +1,57 @@ +// See LICENSE for license details. + +/** Variations and helpers for registers. + */ + +package chisel.util + +import chisel._ + +object RegNext { + + def apply[T <: Data](next: T): T = Reg[T](null.asInstanceOf[T], next, null.asInstanceOf[T]) + + def apply[T <: Data](next: T, init: T): T = Reg[T](null.asInstanceOf[T], next, init) + +} + +object RegInit { + + def apply[T <: Data](init: T): T = Reg[T](null.asInstanceOf[T], null.asInstanceOf[T], init) + +} + +/** A register with an Enable signal */ +object RegEnable +{ + def apply[T <: Data](updateData: T, enable: Bool): T = { + val r = Reg(updateData) + when (enable) { r := updateData } + r + } + def apply[T <: Data](updateData: T, resetData: T, enable: Bool): T = { + val r = RegInit(resetData) + when (enable) { r := updateData } + r + } +} + +/** Returns the n-cycle delayed version of the input signal. + */ +object ShiftRegister +{ + /** @param in input to delay + * @param n number of cycles to delay + * @param en enable the shift */ + def apply[T <: Data](in: T, n: Int, en: Bool = Bool(true)): T = + { + // The order of tests reflects the expected use cases. + if (n == 1) { + RegEnable(in, en) + } else if (n != 0) { + RegNext(apply(in, n-1, en)) + } else { + in + } + } +} diff --git a/src/main/scala/chisel3/util/TransitName.scala b/src/main/scala/chisel3/util/TransitName.scala new file mode 100644 index 00000000..04e1995b --- /dev/null +++ b/src/main/scala/chisel3/util/TransitName.scala @@ -0,0 +1,22 @@ +package chisel.util + +import chisel._ +import internal.HasId + +object TransitName { + // The purpose of this is to allow a library to 'move' a name call to a more + // appropriate place. + // For example, a library factory function may create a module and return + // the io. The only user-exposed field is that given IO, which can't use + // any name supplied by the user. This can add a hook so that the supplied + // name then names the Module. + // See Queue companion object for working example + def apply[T<:HasId](from: T, to: HasId): T = { + from.addPostnameHook((given_name: String) => {to.suggestName(given_name)}) + from + } + def withSuffix[T<:HasId](suffix: String)(from: T, to: HasId): T = { + from.addPostnameHook((given_name: String) => {to.suggestName(given_name+suffix)}) + from + } +} diff --git a/src/main/scala/chisel3/util/Valid.scala b/src/main/scala/chisel3/util/Valid.scala new file mode 100644 index 00000000..56ac9abb --- /dev/null +++ b/src/main/scala/chisel3/util/Valid.scala @@ -0,0 +1,61 @@ +// See LICENSE for license details. + +/** Wrappers for valid interfaces and associated circuit generators using them. + */ + +package chisel.util + +import chisel._ + +/** An I/O Bundle containing data and a signal determining if it is valid */ +class ValidIO[+T <: Data](gen2: T) extends Bundle +{ + val valid = Bool(OUTPUT) + val bits = gen2.cloneType.asOutput + def fire(dummy: Int = 0): Bool = valid + override def cloneType: this.type = new ValidIO(gen2).asInstanceOf[this.type] +} + +/** Adds a valid protocol to any interface. The standard used is + that the consumer uses the flipped interface. +*/ +object Valid { + def apply[T <: Data](gen: T): ValidIO[T] = new ValidIO(gen) +} + +/** A hardware module that delays data coming down the pipeline + by the number of cycles set by the latency parameter. Functionality + is similar to ShiftRegister but this exposes a Pipe interface. + + Example usage: + val pipe = new Pipe(UInt()) + pipe.io.enq <> produce.io.out + consumer.io.in <> pipe.io.deq + */ +object Pipe +{ + def apply[T <: Data](enqValid: Bool, enqBits: T, latency: Int): ValidIO[T] = { + if (latency == 0) { + val out = Wire(Valid(enqBits)) + out.valid <> enqValid + out.bits <> enqBits + out + } else { + val v = Reg(Bool(), next=enqValid, init=Bool(false)) + val b = RegEnable(enqBits, enqValid) + apply(v, b, latency-1) + } + } + def apply[T <: Data](enqValid: Bool, enqBits: T): ValidIO[T] = apply(enqValid, enqBits, 1) + def apply[T <: Data](enq: ValidIO[T], latency: Int = 1): ValidIO[T] = apply(enq.valid, enq.bits, latency) +} + +class Pipe[T <: Data](gen: T, latency: Int = 1) extends Module +{ + val io = new Bundle { + val enq = Valid(gen).flip + val deq = Valid(gen) + } + + io.deq <> Pipe(io.enq, latency) +} -- cgit v1.2.3 From 3026dd214f3db3308eaf8f876d0fc03f75c577d3 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Mon, 20 Jun 2016 11:38:26 -0700 Subject: Rename "package", "import", and explicit references to "chisel3". --- .../src/main/scala/chisel3/core/Aggregate.scala | 20 +- .../src/main/scala/chisel3/core/Assert.scala | 10 +- .../src/main/scala/chisel3/core/Bits.scala | 26 +- .../src/main/scala/chisel3/core/BlackBox.scala | 8 +- .../src/main/scala/chisel3/core/Data.scala | 20 +- .../src/main/scala/chisel3/core/Mem.scala | 10 +- .../src/main/scala/chisel3/core/Module.scala | 16 +- .../src/main/scala/chisel3/core/Printf.scala | 10 +- .../src/main/scala/chisel3/core/Reg.scala | 10 +- .../src/main/scala/chisel3/core/SeqUtils.scala | 6 +- .../src/main/scala/chisel3/core/When.scala | 10 +- .../src/main/scala/chisel3/internal/Builder.scala | 34 +-- .../src/main/scala/chisel3/internal/Error.scala | 8 +- .../main/scala/chisel3/internal/SourceInfo.scala | 4 +- .../main/scala/chisel3/internal/firrtl/IR.scala | 12 +- .../internal/sourceinfo/SourceInfoTransform.scala | 4 +- src/main/scala/chisel3/Driver.scala | 2 +- src/main/scala/chisel3/compatibility.scala | 278 ++++++++++----------- .../compatibility/FileSystemUtilities.scala | 4 +- src/main/scala/chisel3/compatibility/Main.scala | 4 +- src/main/scala/chisel3/compatibility/debug.scala | 4 +- .../chisel3/compatibility/throwException.scala | 4 +- .../scala/chisel3/internal/firrtl/Emitter.scala | 8 +- src/main/scala/chisel3/package.scala | 96 +++---- src/main/scala/chisel3/testers/BasicTester.scala | 4 +- src/main/scala/chisel3/testers/TesterDriver.scala | 4 +- src/main/scala/chisel3/util/Arbiter.scala | 4 +- src/main/scala/chisel3/util/BitPat.scala | 6 +- src/main/scala/chisel3/util/Bitwise.scala | 6 +- src/main/scala/chisel3/util/Cat.scala | 6 +- src/main/scala/chisel3/util/CircuitMath.scala | 4 +- src/main/scala/chisel3/util/Conditional.scala | 6 +- src/main/scala/chisel3/util/Counter.scala | 4 +- src/main/scala/chisel3/util/Decoupled.scala | 4 +- src/main/scala/chisel3/util/Enum.scala | 4 +- .../scala/chisel3/util/ImplicitConversions.scala | 4 +- src/main/scala/chisel3/util/LFSR.scala | 4 +- src/main/scala/chisel3/util/Lookup.scala | 4 +- src/main/scala/chisel3/util/Math.scala | 4 +- src/main/scala/chisel3/util/Mux.scala | 6 +- src/main/scala/chisel3/util/OneHot.scala | 4 +- src/main/scala/chisel3/util/Reg.scala | 4 +- src/main/scala/chisel3/util/TransitName.scala | 4 +- src/main/scala/chisel3/util/Valid.scala | 4 +- src/test/scala/chiselTests/Assert.scala | 6 +- src/test/scala/chiselTests/BitwiseOps.scala | 4 +- src/test/scala/chiselTests/BlackBox.scala | 6 +- src/test/scala/chiselTests/BundleWire.scala | 4 +- src/test/scala/chiselTests/ChiselSpec.scala | 4 +- src/test/scala/chiselTests/ComplexAssign.scala | 6 +- src/test/scala/chiselTests/Counter.scala | 6 +- src/test/scala/chiselTests/Decoder.scala | 6 +- src/test/scala/chiselTests/DeqIOSpec.scala | 6 +- src/test/scala/chiselTests/Direction.scala | 4 +- .../scala/chiselTests/EnableShiftRegister.scala | 4 +- src/test/scala/chiselTests/GCD.scala | 4 +- src/test/scala/chiselTests/Harness.scala | 4 +- src/test/scala/chiselTests/LFSR16.scala | 8 +- src/test/scala/chiselTests/MemorySearch.scala | 4 +- src/test/scala/chiselTests/Module.scala | 2 +- src/test/scala/chiselTests/MulLookup.scala | 4 +- src/test/scala/chiselTests/MultiAssign.scala | 6 +- src/test/scala/chiselTests/OptionBundle.scala | 4 +- src/test/scala/chiselTests/Padding.scala | 2 +- .../scala/chiselTests/ParameterizedModule.scala | 4 +- src/test/scala/chiselTests/Printf.scala | 4 +- src/test/scala/chiselTests/Reg.scala | 4 +- src/test/scala/chiselTests/Risc.scala | 4 +- src/test/scala/chiselTests/SIntOps.scala | 4 +- src/test/scala/chiselTests/Stack.scala | 4 +- src/test/scala/chiselTests/Stop.scala | 4 +- src/test/scala/chiselTests/Tbl.scala | 6 +- src/test/scala/chiselTests/TesterDriverSpec.scala | 6 +- src/test/scala/chiselTests/UIntOps.scala | 4 +- src/test/scala/chiselTests/Vec.scala | 6 +- src/test/scala/chiselTests/VectorPacketIO.scala | 6 +- src/test/scala/chiselTests/VendingMachine.scala | 4 +- src/test/scala/chiselTests/When.scala | 6 +- 78 files changed, 429 insertions(+), 429 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala index 38a42fea..f2774a8d 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala @@ -1,15 +1,15 @@ // See LICENSE for license details. -package chisel.core +package chisel3.core import scala.collection.immutable.ListMap import scala.collection.mutable.{ArrayBuffer, HashSet, LinkedHashMap} import scala.language.experimental.macros -import chisel.internal._ -import chisel.internal.Builder.pushCommand -import chisel.internal.firrtl._ -import chisel.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, VecTransform, SourceInfoTransform} +import chisel3.internal._ +import chisel3.internal.Builder.pushCommand +import chisel3.internal.firrtl._ +import chisel3.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, VecTransform, SourceInfoTransform} /** An abstract class for data types that solely consist of (are an aggregate * of) other Data objects. @@ -163,8 +163,8 @@ sealed class Vec[T <: Data] private (gen: => T, val length: Int) 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] = + private[chisel3] def toType: String = s"${t.toType}[$length]" + private[chisel3] lazy val flatten: IndexedSeq[Bits] = (0 until length).flatMap(i => this.apply(i).flatten) for ((elt, i) <- self zipWithIndex) @@ -331,17 +331,17 @@ class Bundle extends Aggregate(NO_DIR) { } ArrayBuffer(nameMap.toSeq:_*) sortWith {case ((an, a), (bn, b)) => (a._id > b._id) || ((a eq b) && (an > bn))} } - private[chisel] def toType = { + private[chisel3] 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[chisel3] lazy val flatten = namedElts.flatMap(_._2.flatten) private[core] def addElt(name: String, elt: Data): Unit = namedElts += name -> elt - private[chisel] override def _onModuleClose: Unit = // scalastyle:ignore method.name + private[chisel3] override def _onModuleClose: Unit = // scalastyle:ignore method.name for ((name, elt) <- namedElts) { elt.setRef(this, _namespace.name(name)) } override def cloneType : this.type = { diff --git a/chiselFrontend/src/main/scala/chisel3/core/Assert.scala b/chiselFrontend/src/main/scala/chisel3/core/Assert.scala index 00cb00f4..c4727148 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Assert.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Assert.scala @@ -1,14 +1,14 @@ // See LICENSE for license details. -package chisel.core +package chisel3.core import scala.reflect.macros.blackbox.Context import scala.language.experimental.macros -import chisel.internal._ -import chisel.internal.Builder.pushCommand -import chisel.internal.firrtl._ -import chisel.internal.sourceinfo.SourceInfo +import chisel3.internal._ +import chisel3.internal.Builder.pushCommand +import chisel3.internal.firrtl._ +import chisel3.internal.sourceinfo.SourceInfo object assert { // scalastyle:ignore object.name /** Checks for a condition to be valid in the circuit at all times. If the diff --git a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala index 38e71f8d..94d808a4 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala @@ -1,15 +1,15 @@ // See LICENSE for license details. -package chisel.core +package chisel3.core import scala.language.experimental.macros -import chisel.internal._ -import chisel.internal.Builder.pushOp -import chisel.internal.firrtl._ -import chisel.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, SourceInfoTransform, SourceInfoWhiteboxTransform, +import chisel3.internal._ +import chisel3.internal.Builder.pushOp +import chisel3.internal.firrtl._ +import chisel3.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, SourceInfoTransform, SourceInfoWhiteboxTransform, UIntTransform, MuxTransform} -import chisel.internal.firrtl.PrimOp._ +import chisel3.internal.firrtl.PrimOp._ /** Element is a leaf data type: it cannot contain other Data objects. Example * uses are for representing primitive data types, like integers and bits. @@ -25,9 +25,9 @@ sealed abstract class Bits(dirArg: Direction, width: Width, override val litArg: // Arguments for: self-checking code (can't do arithmetic on bits) // Arguments against: generates down to a FIRRTL UInt anyways - private[chisel] def fromInt(x: BigInt, w: Int): this.type + private[chisel3] def fromInt(x: BigInt, w: Int): this.type - private[chisel] def flatten: IndexedSeq[Bits] = IndexedSeq(this) + private[chisel3] def flatten: IndexedSeq[Bits] = IndexedSeq(this) def cloneType: this.type = cloneTypeWidth(width) @@ -360,9 +360,9 @@ sealed class UInt private[core] (dir: Direction, width: Width, lit: Option[ULit] extends Bits(dir, width, lit) with Num[UInt] { private[core] override def cloneTypeWidth(w: Width): this.type = new UInt(dir, w).asInstanceOf[this.type] - private[chisel] def toType = s"UInt$width" + private[chisel3] def toType = s"UInt$width" - override private[chisel] def fromInt(value: BigInt, width: Int): this.type = + override private[chisel3] def fromInt(value: BigInt, width: Int): this.type = UInt(value, width).asInstanceOf[this.type] override def := (that: Data)(implicit sourceInfo: SourceInfo): Unit = that match { @@ -537,14 +537,14 @@ sealed class SInt private (dir: Direction, width: Width, lit: Option[SLit] = Non extends Bits(dir, width, lit) with Num[SInt] { private[core] override def cloneTypeWidth(w: Width): this.type = new SInt(dir, w).asInstanceOf[this.type] - private[chisel] def toType = s"SInt$width" + private[chisel3] def toType = s"SInt$width" override def := (that: Data)(implicit sourceInfo: SourceInfo): Unit = that match { case _: SInt => this connect that case _ => this badConnect that } - override private[chisel] def fromInt(value: BigInt, width: Int): this.type = + override private[chisel3] def fromInt(value: BigInt, width: Int): this.type = SInt(value, width).asInstanceOf[this.type] final def unary_- (): SInt = macro SourceInfoTransform.noArg @@ -671,7 +671,7 @@ sealed class Bool(dir: Direction, lit: Option[ULit] = None) extends UInt(dir, Wi new Bool(dir).asInstanceOf[this.type] } - override private[chisel] def fromInt(value: BigInt, width: Int): this.type = { + override private[chisel3] def fromInt(value: BigInt, width: Int): this.type = { require((value == 0 || value == 1) && width == 1) Bool(value == 1).asInstanceOf[this.type] } diff --git a/chiselFrontend/src/main/scala/chisel3/core/BlackBox.scala b/chiselFrontend/src/main/scala/chisel3/core/BlackBox.scala index 2126ebce..eee8d598 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/BlackBox.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/BlackBox.scala @@ -1,10 +1,10 @@ // See LICENSE for license details. -package chisel.core +package chisel3.core -import chisel.internal.Builder.pushCommand -import chisel.internal.firrtl.{ModuleIO, DefInvalid} -import chisel.internal.sourceinfo.SourceInfo +import chisel3.internal.Builder.pushCommand +import chisel3.internal.firrtl.{ModuleIO, DefInvalid} +import chisel3.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 diff --git a/chiselFrontend/src/main/scala/chisel3/core/Data.scala b/chiselFrontend/src/main/scala/chisel3/core/Data.scala index cae38144..d5704369 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Data.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Data.scala @@ -1,13 +1,13 @@ // See LICENSE for license details. -package chisel.core +package chisel3.core import scala.language.experimental.macros -import chisel.internal._ -import chisel.internal.Builder.pushCommand -import chisel.internal.firrtl._ -import chisel.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, UnlocatableSourceInfo, WireTransform, SourceInfoTransform} +import chisel3.internal._ +import chisel3.internal.Builder.pushCommand +import chisel3.internal.firrtl._ +import chisel3.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, UnlocatableSourceInfo, WireTransform, SourceInfoTransform} sealed abstract class Direction(name: String) { override def toString: String = name @@ -53,9 +53,9 @@ abstract class Data(dirArg: Direction) extends HasId { private[core] def bulkConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit = pushCommand(BulkConnect(sourceInfo, this.lref, that.lref)) private[core] def lref: Node = Node(this) - private[chisel] def ref: Arg = if (isLit) litArg.get else lref + private[chisel3] def ref: Arg = if (isLit) litArg.get else lref private[core] def cloneTypeWidth(width: Width): this.type - private[chisel] def toType: String + private[chisel3] def toType: String def := (that: Data)(implicit sourceInfo: SourceInfo): Unit = this badConnect that @@ -78,7 +78,7 @@ abstract class Data(dirArg: Direction) extends HasId { // currently don't exist (while this information may be available during // FIRRTL emission, it would break directionality querying from Chisel, which // does get used). - private[chisel] def flatten: IndexedSeq[Bits] + private[chisel3] def flatten: IndexedSeq[Bits] /** Creates an new instance of this type, unpacking the input Bits into * structured data. @@ -145,9 +145,9 @@ object Clock { // TODO: Document this. sealed class Clock(dirArg: Direction) extends Element(dirArg, Width(1)) { def cloneType: this.type = Clock(dirArg).asInstanceOf[this.type] - private[chisel] override def flatten: IndexedSeq[Bits] = IndexedSeq() + private[chisel3] override def flatten: IndexedSeq[Bits] = IndexedSeq() private[core] def cloneTypeWidth(width: Width): this.type = cloneType - private[chisel] def toType = "Clock" + private[chisel3] def toType = "Clock" override def := (that: Data)(implicit sourceInfo: SourceInfo): Unit = that match { case _: Clock => this connect that diff --git a/chiselFrontend/src/main/scala/chisel3/core/Mem.scala b/chiselFrontend/src/main/scala/chisel3/core/Mem.scala index a2df2910..38f5ef14 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Mem.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Mem.scala @@ -1,13 +1,13 @@ // See LICENSE for license details. -package chisel.core +package chisel3.core import scala.language.experimental.macros -import chisel.internal._ -import chisel.internal.Builder.pushCommand -import chisel.internal.firrtl._ -import chisel.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, UnlocatableSourceInfo, MemTransform} +import chisel3.internal._ +import chisel3.internal.Builder.pushCommand +import chisel3.internal.firrtl._ +import chisel3.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") diff --git a/chiselFrontend/src/main/scala/chisel3/core/Module.scala b/chiselFrontend/src/main/scala/chisel3/core/Module.scala index 1de3efe5..7032e762 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Module.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Module.scala @@ -1,15 +1,15 @@ // See LICENSE for license details. -package chisel.core +package chisel3.core import scala.collection.mutable.{ArrayBuffer, HashSet} import scala.language.experimental.macros -import chisel.internal._ -import chisel.internal.Builder.pushCommand -import chisel.internal.Builder.dynamicContext -import chisel.internal.firrtl._ -import chisel.internal.sourceinfo.{SourceInfo, InstTransform, UnlocatableSourceInfo} +import chisel3.internal._ +import chisel3.internal.Builder.pushCommand +import chisel3.internal.Builder.dynamicContext +import chisel3.internal.firrtl._ +import chisel3.internal.sourceinfo.{SourceInfo, InstTransform, UnlocatableSourceInfo} object Module { /** A wrapper method that all Module instantiations must be wrapped in @@ -53,7 +53,7 @@ extends HasId { def this(_clock: Clock, _reset: Bool) = this(Option(_clock), Option(_reset)) private[core] val _namespace = Builder.globalNamespace.child - private[chisel] val _commands = ArrayBuffer[Command]() + private[chisel3] val _commands = ArrayBuffer[Command]() private[core] val _ids = ArrayBuffer[HasId]() dynamicContext.currentModule = Some(this) @@ -67,7 +67,7 @@ extends HasId { val clock = Clock(INPUT) val reset = Bool(INPUT) - private[chisel] def addId(d: HasId) { _ids += d } + private[chisel3] def addId(d: HasId) { _ids += d } private[core] def ports: Seq[(String,Data)] = Vector( ("clk", clock), ("reset", reset), ("io", io) diff --git a/chiselFrontend/src/main/scala/chisel3/core/Printf.scala b/chiselFrontend/src/main/scala/chisel3/core/Printf.scala index a7970816..b0a3c955 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Printf.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Printf.scala @@ -1,13 +1,13 @@ // See LICENSE for license details. -package chisel.core +package chisel3.core import scala.language.experimental.macros -import chisel.internal._ -import chisel.internal.Builder.pushCommand -import chisel.internal.firrtl._ -import chisel.internal.sourceinfo.SourceInfo +import chisel3.internal._ +import chisel3.internal.Builder.pushCommand +import chisel3.internal.firrtl._ +import chisel3.internal.sourceinfo.SourceInfo object printf { // scalastyle:ignore object.name /** Prints a message in simulation. diff --git a/chiselFrontend/src/main/scala/chisel3/core/Reg.scala b/chiselFrontend/src/main/scala/chisel3/core/Reg.scala index 78461334..b0dd3bb1 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Reg.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Reg.scala @@ -1,11 +1,11 @@ // See LICENSE for license details. -package chisel.core +package chisel3.core -import chisel.internal._ -import chisel.internal.Builder.pushCommand -import chisel.internal.firrtl._ -import chisel.internal.sourceinfo.{SourceInfo, UnlocatableSourceInfo} +import chisel3.internal._ +import chisel3.internal.Builder.pushCommand +import chisel3.internal.firrtl._ +import chisel3.internal.sourceinfo.{SourceInfo, UnlocatableSourceInfo} object Reg { private[core] def makeType[T <: Data](t: T = null, next: T = null, init: T = null): T = { diff --git a/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala b/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala index e31119a5..91cb9e89 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala @@ -1,12 +1,12 @@ // See LICENSE for license details. -package chisel.core +package chisel3.core import scala.language.experimental.macros -import chisel.internal.sourceinfo.{SourceInfo, SourceInfoTransform} +import chisel3.internal.sourceinfo.{SourceInfo, SourceInfoTransform} -private[chisel] object SeqUtils { +private[chisel3] object SeqUtils { /** Equivalent to Cat(r(n-1), ..., r(0)) */ def asUInt[T <: Bits](in: Seq[T]): UInt = macro SourceInfoTransform.inArg diff --git a/chiselFrontend/src/main/scala/chisel3/core/When.scala b/chiselFrontend/src/main/scala/chisel3/core/When.scala index 5d484313..196e7903 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/When.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/When.scala @@ -1,13 +1,13 @@ // See LICENSE for license details. -package chisel.core +package chisel3.core import scala.language.experimental.macros -import chisel.internal._ -import chisel.internal.Builder.pushCommand -import chisel.internal.firrtl._ -import chisel.internal.sourceinfo.{SourceInfo} +import chisel3.internal._ +import chisel3.internal.Builder.pushCommand +import chisel3.internal.firrtl._ +import chisel3.internal.sourceinfo.{SourceInfo} object when { // scalastyle:ignore object.name /** Create a `when` condition block, where whether a block of logic is diff --git a/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala b/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala index 01628105..0e0a88cc 100644 --- a/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala +++ b/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala @@ -1,15 +1,15 @@ // See LICENSE for license details. -package chisel.internal +package chisel3.internal import scala.util.DynamicVariable import scala.collection.mutable.{ArrayBuffer, HashMap} -import chisel._ +import chisel3._ import core._ import firrtl._ -private[chisel] class Namespace(parent: Option[Namespace], keywords: Set[String]) { +private[chisel3] class Namespace(parent: Option[Namespace], keywords: Set[String]) { private val names = collection.mutable.HashMap[String, Long]() for (keyword <- keywords) names(keyword) = 1 @@ -38,7 +38,7 @@ private[chisel] class Namespace(parent: Option[Namespace], keywords: Set[String] def child: Namespace = child(Set()) } -private[chisel] class IdGen { +private[chisel3] class IdGen { private var counter = -1L def next: Long = { counter += 1 @@ -46,12 +46,12 @@ private[chisel] class IdGen { } } -private[chisel] trait HasId { - private[chisel] def _onModuleClose {} // scalastyle:ignore method.name - private[chisel] val _parent = Builder.dynamicContext.currentModule +private[chisel3] trait HasId { + private[chisel3] def _onModuleClose {} // scalastyle:ignore method.name + private[chisel3] val _parent = Builder.dynamicContext.currentModule _parent.foreach(_.addId(this)) - private[chisel] val _id = Builder.idGen.next + private[chisel3] val _id = Builder.idGen.next override def hashCode: Int = _id.toInt override def equals(that: Any): Boolean = that match { case x: HasId => _id == x._id @@ -68,12 +68,12 @@ private[chisel] trait HasId { for(hook <- postname_hooks) { hook(name) } this } - private[chisel] def addPostnameHook(hook: String=>Unit): Unit = postname_hooks += hook + private[chisel3] def addPostnameHook(hook: String=>Unit): Unit = postname_hooks += hook // Uses a namespace to convert suggestion into a true name // Will not do any naming if the reference already assigned. // (e.g. tried to suggest a name to part of a Bundle) - private[chisel] def forceName(default: =>String, namespace: Namespace): Unit = + private[chisel3] def forceName(default: =>String, namespace: Namespace): Unit = if(_ref.isEmpty) { val candidate_name = suggested_name.getOrElse(default) val available_name = namespace.name(candidate_name) @@ -81,14 +81,14 @@ private[chisel] trait HasId { } private var _ref: Option[Arg] = None - private[chisel] def setRef(imm: Arg): Unit = _ref = Some(imm) - private[chisel] def setRef(parent: HasId, name: String): Unit = setRef(Slot(Node(parent), name)) - private[chisel] def setRef(parent: HasId, index: Int): Unit = setRef(Index(Node(parent), ILit(index))) - private[chisel] def setRef(parent: HasId, index: UInt): Unit = setRef(Index(Node(parent), index.ref)) - private[chisel] def getRef: Arg = _ref.get + private[chisel3] def setRef(imm: Arg): Unit = _ref = Some(imm) + private[chisel3] def setRef(parent: HasId, name: String): Unit = setRef(Slot(Node(parent), name)) + private[chisel3] def setRef(parent: HasId, index: Int): Unit = setRef(Index(Node(parent), ILit(index))) + private[chisel3] def setRef(parent: HasId, index: UInt): Unit = setRef(Index(Node(parent), index.ref)) + private[chisel3] def getRef: Arg = _ref.get } -private[chisel] class DynamicContext { +private[chisel3] class DynamicContext { val idGen = new IdGen val globalNamespace = new Namespace(None, Set()) val components = ArrayBuffer[Component]() @@ -96,7 +96,7 @@ private[chisel] class DynamicContext { val errors = new ErrorLog } -private[chisel] object Builder { +private[chisel3] object Builder { // All global mutable state must be referenced via dynamicContextVar!! private val dynamicContextVar = new DynamicVariable[Option[DynamicContext]](None) diff --git a/chiselFrontend/src/main/scala/chisel3/internal/Error.scala b/chiselFrontend/src/main/scala/chisel3/internal/Error.scala index f0481dc4..7ae0580f 100644 --- a/chiselFrontend/src/main/scala/chisel3/internal/Error.scala +++ b/chiselFrontend/src/main/scala/chisel3/internal/Error.scala @@ -1,20 +1,20 @@ // See LICENSE for license details. -package chisel.internal +package chisel3.internal import scala.collection.mutable.ArrayBuffer -import chisel.core._ +import chisel3.core._ class ChiselException(message: String, cause: Throwable) extends Exception(message, cause) -private[chisel] object throwException { +private[chisel3] object throwException { def apply(s: String, t: Throwable = null): Nothing = throw new ChiselException(s, t) } /** Records and reports runtime errors and warnings. */ -private[chisel] class ErrorLog { +private[chisel3] class ErrorLog { def hasErrors: Boolean = errors.exists(_.isFatal) /** Log an error message */ diff --git a/chiselFrontend/src/main/scala/chisel3/internal/SourceInfo.scala b/chiselFrontend/src/main/scala/chisel3/internal/SourceInfo.scala index c20bd130..5e3bf33e 100644 --- a/chiselFrontend/src/main/scala/chisel3/internal/SourceInfo.scala +++ b/chiselFrontend/src/main/scala/chisel3/internal/SourceInfo.scala @@ -12,7 +12,7 @@ // writers to append source locator information at the point of a library // function invocation. -package chisel.internal.sourceinfo +package chisel3.internal.sourceinfo import scala.language.experimental.macros import scala.reflect.macros.blackbox.Context @@ -42,7 +42,7 @@ 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})" + q"_root_.chisel3.internal.sourceinfo.SourceLine(${p.source.file.name}, ${p.line}, ${p.column})" } } diff --git a/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala b/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala index 70e9938b..64d7d5fd 100644 --- a/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala +++ b/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala @@ -1,11 +1,11 @@ // See LICENSE for license details. -package chisel.internal.firrtl +package chisel3.internal.firrtl -import chisel._ +import chisel3._ import core._ -import chisel.internal._ -import chisel.internal.sourceinfo.{SourceInfo, NoSourceInfo} +import chisel3.internal._ +import chisel3.internal.sourceinfo.{SourceInfo, NoSourceInfo} case class PrimOp(val name: String) { override def toString: String = name @@ -55,8 +55,8 @@ case class Node(id: HasId) extends Arg { } abstract class LitArg(val num: BigInt, widthArg: Width) extends Arg { - private[chisel] def forcedWidth = widthArg.known - private[chisel] def width: Width = if (forcedWidth) widthArg else Width(minWidth) + private[chisel3] def forcedWidth = widthArg.known + private[chisel3] def width: Width = if (forcedWidth) widthArg else Width(minWidth) protected def minWidth: Int if (forcedWidth) { diff --git a/coreMacros/src/main/scala/chisel3/internal/sourceinfo/SourceInfoTransform.scala b/coreMacros/src/main/scala/chisel3/internal/sourceinfo/SourceInfoTransform.scala index 10b677b6..ba14b78f 100644 --- a/coreMacros/src/main/scala/chisel3/internal/sourceinfo/SourceInfoTransform.scala +++ b/coreMacros/src/main/scala/chisel3/internal/sourceinfo/SourceInfoTransform.scala @@ -3,7 +3,7 @@ // This file transform macro definitions to explicitly add implicit source info to Chisel method // calls. -package chisel.internal.sourceinfo +package chisel3.internal.sourceinfo import scala.language.experimental.macros import scala.reflect.macros.blackbox.Context @@ -23,7 +23,7 @@ trait SourceInfoTransformMacro { val c: Context import c.universe._ def thisObj = c.prefix.tree - def implicitSourceInfo = q"implicitly[_root_.chisel.internal.sourceinfo.SourceInfo]" + def implicitSourceInfo = q"implicitly[_root_.chisel3.internal.sourceinfo.SourceInfo]" } class WireTransform(val c: Context) extends SourceInfoTransformMacro { diff --git a/src/main/scala/chisel3/Driver.scala b/src/main/scala/chisel3/Driver.scala index ba2b1389..92e948cc 100644 --- a/src/main/scala/chisel3/Driver.scala +++ b/src/main/scala/chisel3/Driver.scala @@ -1,6 +1,6 @@ // See LICENSE for license details. -package chisel +package chisel3 import scala.sys.process._ import java.io._ diff --git a/src/main/scala/chisel3/compatibility.scala b/src/main/scala/chisel3/compatibility.scala index 56088562..139e9431 100644 --- a/src/main/scala/chisel3/compatibility.scala +++ b/src/main/scala/chisel3/compatibility.scala @@ -1,150 +1,150 @@ // See LICENSE for license details. // Allows legacy users to continue using Chisel (capital C) package name while -// moving to the more standard package naming convention chisel (lowercase c). +// moving to the more standard package naming convention chisel3 (lowercase c). package object Chisel { - type Direction = chisel.core.Direction - val INPUT = chisel.core.INPUT - val OUTPUT = chisel.core.OUTPUT - val NO_DIR = chisel.core.NO_DIR - - type Flipped = chisel.core.Flipped - type Data = chisel.core.Data - val Wire = chisel.core.Wire - val Clock = chisel.core.Clock - type Clock = chisel.core.Clock - - type Aggregate = chisel.core.Aggregate - val Vec = chisel.core.Vec - type Vec[T <: Data] = chisel.core.Vec[T] - type VecLike[T <: Data] = chisel.core.VecLike[T] - type Bundle = chisel.core.Bundle - - val assert = chisel.core.assert - - type Element = chisel.core.Element - type Bits = chisel.core.Bits - val Bits = chisel.core.Bits - type Num[T <: Data] = chisel.core.Num[T] - type UInt = chisel.core.UInt - val UInt = chisel.core.UInt - type SInt = chisel.core.SInt - val SInt = chisel.core.SInt - type Bool = chisel.core.Bool - val Bool = chisel.core.Bool - val Mux = chisel.core.Mux - - type BlackBox = chisel.core.BlackBox - - val Mem = chisel.core.Mem - type MemBase[T <: Data] = chisel.core.MemBase[T] - type Mem[T <: Data] = chisel.core.Mem[T] - val SeqMem = chisel.core.SeqMem - type SeqMem[T <: Data] = chisel.core.SeqMem[T] - - val Module = chisel.core.Module - type Module = chisel.core.Module - - val printf = chisel.core.printf - - val Reg = chisel.core.Reg - - val when = chisel.core.when - type WhenContext = chisel.core.WhenContext - - - type BackendCompilationUtilities = chisel.BackendCompilationUtilities - val Driver = chisel.Driver - type FileSystemUtilities = chisel.compatibility.FileSystemUtilities - val ImplicitConversions = chisel.util.ImplicitConversions - val chiselMain = chisel.compatibility.chiselMain - val throwException = chisel.compatibility.throwException - val debug = chisel.compatibility.debug + type Direction = chisel3.core.Direction + val INPUT = chisel3.core.INPUT + val OUTPUT = chisel3.core.OUTPUT + val NO_DIR = chisel3.core.NO_DIR + + type Flipped = chisel3.core.Flipped + type Data = chisel3.core.Data + val Wire = chisel3.core.Wire + val Clock = chisel3.core.Clock + type Clock = chisel3.core.Clock + + type Aggregate = chisel3.core.Aggregate + val Vec = chisel3.core.Vec + type Vec[T <: Data] = chisel3.core.Vec[T] + type VecLike[T <: Data] = chisel3.core.VecLike[T] + type Bundle = chisel3.core.Bundle + + val assert = chisel3.core.assert + + type Element = chisel3.core.Element + type Bits = chisel3.core.Bits + val Bits = chisel3.core.Bits + type Num[T <: Data] = chisel3.core.Num[T] + type UInt = chisel3.core.UInt + val UInt = chisel3.core.UInt + type SInt = chisel3.core.SInt + val SInt = chisel3.core.SInt + type Bool = chisel3.core.Bool + val Bool = chisel3.core.Bool + val Mux = chisel3.core.Mux + + type BlackBox = chisel3.core.BlackBox + + val Mem = chisel3.core.Mem + type MemBase[T <: Data] = chisel3.core.MemBase[T] + type Mem[T <: Data] = chisel3.core.Mem[T] + val SeqMem = chisel3.core.SeqMem + type SeqMem[T <: Data] = chisel3.core.SeqMem[T] + + val Module = chisel3.core.Module + type Module = chisel3.core.Module + + val printf = chisel3.core.printf + + val Reg = chisel3.core.Reg + + val when = chisel3.core.when + type WhenContext = chisel3.core.WhenContext + + + type BackendCompilationUtilities = chisel3.BackendCompilationUtilities + val Driver = chisel3.Driver + type FileSystemUtilities = chisel3.compatibility.FileSystemUtilities + val ImplicitConversions = chisel3.util.ImplicitConversions + val chiselMain = chisel3.compatibility.chiselMain + val throwException = chisel3.compatibility.throwException + val debug = chisel3.compatibility.debug object testers { - type BasicTester = chisel.testers.BasicTester - val TesterDriver = chisel.testers.TesterDriver + type BasicTester = chisel3.testers.BasicTester + val TesterDriver = chisel3.testers.TesterDriver } - val log2Up = chisel.util.log2Up - val log2Ceil = chisel.util.log2Ceil - val log2Down = chisel.util.log2Down - val log2Floor = chisel.util.log2Floor - val isPow2 = chisel.util.isPow2 - - val BitPat = chisel.util.BitPat - type BitPat = chisel.util.BitPat - - type ArbiterIO[T <: Data] = chisel.util.ArbiterIO[T] - type LockingArbiterLike[T <: Data] = chisel.util.LockingArbiterLike[T] - type LockingRRArbiter[T <: Data] = chisel.util.LockingRRArbiter[T] - type LockingArbiter[T <: Data] = chisel.util.LockingArbiter[T] - type RRArbiter[T <: Data] = chisel.util.RRArbiter[T] - type Arbiter[T <: Data] = chisel.util.Arbiter[T] - - val FillInterleaved = chisel.util.FillInterleaved - val PopCount = chisel.util.PopCount - val Fill = chisel.util.Fill - val Reverse = chisel.util.Reverse - - val Cat = chisel.util.Cat - - val Log2 = chisel.util.Log2 - - val unless = chisel.util.unless - type SwitchContext[T <: Bits] = chisel.util.SwitchContext[T] - val is = chisel.util.is - val switch = chisel.util.switch - - type Counter = chisel.util.Counter - val Counter = chisel.util.Counter - - type DecoupledIO[+T <: Data] = chisel.util.DecoupledIO[T] - val Decoupled = chisel.util.Decoupled - type EnqIO[T <: Data] = chisel.util.EnqIO[T] - type DeqIO[T <: Data] = chisel.util.DeqIO[T] - type DecoupledIOC[+T <: Data] = chisel.util.DecoupledIOC[T] - type QueueIO[T <: Data] = chisel.util.QueueIO[T] - type Queue[T <: Data] = chisel.util.Queue[T] - val Queue = chisel.util.Queue - - val Enum = chisel.util.Enum - - val LFSR16 = chisel.util.LFSR16 - - val ListLookup = chisel.util.ListLookup - val Lookup = chisel.util.Lookup - - val Mux1H = chisel.util.Mux1H - val PriorityMux = chisel.util.PriorityMux - val MuxLookup = chisel.util.MuxLookup - val MuxCase = chisel.util.MuxCase - - val OHToUInt = chisel.util.OHToUInt - val PriorityEncoder = chisel.util.PriorityEncoder - val UIntToOH = chisel.util.UIntToOH - val PriorityEncoderOH = chisel.util.PriorityEncoderOH - - val RegNext = chisel.util.RegNext - val RegInit = chisel.util.RegInit - val RegEnable = chisel.util.RegEnable - val ShiftRegister = chisel.util.ShiftRegister - - type ValidIO[+T <: Data] = chisel.util.ValidIO[T] - val Valid = chisel.util.Valid - val Pipe = chisel.util.Pipe - type Pipe[T <: Data] = chisel.util.Pipe[T] - - - import chisel.internal.firrtl.Width - implicit def fromBigIntToLiteral(x: BigInt): chisel.fromBigIntToLiteral = - new chisel.fromBigIntToLiteral(x) - implicit def fromIntToLiteral(x: Int): chisel.fromIntToLiteral= - new chisel.fromIntToLiteral(x) - implicit def fromStringToLiteral(x: String): chisel.fromStringToLiteral= - new chisel.fromStringToLiteral(x) - implicit def fromBooleanToLiteral(x: Boolean): chisel.fromBooleanToLiteral= - new chisel.fromBooleanToLiteral(x) + val log2Up = chisel3.util.log2Up + val log2Ceil = chisel3.util.log2Ceil + val log2Down = chisel3.util.log2Down + val log2Floor = chisel3.util.log2Floor + val isPow2 = chisel3.util.isPow2 + + val BitPat = chisel3.util.BitPat + type BitPat = chisel3.util.BitPat + + type ArbiterIO[T <: Data] = chisel3.util.ArbiterIO[T] + type LockingArbiterLike[T <: Data] = chisel3.util.LockingArbiterLike[T] + type LockingRRArbiter[T <: Data] = chisel3.util.LockingRRArbiter[T] + type LockingArbiter[T <: Data] = chisel3.util.LockingArbiter[T] + type RRArbiter[T <: Data] = chisel3.util.RRArbiter[T] + type Arbiter[T <: Data] = chisel3.util.Arbiter[T] + + val FillInterleaved = chisel3.util.FillInterleaved + val PopCount = chisel3.util.PopCount + val Fill = chisel3.util.Fill + val Reverse = chisel3.util.Reverse + + val Cat = chisel3.util.Cat + + val Log2 = chisel3.util.Log2 + + val unless = chisel3.util.unless + type SwitchContext[T <: Bits] = chisel3.util.SwitchContext[T] + val is = chisel3.util.is + val switch = chisel3.util.switch + + type Counter = chisel3.util.Counter + val Counter = chisel3.util.Counter + + type DecoupledIO[+T <: Data] = chisel3.util.DecoupledIO[T] + val Decoupled = chisel3.util.Decoupled + type EnqIO[T <: Data] = chisel3.util.EnqIO[T] + type DeqIO[T <: Data] = chisel3.util.DeqIO[T] + type DecoupledIOC[+T <: Data] = chisel3.util.DecoupledIOC[T] + type QueueIO[T <: Data] = chisel3.util.QueueIO[T] + type Queue[T <: Data] = chisel3.util.Queue[T] + val Queue = chisel3.util.Queue + + val Enum = chisel3.util.Enum + + val LFSR16 = chisel3.util.LFSR16 + + val ListLookup = chisel3.util.ListLookup + val Lookup = chisel3.util.Lookup + + val Mux1H = chisel3.util.Mux1H + val PriorityMux = chisel3.util.PriorityMux + val MuxLookup = chisel3.util.MuxLookup + val MuxCase = chisel3.util.MuxCase + + val OHToUInt = chisel3.util.OHToUInt + val PriorityEncoder = chisel3.util.PriorityEncoder + val UIntToOH = chisel3.util.UIntToOH + val PriorityEncoderOH = chisel3.util.PriorityEncoderOH + + val RegNext = chisel3.util.RegNext + val RegInit = chisel3.util.RegInit + val RegEnable = chisel3.util.RegEnable + val ShiftRegister = chisel3.util.ShiftRegister + + type ValidIO[+T <: Data] = chisel3.util.ValidIO[T] + val Valid = chisel3.util.Valid + val Pipe = chisel3.util.Pipe + type Pipe[T <: Data] = chisel3.util.Pipe[T] + + + import chisel3.internal.firrtl.Width + implicit def fromBigIntToLiteral(x: BigInt): chisel3.fromBigIntToLiteral = + new chisel3.fromBigIntToLiteral(x) + implicit def fromIntToLiteral(x: Int): chisel3.fromIntToLiteral= + new chisel3.fromIntToLiteral(x) + implicit def fromStringToLiteral(x: String): chisel3.fromStringToLiteral= + new chisel3.fromStringToLiteral(x) + implicit def fromBooleanToLiteral(x: Boolean): chisel3.fromBooleanToLiteral= + new chisel3.fromBooleanToLiteral(x) } diff --git a/src/main/scala/chisel3/compatibility/FileSystemUtilities.scala b/src/main/scala/chisel3/compatibility/FileSystemUtilities.scala index d12e627d..cd47c731 100644 --- a/src/main/scala/chisel3/compatibility/FileSystemUtilities.scala +++ b/src/main/scala/chisel3/compatibility/FileSystemUtilities.scala @@ -1,8 +1,8 @@ // See LICENSE for license details. -package chisel.compatibility +package chisel3.compatibility -import chisel._ +import chisel3._ @deprecated("FileSystemUtilities doesn't exist in chisel3", "3.0.0") trait FileSystemUtilities { diff --git a/src/main/scala/chisel3/compatibility/Main.scala b/src/main/scala/chisel3/compatibility/Main.scala index 9072bfcf..a41599a3 100644 --- a/src/main/scala/chisel3/compatibility/Main.scala +++ b/src/main/scala/chisel3/compatibility/Main.scala @@ -1,10 +1,10 @@ // See LICENSE for license details. -package chisel.compatibility +package chisel3.compatibility import java.io.File -import chisel._ +import chisel3._ @deprecated("chiselMain doesn't exist in Chisel3", "3.0") object chiselMain { def apply[T <: Module](args: Array[String], gen: () => T): Unit = diff --git a/src/main/scala/chisel3/compatibility/debug.scala b/src/main/scala/chisel3/compatibility/debug.scala index 8850c76b..c3966dae 100644 --- a/src/main/scala/chisel3/compatibility/debug.scala +++ b/src/main/scala/chisel3/compatibility/debug.scala @@ -1,6 +1,6 @@ -package chisel.compatibility +package chisel3.compatibility -import chisel.core._ +import chisel3.core._ @deprecated("debug doesn't do anything in Chisel3 as no pruning happens in the frontend", "chisel3") object debug { // scalastyle:ignore object.name diff --git a/src/main/scala/chisel3/compatibility/throwException.scala b/src/main/scala/chisel3/compatibility/throwException.scala index 3b9fd06e..3e8b33e6 100644 --- a/src/main/scala/chisel3/compatibility/throwException.scala +++ b/src/main/scala/chisel3/compatibility/throwException.scala @@ -1,8 +1,8 @@ // See LICENSE for license details. -package chisel.compatibility +package chisel3.compatibility -import chisel._ +import chisel3._ @deprecated("throwException doesn't exist in Chisel3", "3.0.0") @throws(classOf[Exception]) diff --git a/src/main/scala/chisel3/internal/firrtl/Emitter.scala b/src/main/scala/chisel3/internal/firrtl/Emitter.scala index e48eb226..08646cf9 100644 --- a/src/main/scala/chisel3/internal/firrtl/Emitter.scala +++ b/src/main/scala/chisel3/internal/firrtl/Emitter.scala @@ -1,10 +1,10 @@ // See LICENSE for license details. -package chisel.internal.firrtl -import chisel._ -import chisel.internal.sourceinfo.{NoSourceInfo, SourceLine} +package chisel3.internal.firrtl +import chisel3._ +import chisel3.internal.sourceinfo.{NoSourceInfo, SourceLine} -private[chisel] object Emitter { +private[chisel3] object Emitter { def emit(circuit: Circuit): String = new Emitter(circuit).toString } diff --git a/src/main/scala/chisel3/package.scala b/src/main/scala/chisel3/package.scala index f7ed6b13..0b548683 100644 --- a/src/main/scala/chisel3/package.scala +++ b/src/main/scala/chisel3/package.scala @@ -1,4 +1,4 @@ -package object chisel { +package object chisel3 { import scala.language.experimental.macros import internal.firrtl.Width @@ -6,53 +6,53 @@ package object chisel { import util.BitPat - type Direction = chisel.core.Direction - val INPUT = chisel.core.INPUT - val OUTPUT = chisel.core.OUTPUT - val NO_DIR = chisel.core.NO_DIR - type Flipped = chisel.core.Flipped - type Data = chisel.core.Data - val Wire = chisel.core.Wire - val Clock = chisel.core.Clock - type Clock = chisel.core.Clock - - type Aggregate = chisel.core.Aggregate - val Vec = chisel.core.Vec - type Vec[T <: Data] = chisel.core.Vec[T] - type VecLike[T <: Data] = chisel.core.VecLike[T] - type Bundle = chisel.core.Bundle - - val assert = chisel.core.assert - - type Element = chisel.core.Element - type Bits = chisel.core.Bits - val Bits = chisel.core.Bits - type Num[T <: Data] = chisel.core.Num[T] - type UInt = chisel.core.UInt - val UInt = chisel.core.UInt - type SInt = chisel.core.SInt - val SInt = chisel.core.SInt - type Bool = chisel.core.Bool - val Bool = chisel.core.Bool - val Mux = chisel.core.Mux - - type BlackBox = chisel.core.BlackBox - - val Mem = chisel.core.Mem - type MemBase[T <: Data] = chisel.core.MemBase[T] - type Mem[T <: Data] = chisel.core.Mem[T] - val SeqMem = chisel.core.SeqMem - type SeqMem[T <: Data] = chisel.core.SeqMem[T] - - val Module = chisel.core.Module - type Module = chisel.core.Module - - val printf = chisel.core.printf - - val Reg = chisel.core.Reg - - val when = chisel.core.when - type WhenContext = chisel.core.WhenContext + type Direction = chisel3.core.Direction + val INPUT = chisel3.core.INPUT + val OUTPUT = chisel3.core.OUTPUT + val NO_DIR = chisel3.core.NO_DIR + type Flipped = chisel3.core.Flipped + type Data = chisel3.core.Data + val Wire = chisel3.core.Wire + val Clock = chisel3.core.Clock + type Clock = chisel3.core.Clock + + type Aggregate = chisel3.core.Aggregate + val Vec = chisel3.core.Vec + type Vec[T <: Data] = chisel3.core.Vec[T] + type VecLike[T <: Data] = chisel3.core.VecLike[T] + type Bundle = chisel3.core.Bundle + + val assert = chisel3.core.assert + + type Element = chisel3.core.Element + type Bits = chisel3.core.Bits + val Bits = chisel3.core.Bits + type Num[T <: Data] = chisel3.core.Num[T] + type UInt = chisel3.core.UInt + val UInt = chisel3.core.UInt + type SInt = chisel3.core.SInt + val SInt = chisel3.core.SInt + type Bool = chisel3.core.Bool + val Bool = chisel3.core.Bool + val Mux = chisel3.core.Mux + + type BlackBox = chisel3.core.BlackBox + + val Mem = chisel3.core.Mem + type MemBase[T <: Data] = chisel3.core.MemBase[T] + type Mem[T <: Data] = chisel3.core.Mem[T] + val SeqMem = chisel3.core.SeqMem + type SeqMem[T <: Data] = chisel3.core.SeqMem[T] + + val Module = chisel3.core.Module + type Module = chisel3.core.Module + + val printf = chisel3.core.printf + + val Reg = chisel3.core.Reg + + val when = chisel3.core.when + type WhenContext = chisel3.core.WhenContext implicit class fromBigIntToLiteral(val x: BigInt) extends AnyVal { diff --git a/src/main/scala/chisel3/testers/BasicTester.scala b/src/main/scala/chisel3/testers/BasicTester.scala index 36ff7c52..f91536d5 100644 --- a/src/main/scala/chisel3/testers/BasicTester.scala +++ b/src/main/scala/chisel3/testers/BasicTester.scala @@ -1,7 +1,7 @@ // See LICENSE for license details. -package chisel.testers -import chisel._ +package chisel3.testers +import chisel3._ import scala.language.experimental.macros diff --git a/src/main/scala/chisel3/testers/TesterDriver.scala b/src/main/scala/chisel3/testers/TesterDriver.scala index 5c0275e0..586fa780 100644 --- a/src/main/scala/chisel3/testers/TesterDriver.scala +++ b/src/main/scala/chisel3/testers/TesterDriver.scala @@ -1,8 +1,8 @@ // See LICENSE for license details. -package chisel.testers +package chisel3.testers -import chisel._ +import chisel3._ import scala.io.Source import scala.sys.process._ import java.io._ diff --git a/src/main/scala/chisel3/util/Arbiter.scala b/src/main/scala/chisel3/util/Arbiter.scala index 3723f2a9..eb541977 100644 --- a/src/main/scala/chisel3/util/Arbiter.scala +++ b/src/main/scala/chisel3/util/Arbiter.scala @@ -3,9 +3,9 @@ /** Arbiters in all shapes and sizes. */ -package chisel.util +package chisel3.util -import chisel._ +import chisel3._ /** An I/O bundle for the Arbiter */ class ArbiterIO[T <: Data](gen: T, n: Int) extends Bundle { diff --git a/src/main/scala/chisel3/util/BitPat.scala b/src/main/scala/chisel3/util/BitPat.scala index 13bbe1b0..9eb5cf67 100644 --- a/src/main/scala/chisel3/util/BitPat.scala +++ b/src/main/scala/chisel3/util/BitPat.scala @@ -1,11 +1,11 @@ // See LICENSE for license details. -package chisel.util +package chisel3.util import scala.language.experimental.macros -import chisel._ -import chisel.internal.sourceinfo.{SourceInfo, SourceInfoTransform} +import chisel3._ +import chisel3.internal.sourceinfo.{SourceInfo, SourceInfoTransform} object BitPat { /** Parses a bit pattern string into (bits, mask, width). diff --git a/src/main/scala/chisel3/util/Bitwise.scala b/src/main/scala/chisel3/util/Bitwise.scala index d7d62ea3..ab1ff550 100644 --- a/src/main/scala/chisel3/util/Bitwise.scala +++ b/src/main/scala/chisel3/util/Bitwise.scala @@ -3,10 +3,10 @@ /** Miscellaneous circuit generators operating on bits. */ -package chisel.util +package chisel3.util -import chisel._ -import chisel.core.SeqUtils +import chisel3._ +import chisel3.core.SeqUtils object FillInterleaved { diff --git a/src/main/scala/chisel3/util/Cat.scala b/src/main/scala/chisel3/util/Cat.scala index b47da706..469bf9ab 100644 --- a/src/main/scala/chisel3/util/Cat.scala +++ b/src/main/scala/chisel3/util/Cat.scala @@ -1,9 +1,9 @@ // See LICENSE for license details. -package chisel.util +package chisel3.util -import chisel._ -import chisel.core.SeqUtils +import chisel3._ +import chisel3.core.SeqUtils object Cat { /** Combine data elements together diff --git a/src/main/scala/chisel3/util/CircuitMath.scala b/src/main/scala/chisel3/util/CircuitMath.scala index c3b94fdb..1174c71c 100644 --- a/src/main/scala/chisel3/util/CircuitMath.scala +++ b/src/main/scala/chisel3/util/CircuitMath.scala @@ -3,9 +3,9 @@ /** Circuit-land math operations. */ -package chisel.util +package chisel3.util -import chisel._ +import chisel3._ /** Compute Log2 with truncation of a UInt in hardware using a Mux Tree * An alternative interpretation is it computes the minimum number of bits needed to represent x diff --git a/src/main/scala/chisel3/util/Conditional.scala b/src/main/scala/chisel3/util/Conditional.scala index 01c12799..6218feb0 100644 --- a/src/main/scala/chisel3/util/Conditional.scala +++ b/src/main/scala/chisel3/util/Conditional.scala @@ -3,14 +3,14 @@ /** Conditional blocks. */ -package chisel.util +package chisel3.util import scala.language.reflectiveCalls import scala.language.experimental.macros import scala.reflect.runtime.universe._ import scala.reflect.macros.blackbox._ -import chisel._ +import chisel3._ /** This is identical to [[Chisel.when when]] with the condition inverted */ object unless { // scalastyle:ignore object.name @@ -63,7 +63,7 @@ object switch { // scalastyle:ignore object.name def extractIsStatement(tree: Tree): List[c.universe.Tree] = tree match { // TODO: remove when Chisel compatibility package is removed case q"Chisel.`package`.is.apply( ..$params )( ..$body )" => List(q"$sc.is( ..$params )( ..$body )") - case q"chisel.util.is.apply( ..$params )( ..$body )" => List(q"$sc.is( ..$params )( ..$body )") + case q"chisel3.util.is.apply( ..$params )( ..$body )" => List(q"$sc.is( ..$params )( ..$body )") case b => throw new Exception(s"Cannot include blocks that do not begin with is() in switch.") } val q"..$body" = x diff --git a/src/main/scala/chisel3/util/Counter.scala b/src/main/scala/chisel3/util/Counter.scala index 1c0b0203..40615769 100644 --- a/src/main/scala/chisel3/util/Counter.scala +++ b/src/main/scala/chisel3/util/Counter.scala @@ -1,8 +1,8 @@ // See LICENSE for license details. -package chisel.util +package chisel3.util -import chisel._ +import chisel3._ /** A counter module * @param n number of counts before the counter resets (or one more than the diff --git a/src/main/scala/chisel3/util/Decoupled.scala b/src/main/scala/chisel3/util/Decoupled.scala index 89b0e39d..f37a5c31 100644 --- a/src/main/scala/chisel3/util/Decoupled.scala +++ b/src/main/scala/chisel3/util/Decoupled.scala @@ -3,9 +3,9 @@ /** Wrappers for ready-valid (Decoupled) interfaces and associated circuit generators using them. */ -package chisel.util +package chisel3.util -import chisel._ +import chisel3._ /** An I/O Bundle with simple handshaking using valid and ready signals for data 'bits'*/ class DecoupledIO[+T <: Data](gen: T) extends Bundle diff --git a/src/main/scala/chisel3/util/Enum.scala b/src/main/scala/chisel3/util/Enum.scala index 8babcd23..4ecc243b 100644 --- a/src/main/scala/chisel3/util/Enum.scala +++ b/src/main/scala/chisel3/util/Enum.scala @@ -3,9 +3,9 @@ /** Enum generators, allowing circuit constants to have more meaningful names. */ -package chisel.util +package chisel3.util -import chisel._ +import chisel3._ object Enum { /** Returns a sequence of Bits subtypes with values from 0 until n. Helper method. */ diff --git a/src/main/scala/chisel3/util/ImplicitConversions.scala b/src/main/scala/chisel3/util/ImplicitConversions.scala index 846c0cbd..4d816a19 100644 --- a/src/main/scala/chisel3/util/ImplicitConversions.scala +++ b/src/main/scala/chisel3/util/ImplicitConversions.scala @@ -1,8 +1,8 @@ // See LICENSE for license details. -package chisel.util +package chisel3.util -import chisel._ +import chisel3._ object ImplicitConversions { implicit def intToUInt(x: Int): UInt = UInt(x) diff --git a/src/main/scala/chisel3/util/LFSR.scala b/src/main/scala/chisel3/util/LFSR.scala index f70630bf..a30c276f 100644 --- a/src/main/scala/chisel3/util/LFSR.scala +++ b/src/main/scala/chisel3/util/LFSR.scala @@ -3,9 +3,9 @@ /** LFSRs in all shapes and sizes. */ -package chisel.util +package chisel3.util -import chisel._ +import chisel3._ // scalastyle:off magic.number /** linear feedback shift register diff --git a/src/main/scala/chisel3/util/Lookup.scala b/src/main/scala/chisel3/util/Lookup.scala index d32d9aec..9e909c0c 100644 --- a/src/main/scala/chisel3/util/Lookup.scala +++ b/src/main/scala/chisel3/util/Lookup.scala @@ -1,8 +1,8 @@ // See LICENSE for license details. -package chisel.util +package chisel3.util -import chisel._ +import chisel3._ object ListLookup { def apply[T <: Data](addr: UInt, default: List[T], mapping: Array[(BitPat, List[T])]): List[T] = { diff --git a/src/main/scala/chisel3/util/Math.scala b/src/main/scala/chisel3/util/Math.scala index 69464d15..73665f0f 100644 --- a/src/main/scala/chisel3/util/Math.scala +++ b/src/main/scala/chisel3/util/Math.scala @@ -3,9 +3,9 @@ /** Scala-land math helper functions, like logs. */ -package chisel.util +package chisel3.util -import chisel._ +import chisel3._ /** Compute the log2 rounded up with min value of 1 */ object log2Up { diff --git a/src/main/scala/chisel3/util/Mux.scala b/src/main/scala/chisel3/util/Mux.scala index 6f074a7e..07a34f9b 100644 --- a/src/main/scala/chisel3/util/Mux.scala +++ b/src/main/scala/chisel3/util/Mux.scala @@ -3,10 +3,10 @@ /** Mux circuit generators. */ -package chisel.util +package chisel3.util -import chisel._ -import chisel.core.SeqUtils +import chisel3._ +import chisel3.core.SeqUtils /** Builds a Mux tree out of the input signal vector using a one hot encoded select signal. Returns the output of the Mux tree. diff --git a/src/main/scala/chisel3/util/OneHot.scala b/src/main/scala/chisel3/util/OneHot.scala index ef21c65d..820c72d6 100644 --- a/src/main/scala/chisel3/util/OneHot.scala +++ b/src/main/scala/chisel3/util/OneHot.scala @@ -3,9 +3,9 @@ /** Circuit generators for working with one-hot representations. */ -package chisel.util +package chisel3.util -import chisel._ +import chisel3._ /** Converts from One Hot Encoding to a UInt indicating which bit is active * This is the inverse of [[Chisel.UIntToOH UIntToOH]]*/ diff --git a/src/main/scala/chisel3/util/Reg.scala b/src/main/scala/chisel3/util/Reg.scala index 1b40646d..81de4754 100644 --- a/src/main/scala/chisel3/util/Reg.scala +++ b/src/main/scala/chisel3/util/Reg.scala @@ -3,9 +3,9 @@ /** Variations and helpers for registers. */ -package chisel.util +package chisel3.util -import chisel._ +import chisel3._ object RegNext { diff --git a/src/main/scala/chisel3/util/TransitName.scala b/src/main/scala/chisel3/util/TransitName.scala index 04e1995b..f36f926f 100644 --- a/src/main/scala/chisel3/util/TransitName.scala +++ b/src/main/scala/chisel3/util/TransitName.scala @@ -1,6 +1,6 @@ -package chisel.util +package chisel3.util -import chisel._ +import chisel3._ import internal.HasId object TransitName { diff --git a/src/main/scala/chisel3/util/Valid.scala b/src/main/scala/chisel3/util/Valid.scala index 56ac9abb..78187ff6 100644 --- a/src/main/scala/chisel3/util/Valid.scala +++ b/src/main/scala/chisel3/util/Valid.scala @@ -3,9 +3,9 @@ /** Wrappers for valid interfaces and associated circuit generators using them. */ -package chisel.util +package chisel3.util -import chisel._ +import chisel3._ /** An I/O Bundle containing data and a signal determining if it is valid */ class ValidIO[+T <: Data](gen2: T) extends Bundle diff --git a/src/test/scala/chiselTests/Assert.scala b/src/test/scala/chiselTests/Assert.scala index eb8617b2..3fed2bd4 100644 --- a/src/test/scala/chiselTests/Assert.scala +++ b/src/test/scala/chiselTests/Assert.scala @@ -3,9 +3,9 @@ package chiselTests import org.scalatest._ -import chisel._ -import chisel.testers.BasicTester -import chisel.util._ +import chisel3._ +import chisel3.testers.BasicTester +import chisel3.util._ class FailingAssertTester() extends BasicTester { assert(Bool(false)) diff --git a/src/test/scala/chiselTests/BitwiseOps.scala b/src/test/scala/chiselTests/BitwiseOps.scala index 0c1d4d74..08999a1b 100644 --- a/src/test/scala/chiselTests/BitwiseOps.scala +++ b/src/test/scala/chiselTests/BitwiseOps.scala @@ -2,10 +2,10 @@ package chiselTests -import chisel._ +import chisel3._ import org.scalatest._ import org.scalatest.prop._ -import chisel.testers.BasicTester +import chisel3.testers.BasicTester class BitwiseOpsTester(w: Int, _a: Int, _b: Int) extends BasicTester { val mask = (1 << w) - 1 diff --git a/src/test/scala/chiselTests/BlackBox.scala b/src/test/scala/chiselTests/BlackBox.scala index b77550c1..fdc5970e 100644 --- a/src/test/scala/chiselTests/BlackBox.scala +++ b/src/test/scala/chiselTests/BlackBox.scala @@ -5,9 +5,9 @@ package chiselTests import java.io.File import org.scalatest._ -import chisel._ -import chisel.testers.BasicTester -import chisel.util._ +import chisel3._ +import chisel3.testers.BasicTester +import chisel3.util._ class BlackBoxInverter extends BlackBox { val io = new Bundle() { diff --git a/src/test/scala/chiselTests/BundleWire.scala b/src/test/scala/chiselTests/BundleWire.scala index 36dbb365..e5e9fb1a 100644 --- a/src/test/scala/chiselTests/BundleWire.scala +++ b/src/test/scala/chiselTests/BundleWire.scala @@ -1,10 +1,10 @@ // See LICENSE for license details. package chiselTests -import chisel._ +import chisel3._ import org.scalatest._ import org.scalatest.prop._ -import chisel.testers.BasicTester +import chisel3.testers.BasicTester class Coord extends Bundle { val x = UInt(width = 32) diff --git a/src/test/scala/chiselTests/ChiselSpec.scala b/src/test/scala/chiselTests/ChiselSpec.scala index 9c66b0db..d335bdf6 100644 --- a/src/test/scala/chiselTests/ChiselSpec.scala +++ b/src/test/scala/chiselTests/ChiselSpec.scala @@ -6,8 +6,8 @@ import java.io.File import org.scalatest._ import org.scalatest.prop._ import org.scalacheck._ -import chisel._ -import chisel.testers._ +import chisel3._ +import chisel3.testers._ /** Common utility functions for Chisel unit tests. */ trait ChiselRunners extends Assertions { diff --git a/src/test/scala/chiselTests/ComplexAssign.scala b/src/test/scala/chiselTests/ComplexAssign.scala index 53a6a67d..304fbcf5 100644 --- a/src/test/scala/chiselTests/ComplexAssign.scala +++ b/src/test/scala/chiselTests/ComplexAssign.scala @@ -5,9 +5,9 @@ package chiselTests import org.scalatest._ import org.scalatest.prop._ -import chisel._ -import chisel.testers.BasicTester -import chisel.util._ +import chisel3._ +import chisel3.testers.BasicTester +import chisel3.util._ class Complex[T <: Data](val re: T, val im: T) extends Bundle { override def cloneType: this.type = diff --git a/src/test/scala/chiselTests/Counter.scala b/src/test/scala/chiselTests/Counter.scala index 963c1c92..69d8a44a 100644 --- a/src/test/scala/chiselTests/Counter.scala +++ b/src/test/scala/chiselTests/Counter.scala @@ -5,9 +5,9 @@ package chiselTests import org.scalatest._ import org.scalatest.prop._ -import chisel._ -import chisel.testers.BasicTester -import chisel.util._ +import chisel3._ +import chisel3.testers.BasicTester +import chisel3.util._ class CountTester(max: Int) extends BasicTester { val cnt = Counter(max) diff --git a/src/test/scala/chiselTests/Decoder.scala b/src/test/scala/chiselTests/Decoder.scala index 33980955..5586561b 100644 --- a/src/test/scala/chiselTests/Decoder.scala +++ b/src/test/scala/chiselTests/Decoder.scala @@ -6,9 +6,9 @@ import org.scalatest._ import org.scalatest.prop._ import org.scalacheck._ -import chisel._ -import chisel.testers.BasicTester -import chisel.util._ +import chisel3._ +import chisel3.testers.BasicTester +import chisel3.util._ class Decoder(bitpats: List[String]) extends Module { val io = new Bundle { diff --git a/src/test/scala/chiselTests/DeqIOSpec.scala b/src/test/scala/chiselTests/DeqIOSpec.scala index 95160140..09891647 100644 --- a/src/test/scala/chiselTests/DeqIOSpec.scala +++ b/src/test/scala/chiselTests/DeqIOSpec.scala @@ -2,9 +2,9 @@ package chiselTests -import chisel._ -import chisel.testers.BasicTester -import chisel.util._ +import chisel3._ +import chisel3.testers.BasicTester +import chisel3.util._ /** * Created by chick on 2/8/16. diff --git a/src/test/scala/chiselTests/Direction.scala b/src/test/scala/chiselTests/Direction.scala index 3ed543aa..8b84f844 100644 --- a/src/test/scala/chiselTests/Direction.scala +++ b/src/test/scala/chiselTests/Direction.scala @@ -2,10 +2,10 @@ package chiselTests -import chisel._ +import chisel3._ import org.scalatest._ import org.scalatest.prop._ -import chisel.testers.BasicTester +import chisel3.testers.BasicTester class DirectionHaver extends Module { val io = new Bundle { diff --git a/src/test/scala/chiselTests/EnableShiftRegister.scala b/src/test/scala/chiselTests/EnableShiftRegister.scala index 30fc2486..7db20fc1 100644 --- a/src/test/scala/chiselTests/EnableShiftRegister.scala +++ b/src/test/scala/chiselTests/EnableShiftRegister.scala @@ -1,8 +1,8 @@ // See LICENSE for license details. package chiselTests -import chisel._ -import chisel.testers.BasicTester +import chisel3._ +import chisel3.testers.BasicTester class EnableShiftRegister extends Module { val io = new Bundle { diff --git a/src/test/scala/chiselTests/GCD.scala b/src/test/scala/chiselTests/GCD.scala index 77452db6..60a70cc8 100644 --- a/src/test/scala/chiselTests/GCD.scala +++ b/src/test/scala/chiselTests/GCD.scala @@ -2,8 +2,8 @@ package chiselTests -import chisel._ -import chisel.testers.BasicTester +import chisel3._ +import chisel3.testers.BasicTester import org.scalatest._ import org.scalatest.prop._ diff --git a/src/test/scala/chiselTests/Harness.scala b/src/test/scala/chiselTests/Harness.scala index 805e2de9..83f60391 100644 --- a/src/test/scala/chiselTests/Harness.scala +++ b/src/test/scala/chiselTests/Harness.scala @@ -2,13 +2,13 @@ package chiselTests -import chisel.testers.BasicTester +import chisel3.testers.BasicTester import org.scalatest._ import org.scalatest.prop._ import java.io.File class HarnessSpec extends ChiselPropSpec - with chisel.BackendCompilationUtilities { + with chisel3.BackendCompilationUtilities { def makeTrivialVerilog: (File => File) = makeHarness((prefix: String) => s""" module ${prefix}; diff --git a/src/test/scala/chiselTests/LFSR16.scala b/src/test/scala/chiselTests/LFSR16.scala index b3e69884..a1699441 100644 --- a/src/test/scala/chiselTests/LFSR16.scala +++ b/src/test/scala/chiselTests/LFSR16.scala @@ -2,9 +2,9 @@ package chiselTests -import chisel._ -import chisel.testers.BasicTester -import chisel.util._ +import chisel3._ +import chisel3.testers.BasicTester +import chisel3.util._ class LFSR16 extends Module { val io = new Bundle { @@ -36,7 +36,7 @@ class LFSR16Tester(c: LFSR16) extends Tester(c) { } */ -//TODO: Use chisel.util version instead? +//TODO: Use chisel3.util version instead? class LFSRSpec extends ChiselPropSpec { diff --git a/src/test/scala/chiselTests/MemorySearch.scala b/src/test/scala/chiselTests/MemorySearch.scala index b48d2881..679b894c 100644 --- a/src/test/scala/chiselTests/MemorySearch.scala +++ b/src/test/scala/chiselTests/MemorySearch.scala @@ -2,8 +2,8 @@ package chiselTests -import chisel._ -import chisel.testers.BasicTester +import chisel3._ +import chisel3.testers.BasicTester class MemorySearch extends Module { val io = new Bundle { diff --git a/src/test/scala/chiselTests/Module.scala b/src/test/scala/chiselTests/Module.scala index 64b00fab..23788b72 100644 --- a/src/test/scala/chiselTests/Module.scala +++ b/src/test/scala/chiselTests/Module.scala @@ -2,7 +2,7 @@ package chiselTests -import chisel._ +import chisel3._ class SimpleIO extends Bundle { val in = UInt(INPUT, 32) diff --git a/src/test/scala/chiselTests/MulLookup.scala b/src/test/scala/chiselTests/MulLookup.scala index 5e223f91..831e323f 100644 --- a/src/test/scala/chiselTests/MulLookup.scala +++ b/src/test/scala/chiselTests/MulLookup.scala @@ -2,10 +2,10 @@ package chiselTests -import chisel._ +import chisel3._ import org.scalatest._ import org.scalatest.prop._ -import chisel.testers.BasicTester +import chisel3.testers.BasicTester class MulLookup(val w: Int) extends Module { val io = new Bundle { diff --git a/src/test/scala/chiselTests/MultiAssign.scala b/src/test/scala/chiselTests/MultiAssign.scala index 152e6723..c22a5e30 100644 --- a/src/test/scala/chiselTests/MultiAssign.scala +++ b/src/test/scala/chiselTests/MultiAssign.scala @@ -4,9 +4,9 @@ package chiselTests import org.scalatest._ -import chisel._ -import chisel.testers.BasicTester -import chisel.util._ +import chisel3._ +import chisel3.testers.BasicTester +import chisel3.util._ class LastAssignTester() extends BasicTester { val cnt = Counter(2) diff --git a/src/test/scala/chiselTests/OptionBundle.scala b/src/test/scala/chiselTests/OptionBundle.scala index ab3b6860..fa691b43 100644 --- a/src/test/scala/chiselTests/OptionBundle.scala +++ b/src/test/scala/chiselTests/OptionBundle.scala @@ -3,8 +3,8 @@ package chiselTests import org.scalatest._ -import chisel._ -import chisel.testers.BasicTester +import chisel3._ +import chisel3.testers.BasicTester class OptionBundle(hasIn: Boolean) extends Bundle { val in = if (hasIn) { diff --git a/src/test/scala/chiselTests/Padding.scala b/src/test/scala/chiselTests/Padding.scala index 03496649..3fb0f955 100644 --- a/src/test/scala/chiselTests/Padding.scala +++ b/src/test/scala/chiselTests/Padding.scala @@ -2,7 +2,7 @@ package chiselTests -import chisel._ +import chisel3._ class Padder extends Module { val io = new Bundle { diff --git a/src/test/scala/chiselTests/ParameterizedModule.scala b/src/test/scala/chiselTests/ParameterizedModule.scala index e2629224..4859759e 100644 --- a/src/test/scala/chiselTests/ParameterizedModule.scala +++ b/src/test/scala/chiselTests/ParameterizedModule.scala @@ -3,8 +3,8 @@ package chiselTests import org.scalatest._ -import chisel._ -import chisel.testers.BasicTester +import chisel3._ +import chisel3.testers.BasicTester class ParameterizedModule(invert: Boolean) extends Module { val io = new Bundle { diff --git a/src/test/scala/chiselTests/Printf.scala b/src/test/scala/chiselTests/Printf.scala index b5e1e66e..c872fde4 100644 --- a/src/test/scala/chiselTests/Printf.scala +++ b/src/test/scala/chiselTests/Printf.scala @@ -3,8 +3,8 @@ package chiselTests import org.scalatest._ -import chisel._ -import chisel.testers.BasicTester +import chisel3._ +import chisel3.testers.BasicTester class SinglePrintfTester() extends BasicTester { val x = UInt(254) diff --git a/src/test/scala/chiselTests/Reg.scala b/src/test/scala/chiselTests/Reg.scala index 8954c3ef..fc2cbf9d 100644 --- a/src/test/scala/chiselTests/Reg.scala +++ b/src/test/scala/chiselTests/Reg.scala @@ -3,8 +3,8 @@ package chiselTests import org.scalatest._ -import chisel._ -import chisel.testers.BasicTester +import chisel3._ +import chisel3.testers.BasicTester class RegSpec extends ChiselFlatSpec { "A Reg" should "throw an exception if not given any parameters" in { diff --git a/src/test/scala/chiselTests/Risc.scala b/src/test/scala/chiselTests/Risc.scala index 741e9896..f5e61115 100644 --- a/src/test/scala/chiselTests/Risc.scala +++ b/src/test/scala/chiselTests/Risc.scala @@ -2,8 +2,8 @@ package chiselTests -import chisel._ -import chisel.util._ +import chisel3._ +import chisel3.util._ class Risc extends Module { val io = new Bundle { diff --git a/src/test/scala/chiselTests/SIntOps.scala b/src/test/scala/chiselTests/SIntOps.scala index 07111af6..6cd013f1 100644 --- a/src/test/scala/chiselTests/SIntOps.scala +++ b/src/test/scala/chiselTests/SIntOps.scala @@ -2,8 +2,8 @@ package chiselTests -import chisel._ -import chisel.testers.BasicTester +import chisel3._ +import chisel3.testers.BasicTester class SIntOps extends Module { val io = new Bundle { diff --git a/src/test/scala/chiselTests/Stack.scala b/src/test/scala/chiselTests/Stack.scala index 0ce228de..cbd9f3e3 100644 --- a/src/test/scala/chiselTests/Stack.scala +++ b/src/test/scala/chiselTests/Stack.scala @@ -4,8 +4,8 @@ package chiselTests import scala.collection.mutable.Stack -import chisel._ -import chisel.util._ +import chisel3._ +import chisel3.util._ class ChiselStack(val depth: Int) extends Module { val io = new Bundle { diff --git a/src/test/scala/chiselTests/Stop.scala b/src/test/scala/chiselTests/Stop.scala index d57eb7c6..4afb077a 100644 --- a/src/test/scala/chiselTests/Stop.scala +++ b/src/test/scala/chiselTests/Stop.scala @@ -3,8 +3,8 @@ package chiselTests import org.scalatest._ -import chisel._ -import chisel.testers.BasicTester +import chisel3._ +import chisel3.testers.BasicTester class StopTester() extends BasicTester { stop() diff --git a/src/test/scala/chiselTests/Tbl.scala b/src/test/scala/chiselTests/Tbl.scala index 2049d8bb..d84cd85e 100644 --- a/src/test/scala/chiselTests/Tbl.scala +++ b/src/test/scala/chiselTests/Tbl.scala @@ -5,9 +5,9 @@ package chiselTests import org.scalatest._ import org.scalatest.prop._ -import chisel._ -import chisel.testers.BasicTester -import chisel.util._ +import chisel3._ +import chisel3.testers.BasicTester +import chisel3.util._ class Tbl(w: Int, n: Int) extends Module { val io = new Bundle { diff --git a/src/test/scala/chiselTests/TesterDriverSpec.scala b/src/test/scala/chiselTests/TesterDriverSpec.scala index 50290fab..2f3e9368 100644 --- a/src/test/scala/chiselTests/TesterDriverSpec.scala +++ b/src/test/scala/chiselTests/TesterDriverSpec.scala @@ -2,9 +2,9 @@ package chiselTests -import chisel._ -import chisel.testers.BasicTester -import chisel.util._ +import chisel3._ +import chisel3.testers.BasicTester +import chisel3.util._ /** Extend BasicTester with a simple circuit and finish method. TesterDriver will call the * finish method after the FinishTester's constructor has completed, which will alter the diff --git a/src/test/scala/chiselTests/UIntOps.scala b/src/test/scala/chiselTests/UIntOps.scala index 8b2a31fd..c5069fc4 100644 --- a/src/test/scala/chiselTests/UIntOps.scala +++ b/src/test/scala/chiselTests/UIntOps.scala @@ -2,9 +2,9 @@ package chiselTests -import chisel._ +import chisel3._ import org.scalatest._ -import chisel.testers.BasicTester +import chisel3.testers.BasicTester class UIntOps extends Module { val io = new Bundle { diff --git a/src/test/scala/chiselTests/Vec.scala b/src/test/scala/chiselTests/Vec.scala index 35a0c8bc..7dd80a13 100644 --- a/src/test/scala/chiselTests/Vec.scala +++ b/src/test/scala/chiselTests/Vec.scala @@ -5,9 +5,9 @@ package chiselTests import org.scalatest._ import org.scalatest.prop._ -import chisel._ -import chisel.testers.BasicTester -import chisel.util._ +import chisel3._ +import chisel3.testers.BasicTester +import chisel3.util._ class ValueTester(w: Int, values: List[Int]) extends BasicTester { val v = Vec(values.map(UInt(_, width = w))) // TODO: does this need a Wire? Why no error? diff --git a/src/test/scala/chiselTests/VectorPacketIO.scala b/src/test/scala/chiselTests/VectorPacketIO.scala index a1282071..07779faa 100644 --- a/src/test/scala/chiselTests/VectorPacketIO.scala +++ b/src/test/scala/chiselTests/VectorPacketIO.scala @@ -2,9 +2,9 @@ package chiselTests -import chisel._ -import chisel.testers.BasicTester -import chisel.util._ +import chisel3._ +import chisel3.testers.BasicTester +import chisel3.util._ /** * This test used to fail when assignment statements were diff --git a/src/test/scala/chiselTests/VendingMachine.scala b/src/test/scala/chiselTests/VendingMachine.scala index 0d621e6a..f03cb881 100644 --- a/src/test/scala/chiselTests/VendingMachine.scala +++ b/src/test/scala/chiselTests/VendingMachine.scala @@ -2,8 +2,8 @@ package chiselTests -import chisel._ -import chisel.util._ +import chisel3._ +import chisel3.util._ class VendingMachine extends Module { val io = new Bundle { diff --git a/src/test/scala/chiselTests/When.scala b/src/test/scala/chiselTests/When.scala index 1c9c3bc5..5f3d3e61 100644 --- a/src/test/scala/chiselTests/When.scala +++ b/src/test/scala/chiselTests/When.scala @@ -4,9 +4,9 @@ package chiselTests import org.scalatest._ -import chisel._ -import chisel.testers.BasicTester -import chisel.util._ +import chisel3._ +import chisel3.testers.BasicTester +import chisel3.util._ class WhenTester() extends BasicTester { val cnt = Counter(4) -- cgit v1.2.3 From 077aa80ea61b8517ef13f72d1fa3bec2aaa3063b Mon Sep 17 00:00:00 2001 From: Howard Mao Date: Mon, 20 Jun 2016 13:44:08 -0700 Subject: make sure MuxCase and MuxLookup can take all subclasses of Data (#222) --- src/main/scala/chisel/util/Mux.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/chisel/util/Mux.scala b/src/main/scala/chisel/util/Mux.scala index 6f074a7e..04b174e9 100644 --- a/src/main/scala/chisel/util/Mux.scala +++ b/src/main/scala/chisel/util/Mux.scala @@ -40,7 +40,7 @@ object MuxLookup { * @param mapping a sequence to search of keys and values * @return the value found or the default if not */ - def apply[S <: UInt, T <: Bits] (key: S, default: T, mapping: Seq[(S, T)]): T = { + def apply[S <: UInt, T <: Data] (key: S, default: T, mapping: Seq[(S, T)]): T = { var res = default for ((k, v) <- mapping.reverse) res = Mux(k === key, v, res) @@ -54,7 +54,7 @@ object MuxCase { /** @param default the default value if none are enabled * @param mapping a set of data values with associated enables * @return the first value in mapping that is enabled */ - def apply[T <: Bits] (default: T, mapping: Seq[(Bool, T)]): T = { + def apply[T <: Data] (default: T, mapping: Seq[(Bool, T)]): T = { var res = default for ((t, v) <- mapping.reverse){ res = Mux(t, v, res) -- cgit v1.2.3 From 70a41e5aed5dc3bc52133aecf46049a5946d33fe Mon Sep 17 00:00:00 2001 From: Howard Mao Date: Mon, 20 Jun 2016 16:00:19 -0700 Subject: fix BlackBox setRefs to correctly handle arbitrarily nested bundles as ports (#223) --- chiselFrontend/src/main/scala/chisel/core/BlackBox.scala | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel/core/BlackBox.scala b/chiselFrontend/src/main/scala/chisel/core/BlackBox.scala index 2126ebce..0e4c7a0c 100644 --- a/chiselFrontend/src/main/scala/chisel/core/BlackBox.scala +++ b/chiselFrontend/src/main/scala/chisel/core/BlackBox.scala @@ -28,13 +28,21 @@ abstract class BlackBox extends Module { // Do not do reflective naming of internal signals, just name io override private[core] def setRefs(): this.type = { - for ((name, port) <- ports) { - port.setRef(ModuleIO(this, _namespace.name(name))) - } // setRef is not called on the actual io. // There is a risk of user improperly attempting to connect directly with io // Long term solution will be to define BlackBox IO differently as part of // it not descending from the (current) Module + for ((name, port) <- ports) { + port.setRef(ModuleIO(this, _namespace.name(name))) + } + // We need to call forceName and onModuleClose on all of the sub-elements + // of the io bundle, but NOT on the io bundle itself. + // Doing so would cause the wrong names to be assigned, since their parent + // is now the module itself instead of the io bundle. + for (id <- _ids; if id ne io) { + id.forceName(default="T", _namespace) + id._onModuleClose + } this } -- cgit v1.2.3 From 2e9b41cafe9158f20ecb03ae9eabecb82e557829 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Thu, 23 Jun 2016 12:14:34 -0700 Subject: Expose FIRRTL stop construct --- chiselFrontend/src/main/scala/chisel/core/Assert.scala | 14 ++++++++++++++ src/main/scala/chisel/compatibility.scala | 1 + 2 files changed, 15 insertions(+) diff --git a/chiselFrontend/src/main/scala/chisel/core/Assert.scala b/chiselFrontend/src/main/scala/chisel/core/Assert.scala index 00cb00f4..f665843b 100644 --- a/chiselFrontend/src/main/scala/chisel/core/Assert.scala +++ b/chiselFrontend/src/main/scala/chisel/core/Assert.scala @@ -71,3 +71,17 @@ object assert { // scalastyle:ignore object.name Predef.assert(cond, "") } } + +object stop { // scalastyle:ignore object.name + /** Terminate execution with a failure code. */ + def apply(code: Int)(implicit sourceInfo: SourceInfo): Unit = { + when (!Builder.dynamicContext.currentModule.get.reset) { + pushCommand(Stop(sourceInfo, Node(Builder.dynamicContext.currentModule.get.clock), code)) + } + } + + /** Terminate execution, indicating success. */ + def apply()(implicit sourceInfo: SourceInfo): Unit = { + stop(0) + } +} diff --git a/src/main/scala/chisel/compatibility.scala b/src/main/scala/chisel/compatibility.scala index 56088562..af5daef7 100644 --- a/src/main/scala/chisel/compatibility.scala +++ b/src/main/scala/chisel/compatibility.scala @@ -22,6 +22,7 @@ package object Chisel { type Bundle = chisel.core.Bundle val assert = chisel.core.assert + val stop = chisel.core.stop type Element = chisel.core.Element type Bits = chisel.core.Bits -- cgit v1.2.3 From 3eb51f8484ad21d8a39da1ab7b036f1bb3bbe102 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Mon, 27 Jun 2016 14:04:37 -0700 Subject: Guard firrtl stop, fixing pipelined reset --- src/main/scala/chisel/Driver.scala | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/scala/chisel/Driver.scala b/src/main/scala/chisel/Driver.scala index ba2b1389..8fdc8f65 100644 --- a/src/main/scala/chisel/Driver.scala +++ b/src/main/scala/chisel/Driver.scala @@ -71,6 +71,7 @@ trait BackendCompilationUtilities { "--top-module", topModule, "+define+TOP_TYPE=V" + dutFile, s"+define+PRINTF_COND=!$topModule.reset", + s"+define+STOP_COND=!$topModule.reset", "-CFLAGS", s"""-Wno-undefined-bool-conversion -O2 -DTOP_TYPE=V$dutFile -include V$dutFile.h""", "-Mdir", dir.toString, -- cgit v1.2.3 From 378edecbf797f19cf26f5a4d6a3ed3df701ba66d Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Fri, 1 Jul 2016 11:54:49 -0700 Subject: Reflectively name Module fields declared in superclasses Closes #229 h/t @sdtwigg @davidbiancolin --- chiselFrontend/src/main/scala/chisel3/core/Module.scala | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/Module.scala b/chiselFrontend/src/main/scala/chisel3/core/Module.scala index 7032e762..cde7032d 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Module.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Module.scala @@ -2,7 +2,7 @@ package chisel3.core -import scala.collection.mutable.{ArrayBuffer, HashSet} +import scala.collection.mutable.ArrayBuffer import scala.language.experimental.macros import chisel3.internal._ @@ -96,7 +96,11 @@ extends HasId { } // Suggest names to nodes using runtime reflection - val valNames = HashSet[String](getClass.getDeclaredFields.map(_.getName):_*) + def getValNames(c: Class[_]): Set[String] = { + if (c == classOf[Module]) Set() + else getValNames(c.getSuperclass) ++ c.getDeclaredFields.map(_.getName) + } + val valNames = getValNames(this.getClass) def isPublicVal(m: java.lang.reflect.Method) = m.getParameterTypes.isEmpty && valNames.contains(m.getName) val methods = getClass.getMethods.sortWith(_.getName > _.getName) -- cgit v1.2.3 From fb39f7dc372b5836f02d8d7964f5fcc6a38f8747 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Thu, 7 Jul 2016 00:11:15 -0700 Subject: Avoid needlessly creating Vecs --- src/main/scala/chisel3/util/Bitwise.scala | 2 +- src/main/scala/chisel3/util/OneHot.scala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/chisel3/util/Bitwise.scala b/src/main/scala/chisel3/util/Bitwise.scala index ab1ff550..7f295200 100644 --- a/src/main/scala/chisel3/util/Bitwise.scala +++ b/src/main/scala/chisel3/util/Bitwise.scala @@ -11,7 +11,7 @@ import chisel3.core.SeqUtils object FillInterleaved { def apply(n: Int, in: UInt): UInt = apply(n, in.toBools) - def apply(n: Int, in: Seq[Bool]): UInt = Vec(in.map(Fill(n, _))).toBits + def apply(n: Int, in: Seq[Bool]): UInt = Cat(in.map(Fill(n, _)).reverse) } /** Returns the number of bits set (i.e value is 1) in the input signal. diff --git a/src/main/scala/chisel3/util/OneHot.scala b/src/main/scala/chisel3/util/OneHot.scala index 820c72d6..abede61e 100644 --- a/src/main/scala/chisel3/util/OneHot.scala +++ b/src/main/scala/chisel3/util/OneHot.scala @@ -10,7 +10,7 @@ import chisel3._ /** Converts from One Hot Encoding to a UInt indicating which bit is active * This is the inverse of [[Chisel.UIntToOH UIntToOH]]*/ object OHToUInt { - def apply(in: Seq[Bool]): UInt = apply(Vec(in)) + def apply(in: Seq[Bool]): UInt = apply(Cat(in.reverse), in.size) def apply(in: Vec[Bool]): UInt = apply(in.toBits, in.size) def apply(in: Bits): UInt = apply(in, in.getWidth) -- cgit v1.2.3 From bae5cbbbf64782ffe7a5a06981d94655bfc76089 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Wed, 6 Jul 2016 23:01:42 -0700 Subject: Correct erroneous Log2 documentation --- src/main/scala/chisel3/util/CircuitMath.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/scala/chisel3/util/CircuitMath.scala b/src/main/scala/chisel3/util/CircuitMath.scala index 1174c71c..b5be03bf 100644 --- a/src/main/scala/chisel3/util/CircuitMath.scala +++ b/src/main/scala/chisel3/util/CircuitMath.scala @@ -7,11 +7,11 @@ package chisel3.util import chisel3._ -/** Compute Log2 with truncation of a UInt in hardware using a Mux Tree - * An alternative interpretation is it computes the minimum number of bits needed to represent x +/** Compute the base-2 integer logarithm of a UInt * @example * {{{ data_out := Log2(data_in) }}} - * @note Truncation is used so Log2(UInt(12412)) = 13*/ + * @note The result is truncated, so e.g. Log2(UInt(13)) = 3 + */ object Log2 { /** Compute the Log2 on the least significant n bits of x */ def apply(x: Bits, width: Int): UInt = { -- cgit v1.2.3 From a49e27d1247597de5997f0fe6f3d2ac594ec2e6b Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Thu, 7 Jul 2016 00:37:34 -0700 Subject: Improve Fill code generation --- src/main/scala/chisel3/util/Bitwise.scala | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/main/scala/chisel3/util/Bitwise.scala b/src/main/scala/chisel3/util/Bitwise.scala index 7f295200..3134d043 100644 --- a/src/main/scala/chisel3/util/Bitwise.scala +++ b/src/main/scala/chisel3/util/Bitwise.scala @@ -29,22 +29,17 @@ object Fill { n match { case 0 => UInt(width=0) case 1 => x - case y if n > 1 => + case _ if x.width.known && x.getWidth == 1 => + Mux(x.toBool, UInt((BigInt(1) << n) - 1, n), UInt(0, n)) + case _ if n > 1 => val p2 = Array.ofDim[UInt](log2Up(n + 1)) p2(0) = x for (i <- 1 until p2.length) p2(i) = Cat(p2(i-1), p2(i-1)) - Cat((0 until log2Up(y + 1)).filter(i => (y & (1 << i)) != 0).map(p2(_))) + Cat((0 until log2Up(n + 1)).filter(i => (n & (1 << i)) != 0).map(p2(_))) case _ => throw new IllegalArgumentException(s"n (=$n) must be nonnegative integer.") } } - /** Fan out x n times */ - def apply(n: Int, x: Bool): UInt = - if (n > 1) { - UInt(0,n) - x - } else { - apply(n, x: UInt) - } } /** Litte/big bit endian convertion: reverse the order of the bits in a UInt. -- cgit v1.2.3 From c90be4ea06faf9a39c85f38e932d29fe63eb4b37 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Thu, 7 Jul 2016 15:41:10 -0700 Subject: Improve QoR for Log2 For reasonable circuit delay, need to divide & conquer. --- src/main/scala/chisel3/util/CircuitMath.scala | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/main/scala/chisel3/util/CircuitMath.scala b/src/main/scala/chisel3/util/CircuitMath.scala index b5be03bf..a64447d9 100644 --- a/src/main/scala/chisel3/util/CircuitMath.scala +++ b/src/main/scala/chisel3/util/CircuitMath.scala @@ -19,10 +19,18 @@ object Log2 { UInt(0) } else if (width == 2) { x(1) - } else { + } else if (width <= divideAndConquerThreshold) { Mux(x(width-1), UInt(width-1), apply(x, width-1)) + } else { + val mid = 1 << (log2Ceil(width) - 1) + val hi = x(width-1, mid) + val lo = x(mid-1, 0) + val useHi = hi.orR + Cat(useHi, Mux(useHi, Log2(hi, width - mid), Log2(lo, mid))) } } def apply(x: Bits): UInt = apply(x, x.getWidth) + + private def divideAndConquerThreshold = 4 } -- cgit v1.2.3 From 1b8f84859f2ac2d40085e6c31034dd598a5c6aad Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Thu, 7 Jul 2016 20:12:30 -0700 Subject: Don't check GCD result before sending it a request --- src/test/scala/chiselTests/GCD.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/scala/chiselTests/GCD.scala b/src/test/scala/chiselTests/GCD.scala index 60a70cc8..23df3256 100644 --- a/src/test/scala/chiselTests/GCD.scala +++ b/src/test/scala/chiselTests/GCD.scala @@ -31,7 +31,7 @@ class GCDTester(a: Int, b: Int, z: Int) extends BasicTester { dut.io.b := UInt(b) dut.io.e := first when(first) { first := Bool(false) } - when(dut.io.v) { + when(!first && dut.io.v) { assert(dut.io.z === UInt(z)) stop() } -- cgit v1.2.3 From bb5467fc67d3b8fc6cc2a15f6e681dc45f7cb029 Mon Sep 17 00:00:00 2001 From: Donggyu Date: Mon, 11 Jul 2016 15:17:59 -0700 Subject: bitpat should keep the width of uint (#232) --- src/main/scala/chisel3/util/BitPat.scala | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/scala/chisel3/util/BitPat.scala b/src/main/scala/chisel3/util/BitPat.scala index 9eb5cf67..d476f957 100644 --- a/src/main/scala/chisel3/util/BitPat.scala +++ b/src/main/scala/chisel3/util/BitPat.scala @@ -68,7 +68,8 @@ object BitPat { */ def apply(x: UInt): BitPat = { require(x.isLit) - BitPat("b" + x.litValue.toString(2)) + val len = if (x.width.known) x.getWidth else 0 + apply("b" + x.litValue.toString(2).reverse.padTo(len, "0").reverse.mkString) } } @@ -83,7 +84,7 @@ sealed class BitPat(val value: BigInt, val mask: BigInt, width: Int) { 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 = UInt(value, width) === (that & UInt(mask)) def do_=/= (that: UInt)(implicit sourceInfo: SourceInfo): Bool = !(this === that) def do_!= (that: UInt)(implicit sourceInfo: SourceInfo): Bool = this =/= that } -- cgit v1.2.3 From 8fc61aeab7c50a5bf2ff6f6f8ab46e960cce2adf Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Fri, 15 Jul 2016 00:09:05 -0700 Subject: Improve PopCount implementation Clean up Scala code, and use +& to generate a lot less FIRRTL --- chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala b/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala index 91cb9e89..0872ec41 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala @@ -23,14 +23,10 @@ private[chisel3] object SeqUtils { /** Counts the number of true Bools in a Seq */ 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) { - in.head - } else { - count(in.slice(0, in.size/2)) + (UInt(0) ## count(in.slice(in.size/2, in.size))) - } + def do_count(in: Seq[Bool])(implicit sourceInfo: SourceInfo): UInt = in.size match { + case 0 => UInt(0) + case 1 => in.head + case n => count(in take n/2) +& count(in drop n/2) } /** Returns data value corresponding to first true predicate */ -- cgit v1.2.3 From 54cd58cbb435170dd2ed67dafe1cb1d769a799e8 Mon Sep 17 00:00:00 2001 From: Jack Koenig Date: Wed, 20 Jul 2016 13:33:23 -0700 Subject: Generate better names for nodes (#190) For Chisel nodes defined in Module class-level values of type Option or Iterable, we can still use reflection to assign names based on the name of the value. This works for arbitrary nesting of Option and Iterable so long as the innermost type is HasId. Note that this excludes Maps which always have an innermost type of Tuple2[_,_]. --- .../src/main/scala/chisel3/core/Module.scala | 24 ++++- src/test/scala/chiselTests/BetterNamingTests.scala | 101 +++++++++++++++++++++ 2 files changed, 122 insertions(+), 3 deletions(-) create mode 100644 src/test/scala/chiselTests/BetterNamingTests.scala diff --git a/chiselFrontend/src/main/scala/chisel3/core/Module.scala b/chiselFrontend/src/main/scala/chisel3/core/Module.scala index cde7032d..ca91c5f8 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Module.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Module.scala @@ -103,10 +103,28 @@ extends HasId { val valNames = getValNames(this.getClass) def isPublicVal(m: java.lang.reflect.Method) = m.getParameterTypes.isEmpty && valNames.contains(m.getName) + + /** Recursively suggests names to supported "container" classes + * Arbitrary nestings of supported classes are allowed so long as the + * innermost element is of type HasId + * Currently supported: + * - Iterable + * - Option + * (Note that Map is Iterable[Tuple2[_,_]] and thus excluded) + */ + def nameRecursively(prefix: String, nameMe: Any): Unit = + nameMe match { + case (id: HasId) => id.suggestName(prefix) + case Some(elt) => nameRecursively(prefix, elt) + case (iter: Iterable[_]) if iter.hasDefiniteSize => + for ((elt, i) <- iter.zipWithIndex) { + nameRecursively(s"${prefix}_${i}", elt) + } + case _ => // Do nothing + } val methods = getClass.getMethods.sortWith(_.getName > _.getName) - for (m <- methods; if isPublicVal(m)) m.invoke(this) match { - case (id: HasId) => id.suggestName(m.getName) - case _ => + for (m <- methods if isPublicVal(m)) { + nameRecursively(m.getName, m.invoke(this)) } // For Module instances we haven't named, suggest the name of the Module diff --git a/src/test/scala/chiselTests/BetterNamingTests.scala b/src/test/scala/chiselTests/BetterNamingTests.scala new file mode 100644 index 00000000..44fc542a --- /dev/null +++ b/src/test/scala/chiselTests/BetterNamingTests.scala @@ -0,0 +1,101 @@ +package chiselTests + +import org.scalatest.{FlatSpec, Matchers} +import collection.mutable + +import Chisel._ + + +// Defined outside of the class so we don't get $ in name +class Other(w: Int) extends Module { + val io = new Bundle { + val a = UInt(width = w) + } +} +class PerNameIndexing(count: Int) extends Module { + val io = new Bundle { } + + val wires = Seq.tabulate(count) { i => Module(new Other(i)) } + val queues = Seq.tabulate(count) { i => Module(new Queue(UInt(width = i), 16)) } +} + +// Note this only checks Iterable[Chisel.Data] which excludes Maps +class IterableNaming extends Module { + val io = new Bundle { } + + val seq = Seq.tabulate(3) { i => + Seq.tabulate(2) { j => Wire(init = (i * j).U) } + } + val optSet = Some(Set(Wire(init = 0.U), + Wire(init = 1.U), + Wire(init = 2.U), + Wire(init = 3.U))) + + val stack = mutable.Stack[Module]() + for (i <- 0 until 4) { + stack push Module(new Other(i)) + } + + def streamFrom(x: Int): Stream[Module] = + Module(new Other(x)) #:: streamFrom(x + 1) + val stream = streamFrom(0) // Check that we don't get into infinite loop + val list = stream.take(8).toList +} + +/* Better Naming Tests + * + * These tests are intended to validate that Chisel picks better names + */ +class BetterNamingTests extends FlatSpec { + + behavior of "Better Naming" + + it should "provide unique counters for each name" in { + val verilog = Driver.emit(() => new PerNameIndexing(4)) + val ModuleDef = """\s*module\s+(\S+)\s+:\s*""".r + val expectedModules = Set("PerNameIndexing", + "Queue", "Queue_1", "Queue_2", "Queue_3", + "Other", "Other_1", "Other_2", "Other_3") + val foundModules = for { + ModuleDef(name) <- verilog.split("\n").toSeq + } yield name + assert(foundModules.toSet === expectedModules) + } + + it should "provide names for things defined in Iterable[HasId] and Option[HasId]" in { + val verilog = Driver.emit(() => new IterableNaming) + + val lines = verilog.split("\n").toSeq + + val SeqDef = """\s*wire\s+seq_(\d+)_(\d+)\s+:\s+UInt\s*""".r + val seqs = for { + i <- (0 until 3) + j <- (0 until 2) + } yield (i.toString, j.toString) + val foundSeqs = for { + SeqDef(i, j) <- lines + } yield (i, j) + assert(foundSeqs.toSet === seqs.toSet) + + val OptSetDef = """\s*wire\s+optSet_(\d+)\s+:\s+UInt\s*""".r + val optSets = (0 until 4) map (_.toString) + val foundOptSets = for { + OptSetDef(i) <- lines + } yield i + assert(foundOptSets.toSet === optSets.toSet) + + val StackDef = """\s*inst\s+stack_(\d+)\s+of\s+Other.*""".r + val stacks = (0 until 4) map (_.toString) + val foundStacks = for { + StackDef(i) <- lines + } yield i + assert(foundStacks.toSet === stacks.toSet) + + val ListDef = """\s*inst\s+list_(\d+)\s+of\s+Other.*""".r + val lists = (0 until 8) map (_.toString) + val foundLists = for { + ListDef(i) <- lines + } yield i + assert(foundLists.toSet === lists.toSet) + } +} -- cgit v1.2.3