From 859094d292dbfa55e098d615bac7c508fada7a67 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Thu, 19 May 2016 16:57:30 -0700 Subject: Update to current sbt resolver idiom. --- build.sbt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.sbt b/build.sbt index 06a73d88..16f8e19f 100644 --- a/build.sbt +++ b/build.sbt @@ -50,8 +50,8 @@ lazy val chiselSettings = Seq ( }, resolvers ++= Seq( - "Sonatype Snapshots" at "http://oss.sonatype.org/content/repositories/snapshots", - "Sonatype Releases" at "http://oss.sonatype.org/content/repositories/releases" + Resolver.sonatypeRepo("snapshots"), + Resolver.sonatypeRepo("releases") ), /* Bumping "com.novocode" % "junit-interface" % "0.11", causes DelayTest testSeqReadBundle to fail -- cgit v1.2.3 From 53813f61b7dfe246d214ab966739d01c65c8ecb0 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Wed, 8 Jun 2016 11:32:23 -0700 Subject: For Module instances we haven't named, suggest the Module class name --- chiselFrontend/src/main/scala/Chisel/Module.scala | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/chiselFrontend/src/main/scala/Chisel/Module.scala b/chiselFrontend/src/main/scala/Chisel/Module.scala index 20c9dd4a..e2101538 100644 --- a/chiselFrontend/src/main/scala/Chisel/Module.scala +++ b/chiselFrontend/src/main/scala/Chisel/Module.scala @@ -105,6 +105,12 @@ extends HasId { 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) -- cgit v1.2.3 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 d675043717593fb7e96fb0f1952debbeb7f20a57 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Tue, 21 Jun 2016 09:17:30 -0700 Subject: New Module, IO, Input/Output wrapping. --- chiselFrontend/src/main/scala/Chisel/Assert.scala | 4 +- chiselFrontend/src/main/scala/Chisel/Module.scala | 66 +++++++++--- .../src/main/scala/Chisel/internal/Builder.scala | 26 +++-- src/main/scala/Chisel/testers/BasicTester.scala | 2 +- src/main/scala/Chisel/util/Decoupled.scala | 113 ++++++++++----------- src/main/scala/Chisel/util/Valid.scala | 30 +++--- src/test/scala/chiselTests/Assert.scala | 2 +- src/test/scala/chiselTests/BundleWire.scala | 8 +- src/test/scala/chiselTests/Decoder.scala | 8 +- src/test/scala/chiselTests/DeqIOSpec.scala | 11 +- .../scala/chiselTests/EnableShiftRegister.scala | 10 +- src/test/scala/chiselTests/LFSR16.scala | 8 +- src/test/scala/chiselTests/Module.scala | 22 ++-- src/test/scala/chiselTests/OptionBundle.scala | 6 +- .../scala/chiselTests/ParameterizedModule.scala | 8 +- src/test/scala/chiselTests/Risc.scala | 16 +-- src/test/scala/chiselTests/SIntOps.scala | 36 +++---- src/test/scala/chiselTests/Tbl.scala | 14 +-- src/test/scala/chiselTests/Vec.scala | 30 ------ src/test/scala/chiselTests/VendingMachine.scala | 9 +- 20 files changed, 222 insertions(+), 207 deletions(-) diff --git a/chiselFrontend/src/main/scala/Chisel/Assert.scala b/chiselFrontend/src/main/scala/Chisel/Assert.scala index c086f014..4187c579 100644 --- a/chiselFrontend/src/main/scala/Chisel/Assert.scala +++ b/chiselFrontend/src/main/scala/Chisel/Assert.scala @@ -50,12 +50,12 @@ object assert { // scalastyle:ignore object.name } def apply_impl_do(cond: Bool, line: String, message: Option[String])(implicit sourceInfo: SourceInfo) { - when (!(cond || Builder.dynamicContext.currentModule.get.reset)) { + when (!(cond || Builder.forcedModule.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)) + pushCommand(Stop(sourceInfo, Node(Builder.forcedModule.clock), 1)) } } diff --git a/chiselFrontend/src/main/scala/Chisel/Module.scala b/chiselFrontend/src/main/scala/Chisel/Module.scala index e2101538..4fba6b25 100644 --- a/chiselFrontend/src/main/scala/Chisel/Module.scala +++ b/chiselFrontend/src/main/scala/Chisel/Module.scala @@ -8,8 +8,9 @@ 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 internal.firrtl +import internal.firrtl.{Command, Component, DefInstance, DefInvalid, ModuleIO} object Module { /** A wrapper method that all Module instantiations must be wrapped in @@ -26,14 +27,19 @@ object Module { // module de-duplication in FIRRTL emission. val childSourceInfo = UnlocatableSourceInfo - val parent = dynamicContext.currentModule - val m = bc.setRefs() + val parent: Option[Module] = Builder.currentModule + val m = bc.setRefs() // This will set currentModule! m._commands.prepend(DefInvalid(childSourceInfo, m.io.ref)) // init module outputs - dynamicContext.currentModule = parent + Builder.currentModule = parent // Back to parent! val ports = m.computePorts Builder.components += Component(m, m.name, ports, m._commands) - pushCommand(DefInstance(sourceInfo, m, ports)) - m.setupInParent(childSourceInfo) + // Avoid referencing 'parent' in top module + if(!Builder.currentModule.isEmpty) { + pushCommand(DefInstance(sourceInfo, m, ports)) + m.setupInParent(childSourceInfo) + } + + m } } @@ -52,10 +58,41 @@ extends HasId { def this(_reset: Bool) = this(None, Option(_reset)) def this(_clock: Clock, _reset: Bool) = this(Option(_clock), Option(_reset)) + // This function binds the iodef as a port in the hardware graph + private[Chisel] def Port[T<:Data](iodef: T): iodef.type = { + // Bind each element of the iodef to being a Port + Binding.bind(iodef, PortBinder(this), "Error: iodef") + iodef + } + + private[this] var ioDefined: Boolean = false + + /** + * This must wrap the datatype used to set the io field of any Module. + * i.e. All concrete modules must have defined io in this form: + * [lazy] val io[: io type] = IO(...[: io type]) + * + * Items in [] are optional. + * + * The granted iodef WILL NOT be cloned (to allow for more seamless use of + * anonymous Bundles in the IO) and thus CANNOT have been bound to any logic. + * This will error if any node is bound (e.g. due to logic in a Bundle + * constructor, which is considered improper). + * + * TODO(twigg): Specifically walk the Data definition to call out which nodes + * are problematic. + */ + def IO[T<:Data](iodef: T): iodef.type = { + require(!ioDefined, "Another IO definition for this module was already declared!") + ioDefined = true + + Port(iodef) + } + private[Chisel] val _namespace = Builder.globalNamespace.child private[Chisel] val _commands = ArrayBuffer[Command]() private[Chisel] val _ids = ArrayBuffer[HasId]() - dynamicContext.currentModule = Some(this) + Builder.currentModule = Some(this) /** Name of the instance. */ val name = Builder.globalNamespace.name(getClass.getName.split('.').last) @@ -64,8 +101,8 @@ extends HasId { * connections in and out of a Module may only go through `io` elements. */ def io: Bundle - val clock = Clock(INPUT) - val reset = Bool(INPUT) + val clock = Port(Input(Clock())) + val reset = Port(Input(Bool())) private[Chisel] def addId(d: HasId) { _ids += d } @@ -73,10 +110,13 @@ extends HasId { ("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 computePorts: Seq[firrtl.Port] = + for((name, port) <- ports) yield { + // Port definitions need to know input or output at top-level. + // By FIRRTL semantics, 'flipped' becomes an Input + val direction = if(Data.isFlipped(port)) Direction.Input else Direction.Output + firrtl.Port(port, direction) + } private[Chisel] def setupInParent(implicit sourceInfo: SourceInfo): this.type = { _parent match { diff --git a/chiselFrontend/src/main/scala/Chisel/internal/Builder.scala b/chiselFrontend/src/main/scala/Chisel/internal/Builder.scala index d0e28b7c..fddc4bd7 100644 --- a/chiselFrontend/src/main/scala/Chisel/internal/Builder.scala +++ b/chiselFrontend/src/main/scala/Chisel/internal/Builder.scala @@ -41,11 +41,11 @@ private[Chisel] class IdGen { } private[Chisel] trait HasId { - private[Chisel] def _onModuleClose {} // scalastyle:ignore method.name - private[Chisel] val _parent = Builder.dynamicContext.currentModule + private[Chisel] def _onModuleClose: Unit = {} // scalastyle:ignore method.name + private[Chisel] val _parent: Option[Module] = Builder.currentModule _parent.foreach(_.addId(this)) - private[Chisel] val _id = Builder.idGen.next + private[Chisel] val _id: Long = Builder.idGen.next override def hashCode: Int = _id.toInt override def equals(that: Any): Boolean = that match { case x: HasId => _id == x._id @@ -93,15 +93,29 @@ private[Chisel] class DynamicContext { private[Chisel] object Builder { // All global mutable state must be referenced via dynamicContextVar!! private val dynamicContextVar = new DynamicVariable[Option[DynamicContext]](None) + private def dynamicContext: DynamicContext = + dynamicContextVar.value.getOrElse(new DynamicContext) - 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 currentModule: Option[Module] = dynamicContext.currentModule + def currentModule_=(target: Option[Module]): Unit = { + dynamicContext.currentModule = target + } + def forcedModule: Module = currentModule match { + case Some(module) => module + case None => throw new Exception( + "Error: Not in a Module. Likely cause: Missed Module() wrap or bare chisel API call." + // A bare api call is, e.g. calling Wire() from the scala console). + ) + } + + // TODO(twigg): Ideally, binding checks and new bindings would all occur here + // However, rest of frontend can't support this yet. def pushCommand[T <: Command](c: T): T = { - dynamicContext.currentModule.foreach(_._commands += c) + forcedModule._commands += c c } def pushOp[T <: Data](cmd: DefPrim[T]): T = pushCommand(cmd).id diff --git a/src/main/scala/Chisel/testers/BasicTester.scala b/src/main/scala/Chisel/testers/BasicTester.scala index b8c1494a..94113836 100644 --- a/src/main/scala/Chisel/testers/BasicTester.scala +++ b/src/main/scala/Chisel/testers/BasicTester.scala @@ -12,7 +12,7 @@ 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() + val io = IO(new Bundle()) def popCount(n: Long): Int = n.toBinaryString.count(_=='1') diff --git a/src/main/scala/Chisel/util/Decoupled.scala b/src/main/scala/Chisel/util/Decoupled.scala index 8e045855..66b348e0 100644 --- a/src/main/scala/Chisel/util/Decoupled.scala +++ b/src/main/scala/Chisel/util/Decoupled.scala @@ -8,71 +8,62 @@ 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] + val ready = Input(Bool()) + val valid = Output(Bool()) + val bits = Output(gen.newType) + override protected def cloneType: this.type = 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 { +object DecoupledIO { + /** Adds a ready-valid handshaking protocol to any interface. + * The standard used is that the consumer uses the flipped interface. + */ 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 } + implicit class AddMethodsToDecoupled[T<:Data](val target: DecoupledIO[T]) extends AnyVal { + def firing: Bool = target.ready && target.valid + + /** 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 = { + target.valid := true.asBool + target.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]; } -} + /** Indicate no enqueue occurs. Valid is set to false, and all bits are set to zero. + */ + def noenq(): Unit = { + target.valid := false.asBool + target.bits := target.bits.fromBits(0.asUInt) + } -/** 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 } + /** 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(): T = { + target.ready := true.asBool + target.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) + /** Indicate no dequeue occurs. Ready is set to false + */ + def nodeq(): Unit = { + target.ready := false.asBool + } } 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 +object EnqIO { + def apply[T<:Data](gen: T): DecoupledIO[T] = Flipped(DecoupledIO(gen)) +} +object DeqIO { + def apply[T<:Data](gen: T): DecoupledIO[T] = DecoupledIO(gen) } /** An I/O Bundle for Queues @@ -81,11 +72,11 @@ class DecoupledIOC[+T <: Data](gen: T) extends Bundle 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() + val enq = EnqIO(gen) /** I/O to enqueue data, is [[Chisel.DecoupledIO]]*/ - val deq = Decoupled(gen.cloneType) + val deq = DeqIO(gen) /** The current amount of data in the queue */ - val count = UInt(OUTPUT, log2Up(entries + 1)) + val count = Output(UInt(log2Up(entries + 1))) } /** A hardware module implementing a Queue @@ -109,7 +100,7 @@ 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 io = IO(new QueueIO(gen, entries)) val ram = Mem(entries, gen) val enq_ptr = Counter(entries) @@ -119,8 +110,8 @@ extends Module(override_reset=override_reset) { 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()) + val do_enq = Wire(init=io.enq.firing) + val do_deq = Wire(init=io.deq.firing) when (do_enq) { ram(enq_ptr.value) := io.enq.bits @@ -167,7 +158,7 @@ extends Module(override_reset=override_reset) { from the inputs. Example usage: - {{{ val q = Queue(Decoupled(UInt()), 16) + {{{ val q = Queue(DecoupledIO(UInt()), 16) q.io.enq <> producer.io.out consumer.io.in <> q.io.deq }}} */ diff --git a/src/main/scala/Chisel/util/Valid.scala b/src/main/scala/Chisel/util/Valid.scala index 9e2202bb..38997cab 100644 --- a/src/main/scala/Chisel/util/Valid.scala +++ b/src/main/scala/Chisel/util/Valid.scala @@ -5,20 +5,18 @@ package Chisel -/** An I/O Bundle containing data and a signal determining if it is valid */ -class ValidIO[+T <: Data](gen2: T) extends Bundle +/** An Bundle containing data and a signal determining if it is valid */ +class Valid[+T <: Data](gen: T) extends Bundle { - val valid = Bool(OUTPUT) - val bits = gen2.cloneType.asOutput + val valid = Output(Bool()) + val bits = Output(gen.cloneType) def fire(dummy: Int = 0): Bool = valid - override def cloneType: this.type = new ValidIO(gen2).asInstanceOf[this.type] + override def cloneType: this.type = Valid(gen).asInstanceOf[this.type] } -/** Adds a valid protocol to any interface. The standard used is - that the consumer uses the flipped interface. -*/ +/** Adds a valid protocol to any interface */ object Valid { - def apply[T <: Data](gen: T): ValidIO[T] = new ValidIO(gen) + def apply[T <: Data](gen: T): Valid[T] = new Valid(gen) } /** A hardware module that delays data coming down the pipeline @@ -32,7 +30,7 @@ object Valid { */ object Pipe { - def apply[T <: Data](enqValid: Bool, enqBits: T, latency: Int): ValidIO[T] = { + def apply[T <: Data](enqValid: Bool, enqBits: T, latency: Int): Valid[T] = { if (latency == 0) { val out = Wire(Valid(enqBits)) out.valid <> enqValid @@ -44,16 +42,16 @@ object Pipe 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) + def apply[T <: Data](enqValid: Bool, enqBits: T): Valid[T] = apply(enqValid, enqBits, 1) + def apply[T <: Data](enq: Valid[T], latency: Int = 1): Valid[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) - } + val io = IO(new Bundle { + val enq = Input(Valid(gen)) + val deq = Output(Valid(gen)) + }) io.deq <> Pipe(io.enq, latency) } diff --git a/src/test/scala/chiselTests/Assert.scala b/src/test/scala/chiselTests/Assert.scala index 24eb8b55..750ed6e4 100644 --- a/src/test/scala/chiselTests/Assert.scala +++ b/src/test/scala/chiselTests/Assert.scala @@ -25,7 +25,7 @@ class SucceedingAssertTester() extends BasicTester { } class PipelinedResetModule extends Module { - val io = new Bundle { } + val io = IO(new Bundle { }) val a = Reg(init = UInt(0xbeef)) val b = Reg(init = UInt(0xbeef)) assert(a === b) diff --git a/src/test/scala/chiselTests/BundleWire.scala b/src/test/scala/chiselTests/BundleWire.scala index d2e42fa9..147575e1 100644 --- a/src/test/scala/chiselTests/BundleWire.scala +++ b/src/test/scala/chiselTests/BundleWire.scala @@ -12,10 +12,10 @@ class Coord extends Bundle { } class BundleWire(n: Int) extends Module { - val io = new Bundle { - val in = (new Coord).asInput - val outs = Vec(n, new Coord).asOutput - } + val io = IO(new Bundle { + val in = Input(new Coord) + val outs = Output(Vec(n, new Coord)) + }) val coords = Wire(Vec(n, new Coord)) for (i <- 0 until n) { coords(i) := io.in diff --git a/src/test/scala/chiselTests/Decoder.scala b/src/test/scala/chiselTests/Decoder.scala index e5cdfd07..07622667 100644 --- a/src/test/scala/chiselTests/Decoder.scala +++ b/src/test/scala/chiselTests/Decoder.scala @@ -8,10 +8,10 @@ import org.scalacheck._ import Chisel.testers.BasicTester class Decoder(bitpats: List[String]) extends Module { - val io = new Bundle { - val inst = UInt(INPUT, 32) - val matched = Bool(OUTPUT) - } + val io = IO(new Bundle { + val inst = Input(UInt(32)) + val matched = Output(Bool()) + }) io.matched := Vec(bitpats.map(BitPat(_) === io.inst)).reduce(_||_) } diff --git a/src/test/scala/chiselTests/DeqIOSpec.scala b/src/test/scala/chiselTests/DeqIOSpec.scala index 8f7937ab..38e00690 100644 --- a/src/test/scala/chiselTests/DeqIOSpec.scala +++ b/src/test/scala/chiselTests/DeqIOSpec.scala @@ -15,17 +15,17 @@ class UsesDeqIOInfo extends Bundle { } class UsesDeqIO extends Module { - val io = new Bundle { - val in = new DeqIO(new UsesDeqIOInfo) - val out = new EnqIO(new UsesDeqIOInfo) - } + val io = IO(new Bundle { + val in = DeqIO(new UsesDeqIOInfo) + val out = EnqIO(new UsesDeqIOInfo) + }) } class DeqIOSpec extends ChiselFlatSpec { runTester { new BasicTester { val dut = new UsesDeqIO - +/* "DeqIO" should "set the direction of it's parameter to INPUT" in { assert(dut.io.in.bits.info_data.dir === INPUT) } @@ -55,6 +55,7 @@ class DeqIOSpec extends ChiselFlatSpec { assert(dut.io.out.ready.dir == out_clone.ready.dir) assert(dut.io.out.valid.dir == out_clone.valid.dir) } + */ } } } diff --git a/src/test/scala/chiselTests/EnableShiftRegister.scala b/src/test/scala/chiselTests/EnableShiftRegister.scala index 6600df2a..11e8b70b 100644 --- a/src/test/scala/chiselTests/EnableShiftRegister.scala +++ b/src/test/scala/chiselTests/EnableShiftRegister.scala @@ -5,11 +5,11 @@ import Chisel._ import Chisel.testers.BasicTester class EnableShiftRegister extends Module { - val io = new Bundle { - val in = UInt(INPUT, 4) - val shift = Bool(INPUT) - val out = UInt(OUTPUT, 4) - } + val io = IO(new Bundle { + val in = Input(UInt(4)) + val shift = Input(Bool()) + val out = Output(UInt(4)) + }) val r0 = Reg(init = UInt(0, 4)) val r1 = Reg(init = UInt(0, 4)) val r2 = Reg(init = UInt(0, 4)) diff --git a/src/test/scala/chiselTests/LFSR16.scala b/src/test/scala/chiselTests/LFSR16.scala index ed76a296..54144bea 100644 --- a/src/test/scala/chiselTests/LFSR16.scala +++ b/src/test/scala/chiselTests/LFSR16.scala @@ -5,10 +5,10 @@ import Chisel._ import Chisel.testers.BasicTester class LFSR16 extends Module { - val io = new Bundle { - val inc = Bool(INPUT) - val out = UInt(OUTPUT, 16) - } + val io = IO(new Bundle { + val inc = Input(Bool()) + val out = Output(UInt(16)) + }) val res = Reg(init = UInt(1, 16)) when (io.inc) { val nxt_res = Cat(res(0)^res(2)^res(3)^res(5), res(15,1)) diff --git a/src/test/scala/chiselTests/Module.scala b/src/test/scala/chiselTests/Module.scala index 88ba795b..ba251916 100644 --- a/src/test/scala/chiselTests/Module.scala +++ b/src/test/scala/chiselTests/Module.scala @@ -4,20 +4,20 @@ package chiselTests import Chisel._ class SimpleIO extends Bundle { - val in = UInt(INPUT, 32) - val out = UInt(OUTPUT, 32) + val in = Input(UInt(32)) + val out = Output(UInt(32)) } class PlusOne extends Module { - val io = new SimpleIO + val io = IO(new SimpleIO) io.out := io.in + UInt(1) } class ModuleVec(val n: Int) extends Module { - val io = new Bundle { - val ins = Vec(n, UInt(INPUT, 32)) - val outs = Vec(n, UInt(OUTPUT, 32)) - } + val io = IO(new Bundle { + val ins = Input(Vec(n, UInt(32))) + val outs = Output(Vec(n, UInt(32))) + }) val pluses = Vec.fill(n){ Module(new PlusOne).io } for (i <- 0 until n) { pluses(i).in := io.ins(i) @@ -39,8 +39,8 @@ class ModuleVecTester(c: ModuleVec) extends Tester(c) { */ class ModuleWire extends Module { - val io = new SimpleIO - val inc = Wire(Module(new PlusOne).io) + val io = IO(new SimpleIO) + val inc = Wire(Module(new PlusOne).io.newType) inc.in := io.in io.out := inc.out } @@ -57,10 +57,10 @@ class ModuleWireTester(c: ModuleWire) extends Tester(c) { */ class ModuleWhen extends Module { - val io = new Bundle { + val io = IO(new Bundle { val s = new SimpleIO val en = Bool() - } + }) when(io.en) { val inc = Module(new PlusOne).io inc.in := io.s.in diff --git a/src/test/scala/chiselTests/OptionBundle.scala b/src/test/scala/chiselTests/OptionBundle.scala index c5a347e6..ad694925 100644 --- a/src/test/scala/chiselTests/OptionBundle.scala +++ b/src/test/scala/chiselTests/OptionBundle.scala @@ -8,15 +8,15 @@ import Chisel.testers.BasicTester class OptionBundle(hasIn: Boolean) extends Bundle { val in = if (hasIn) { - Some(Bool(INPUT)) + Some(Input(Bool())) } else { None } - val out = Bool(OUTPUT) + val out = Output(Bool()) } class OptionBundleModule(hasIn: Boolean) extends Module { - val io = new OptionBundle(hasIn) + val io = IO(new OptionBundle(hasIn)) if (hasIn) { io.out := io.in.get } else { diff --git a/src/test/scala/chiselTests/ParameterizedModule.scala b/src/test/scala/chiselTests/ParameterizedModule.scala index 35e3ba78..f682f310 100644 --- a/src/test/scala/chiselTests/ParameterizedModule.scala +++ b/src/test/scala/chiselTests/ParameterizedModule.scala @@ -7,10 +7,10 @@ import Chisel._ import Chisel.testers.BasicTester class ParameterizedModule(invert: Boolean) extends Module { - val io = new Bundle { - val in = new Bool(INPUT) - val out = new Bool(OUTPUT) - } + val io = IO(new Bundle { + val in = Input(Bool()) + val out = Output(Bool()) + }) if (invert) { io.out := !io.in } else { diff --git a/src/test/scala/chiselTests/Risc.scala b/src/test/scala/chiselTests/Risc.scala index 3daa5bd2..670aa703 100644 --- a/src/test/scala/chiselTests/Risc.scala +++ b/src/test/scala/chiselTests/Risc.scala @@ -4,14 +4,14 @@ package chiselTests import Chisel._ class Risc extends Module { - val io = new Bundle { - val isWr = Bool(INPUT) - val wrAddr = UInt(INPUT, 8) - val wrData = Bits(INPUT, 32) - val boot = Bool(INPUT) - val valid = Bool(OUTPUT) - val out = Bits(OUTPUT, 32) - } + val io = IO(new Bundle { + val isWr = Input(Bool()) + val wrAddr = Input(UInt(8)) + val wrData = Input(Bits(32)) + val boot = Input(Bool()) + val valid = Output(Bool()) + val out = Output(Bits(32)) + }) val memSize = 256 val file = Mem(memSize, Bits(width = 32)) val code = Mem(memSize, Bits(width = 32)) diff --git a/src/test/scala/chiselTests/SIntOps.scala b/src/test/scala/chiselTests/SIntOps.scala index 0835fb4d..934c66a4 100644 --- a/src/test/scala/chiselTests/SIntOps.scala +++ b/src/test/scala/chiselTests/SIntOps.scala @@ -5,24 +5,24 @@ import Chisel._ import Chisel.testers.BasicTester class SIntOps extends Module { - val io = new Bundle { - val a = SInt(INPUT, 16) - val b = SInt(INPUT, 16) - val addout = SInt(OUTPUT, 16) - val subout = SInt(OUTPUT, 16) - val timesout = SInt(OUTPUT, 16) - val divout = SInt(OUTPUT, 16) - val modout = SInt(OUTPUT, 16) - val lshiftout = SInt(OUTPUT, 16) - val rshiftout = SInt(OUTPUT, 16) - val lessout = Bool(OUTPUT) - val greatout = Bool(OUTPUT) - val eqout = Bool(OUTPUT) - val noteqout = Bool(OUTPUT) - val lesseqout = Bool(OUTPUT) - val greateqout = Bool(OUTPUT) - val negout = SInt(OUTPUT, 16) - } + val io = IO(new Bundle { + val a = Input(SInt(16)) + val b = Input(SInt(16)) + val addout = Output(SInt(16)) + val subout = Output(SInt(16)) + val timesout = Output(SInt(16)) + val divout = Output(SInt(16)) + val modout = Output(SInt(16)) + val lshiftout = Output(SInt(16)) + val rshiftout = Output(SInt(16)) + val lessout = Output(Bool()) + val greatout = Output(Bool()) + val eqout = Output(Bool()) + val noteqout = Output(Bool()) + val lesseqout = Output(Bool()) + val greateqout = Output(Bool()) + val negout = Output(SInt(16)) + }) val a = io.a val b = io.b diff --git a/src/test/scala/chiselTests/Tbl.scala b/src/test/scala/chiselTests/Tbl.scala index c79eb8a4..751dc127 100644 --- a/src/test/scala/chiselTests/Tbl.scala +++ b/src/test/scala/chiselTests/Tbl.scala @@ -8,13 +8,13 @@ import org.scalatest.prop._ import Chisel.testers.BasicTester class Tbl(w: Int, n: Int) extends Module { - val io = new Bundle { - val wi = UInt(INPUT, log2Up(n)) - val ri = UInt(INPUT, log2Up(n)) - val we = Bool(INPUT) - val d = UInt(INPUT, w) - val o = UInt(OUTPUT, w) - } + val io = IO(new Bundle { + val wi = Input(UInt(log2Up(n))) + val ri = Input(UInt(log2Up(n))) + val we = Input(Bool()) + val d = Input(UInt(w)) + val o = Output(UInt(w)) + }) val m = Mem(n, UInt(width = w)) io.o := m(io.ri) when (io.we) { diff --git a/src/test/scala/chiselTests/Vec.scala b/src/test/scala/chiselTests/Vec.scala index 943d9e4b..5239c6ba 100644 --- a/src/test/scala/chiselTests/Vec.scala +++ b/src/test/scala/chiselTests/Vec.scala @@ -41,32 +41,6 @@ class ShiftRegisterTester(n: Int) extends BasicTester { } } -class FunBundle extends Bundle { - val stuff = UInt(width = 10) -} - -class ZeroModule extends Module { - val io = new Bundle { - val mem = UInt(width = 10) - val interrupts = Vec(2, Bool()).asInput - val mmio_axi = Vec(0, new FunBundle) - val mmio_ahb = Vec(0, new FunBundle).flip - } - - io.mmio_axi <> io.mmio_ahb - - io.mem := UInt(0) - when (io.interrupts(0)) { io.mem := UInt(1) } - when (io.interrupts(1)) { io.mem := UInt(2) } -} - -class ZeroTester extends BasicTester { - val foo = Module(new ZeroModule) - foo.io.interrupts := Vec.tabulate(2) { _ => Bool(true) } - assert (foo.io.mem === UInt(2)) - stop() -} - class VecSpec extends ChiselPropSpec { property("Vecs should be assignable") { forAll(safeUIntN(8)) { case(w: Int, v: List[Int]) => @@ -81,8 +55,4 @@ class VecSpec extends ChiselPropSpec { property("Regs of vecs should be usable as shift registers") { forAll(smallPosInts) { (n: Int) => assertTesterPasses{ new ShiftRegisterTester(n) } } } - - property("Dual empty Vectors") { - assertTesterPasses{ new ZeroTester } - } } diff --git a/src/test/scala/chiselTests/VendingMachine.scala b/src/test/scala/chiselTests/VendingMachine.scala index 012fc493..5baff275 100644 --- a/src/test/scala/chiselTests/VendingMachine.scala +++ b/src/test/scala/chiselTests/VendingMachine.scala @@ -4,10 +4,11 @@ package chiselTests import Chisel._ class VendingMachine extends Module { - val io = new Bundle { - val nickel = Bool(dir = INPUT) - val dime = Bool(dir = INPUT) - val valid = Bool(dir = OUTPUT) } + val io = IO(new Bundle { + val nickel = Input(Bool()) + val dime = Input(Bool()) + val valid = Output(Bool()) + }) val c = UInt(5, width = 3) val sIdle :: s5 :: s10 :: s15 :: sOk :: Nil = Enum(UInt(), 5) val state = Reg(init = sIdle) -- cgit v1.2.3 From 083610b2faa456dfccc4365dd115565d36e522fa Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Tue, 21 Jun 2016 10:13:51 -0700 Subject: Most of the remaining tests with Module, IO wrapping. --- chiselFrontend/src/main/scala/Chisel/Printf.scala | 4 +- src/main/scala/Chisel/util/Arbiter.scala | 14 +++---- src/test/scala/chiselTests/BlackBox.scala | 32 +++++++-------- src/test/scala/chiselTests/ComplexAssign.scala | 10 ++--- src/test/scala/chiselTests/Direction.scala | 8 ++-- src/test/scala/chiselTests/GCD.scala | 14 +++---- src/test/scala/chiselTests/MemorySearch.scala | 12 +++--- src/test/scala/chiselTests/MulLookup.scala | 10 ++--- src/test/scala/chiselTests/Padding.scala | 10 ++--- src/test/scala/chiselTests/Stack.scala | 14 +++---- src/test/scala/chiselTests/UIntOps.scala | 50 +++++++++++------------ src/test/scala/chiselTests/VectorPacketIO.scala | 9 ++-- 12 files changed, 94 insertions(+), 93 deletions(-) diff --git a/chiselFrontend/src/main/scala/Chisel/Printf.scala b/chiselFrontend/src/main/scala/Chisel/Printf.scala index f068f637..cc121eac 100644 --- a/chiselFrontend/src/main/scala/Chisel/Printf.scala +++ b/chiselFrontend/src/main/scala/Chisel/Printf.scala @@ -24,13 +24,13 @@ object printf { // scalastyle:ignore object.name * @param data format string varargs containing data to print */ def apply(fmt: String, data: Bits*)(implicit sourceInfo: SourceInfo) { - when (!(Builder.dynamicContext.currentModule.get.reset)) { + when (!Builder.forcedModule.reset) { printfWithoutReset(fmt, data:_*) } } private[Chisel] def printfWithoutReset(fmt: String, data: Bits*)(implicit sourceInfo: SourceInfo) { - val clock = Builder.dynamicContext.currentModule.get.clock + val clock = Builder.forcedModule.clock pushCommand(Printf(sourceInfo, Node(clock), fmt, data.map((d: Bits) => d.ref))) } } diff --git a/src/main/scala/Chisel/util/Arbiter.scala b/src/main/scala/Chisel/util/Arbiter.scala index 16ae9be5..5cef4b24 100644 --- a/src/main/scala/Chisel/util/Arbiter.scala +++ b/src/main/scala/Chisel/util/Arbiter.scala @@ -7,9 +7,9 @@ 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)) + val in = Flipped(Vec(n, DecoupledIO(gen))) + val out = DecoupledIO(gen) + val chosen = Output(UInt(log2Up(n))) } /** Arbiter Control determining which producer has access */ @@ -25,7 +25,7 @@ private object ArbiterCtrl 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) + val io = IO(new ArbiterIO(gen, n)) io.chosen := choice io.out.valid := io.in(io.chosen).valid @@ -37,7 +37,7 @@ abstract class LockingArbiterLike[T <: Data](gen: T, n: Int, count: Int, needsLo val locked = lockCount.value =/= UInt(0) val wantsLock = needsLock.map(_(io.out.bits)).getOrElse(Bool(true)) - when (io.out.fire() && wantsLock) { + when (io.out.firing && wantsLock) { lockIdx := io.chosen lockCount.inc() } @@ -53,7 +53,7 @@ abstract class LockingArbiterLike[T <: Data](gen: T, n: Int, count: Int, needsLo 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 lastGrant = RegEnable(io.chosen, io.out.firing) lazy val grantMask = (0 until n).map(UInt(_) > lastGrant) lazy val validMask = io.in zip grantMask map { case (in, g) => in.valid && g } @@ -99,7 +99,7 @@ class RRArbiter[T <: Data](gen:T, n: Int) extends LockingRRArbiter[T](gen, n, 1) consumer.io.in <> arb.io.out */ class Arbiter[T <: Data](gen: T, n: Int) extends Module { - val io = new ArbiterIO(gen, n) + val io = IO(new ArbiterIO(gen, n)) io.chosen := UInt(n-1) io.out.bits := io.in(n-1).bits diff --git a/src/test/scala/chiselTests/BlackBox.scala b/src/test/scala/chiselTests/BlackBox.scala index ca94087c..5877149f 100644 --- a/src/test/scala/chiselTests/BlackBox.scala +++ b/src/test/scala/chiselTests/BlackBox.scala @@ -8,25 +8,25 @@ import Chisel._ import Chisel.testers.BasicTester class BlackBoxInverter extends BlackBox { - val io = new Bundle() { - val in = Bool(INPUT) - val out = Bool(OUTPUT) - } + val io = IO(new Bundle() { + val in = Input(Bool()) + val out = Output(Bool()) + }) } class BlackBoxPassthrough extends BlackBox { - val io = new Bundle() { - val in = Bool(INPUT) - val out = Bool(OUTPUT) - } + val io = IO(new Bundle() { + val in = Input(Bool()) + val out = Output(Bool()) + }) } class BlackBoxRegister extends BlackBox { - val io = new Bundle() { - val clock = Clock().asInput - val in = Bool(INPUT) - val out = Bool(OUTPUT) - } + val io = IO(new Bundle() { + val clock = Input(Clock()) + val in = Input(Bool()) + val out = Output(Bool()) + }) } class BlackBoxTester extends BasicTester { @@ -84,9 +84,9 @@ class BlackBoxWithClockTester extends BasicTester { /* // Must determine how to handle parameterized Verilog class BlackBoxConstant(value: Int) extends BlackBox { - val io = new Bundle() { - val out = UInt(width=log2Up(value)).asOutput - } + val io = IO(new Bundle() { + val out = Output(UInt(width=log2Up(value))) + }) override val name = s"#(WIDTH=${log2Up(value)},VALUE=$value) " } diff --git a/src/test/scala/chiselTests/ComplexAssign.scala b/src/test/scala/chiselTests/ComplexAssign.scala index d79a2625..58f26c1f 100644 --- a/src/test/scala/chiselTests/ComplexAssign.scala +++ b/src/test/scala/chiselTests/ComplexAssign.scala @@ -13,11 +13,11 @@ class Complex[T <: Data](val re: T, val im: T) extends Bundle { } class ComplexAssign(w: Int) extends Module { - val io = new Bundle { - val e = new Bool(INPUT) - val in = new Complex(UInt(width = w), UInt(width = w)).asInput - val out = new Complex(UInt(width = w), UInt(width = w)).asOutput - } + val io = IO(new Bundle { + val e = Input(Bool()) + val in = Input(new Complex(UInt(width = w), UInt(width = w))) + val out = Output(new Complex(UInt(width = w), UInt(width = w))) + }) when (io.e) { val tmp = Wire(new Complex(UInt(width = w), UInt(width = w))) tmp := io.in diff --git a/src/test/scala/chiselTests/Direction.scala b/src/test/scala/chiselTests/Direction.scala index dd2f6572..28b00adb 100644 --- a/src/test/scala/chiselTests/Direction.scala +++ b/src/test/scala/chiselTests/Direction.scala @@ -8,10 +8,10 @@ import org.scalatest.prop._ import Chisel.testers.BasicTester class DirectionHaver extends Module { - val io = new Bundle { - val in = UInt(INPUT, 32) - val out = UInt(OUTPUT, 32) - } + val io = IO(new Bundle { + val in = Input(UInt(32)) + val out = Output(UInt(32)) + }) } class GoodDirection extends DirectionHaver { diff --git a/src/test/scala/chiselTests/GCD.scala b/src/test/scala/chiselTests/GCD.scala index a1bfffda..edb8c80f 100644 --- a/src/test/scala/chiselTests/GCD.scala +++ b/src/test/scala/chiselTests/GCD.scala @@ -8,13 +8,13 @@ import org.scalatest._ import org.scalatest.prop._ class GCD extends Module { - val io = new Bundle { - val a = UInt(INPUT, 32) - val b = UInt(INPUT, 32) - val e = Bool(INPUT) - val z = UInt(OUTPUT, 32) - val v = Bool(OUTPUT) - } + val io = IO(new Bundle { + val a = Input(UInt(32)) + val b = Input(UInt(32)) + val e = Input(Bool()) + val z = Output(UInt(32)) + val v = Output(Bool()) + }) val x = Reg(UInt(width = 32)) val y = Reg(UInt(width = 32)) when (x > y) { x := x -% y } diff --git a/src/test/scala/chiselTests/MemorySearch.scala b/src/test/scala/chiselTests/MemorySearch.scala index 55b704a0..a321522b 100644 --- a/src/test/scala/chiselTests/MemorySearch.scala +++ b/src/test/scala/chiselTests/MemorySearch.scala @@ -5,12 +5,12 @@ import Chisel._ import Chisel.testers.BasicTester class MemorySearch extends Module { - val io = new Bundle { - val target = UInt(INPUT, 4) - val en = Bool(INPUT) - val done = Bool(OUTPUT) - val address = UInt(OUTPUT, 3) - } + val io = IO(new Bundle { + val target = Input(UInt(4)) + val en = Input(Bool()) + val done = Output(Bool()) + val address = Output(UInt(3)) + }) val vals = Array(0, 4, 15, 14, 2, 5, 13) val index = Reg(init = UInt(0, width = 3)) val elts = Vec(vals.map(UInt(_,4))) diff --git a/src/test/scala/chiselTests/MulLookup.scala b/src/test/scala/chiselTests/MulLookup.scala index 49ba13c7..1e5ee798 100644 --- a/src/test/scala/chiselTests/MulLookup.scala +++ b/src/test/scala/chiselTests/MulLookup.scala @@ -8,11 +8,11 @@ import org.scalatest.prop._ import Chisel.testers.BasicTester class MulLookup(val w: Int) extends Module { - val io = new Bundle { - val x = UInt(INPUT, w) - val y = UInt(INPUT, w) - val z = UInt(OUTPUT, 2 * w) - } + val io = IO(new Bundle { + val x = Input(UInt(w)) + val y = Input(UInt(w)) + val z = Output(UInt(2 * w)) + }) val tbl = Vec( for { i <- 0 until 1 << w diff --git a/src/test/scala/chiselTests/Padding.scala b/src/test/scala/chiselTests/Padding.scala index 999b7d36..1f33f8ab 100644 --- a/src/test/scala/chiselTests/Padding.scala +++ b/src/test/scala/chiselTests/Padding.scala @@ -4,11 +4,11 @@ package chiselTests import Chisel._ class Padder extends Module { - val io = new Bundle { - val a = Bits(INPUT, 4) - val asp = SInt(OUTPUT, 8) - val aup = UInt(OUTPUT, 8) - } + val io = IO(new Bundle { + val a = Input(UInt(4)) + val asp = Output(SInt(8)) + val aup = Output(UInt(8)) + }) io.asp := io.a.asSInt io.aup := io.a.asUInt } diff --git a/src/test/scala/chiselTests/Stack.scala b/src/test/scala/chiselTests/Stack.scala index ac799c8a..46e5dc23 100644 --- a/src/test/scala/chiselTests/Stack.scala +++ b/src/test/scala/chiselTests/Stack.scala @@ -5,13 +5,13 @@ import scala.collection.mutable.Stack import Chisel._ class ChiselStack(val depth: Int) extends Module { - val io = new Bundle { - val push = Bool(INPUT) - val pop = Bool(INPUT) - val en = Bool(INPUT) - val dataIn = UInt(INPUT, 32) - val dataOut = UInt(OUTPUT, 32) - } + val io = IO(new Bundle { + val push = Input(Bool()) + val pop = Input(Bool()) + val en = Input(Bool()) + val dataIn = Input(UInt(32)) + val dataOut = Output(UInt(32)) + }) val stack_mem = Mem(depth, UInt(width = 32)) val sp = Reg(init = UInt(0, width = log2Up(depth + 1))) diff --git a/src/test/scala/chiselTests/UIntOps.scala b/src/test/scala/chiselTests/UIntOps.scala index bb0b0f06..4e8506cf 100644 --- a/src/test/scala/chiselTests/UIntOps.scala +++ b/src/test/scala/chiselTests/UIntOps.scala @@ -6,23 +6,23 @@ import org.scalatest._ import Chisel.testers.BasicTester class UIntOps extends Module { - val io = new Bundle { - val a = UInt(INPUT, 16) - val b = UInt(INPUT, 16) - val addout = UInt(OUTPUT, 16) - val subout = UInt(OUTPUT, 16) - val timesout = UInt(OUTPUT, 16) - val divout = UInt(OUTPUT, 16) - val modout = UInt(OUTPUT, 16) - val lshiftout = UInt(OUTPUT, 16) - val rshiftout = UInt(OUTPUT, 16) - val lessout = Bool(OUTPUT) - val greatout = Bool(OUTPUT) - val eqout = Bool(OUTPUT) - val noteqout = Bool(OUTPUT) - val lesseqout = Bool(OUTPUT) - val greateqout = Bool(OUTPUT) - } + val io = IO(new Bundle { + val a = Input(UInt(16)) + val b = Input(UInt(16)) + val addout = Output(UInt(16)) + val subout = Output(UInt(16)) + val timesout = Output(UInt(16)) + val divout = Output(UInt(16)) + val modout = Output(UInt(16)) + val lshiftout = Output(UInt(16)) + val rshiftout = Output(UInt(16)) + val lessout = Output(Bool()) + val greatout = Output(Bool()) + val eqout = Output(Bool()) + val noteqout = Output(Bool()) + val lesseqout = Output(Bool()) + val greateqout = Output(Bool()) + }) val a = io.a val b = io.b @@ -76,18 +76,18 @@ class UIntOpsTester(c: UIntOps) extends Tester(c) { */ class GoodBoolConversion extends Module { - val io = new Bundle { - val u = UInt(1, width = 1).asInput - val b = Bool(OUTPUT) - } + val io = IO(new Bundle { + val u = Input(UInt(1)) + val b = Output(Bool()) + }) io.b := io.u.toBool } class BadBoolConversion extends Module { - val io = new Bundle { - val u = UInt(1, width = 5).asInput - val b = Bool(OUTPUT) - } + val io = IO(new Bundle { + val u = Input(UInt(width = 5)) + val b = Output(Bool()) + }) io.b := io.u.toBool } diff --git a/src/test/scala/chiselTests/VectorPacketIO.scala b/src/test/scala/chiselTests/VectorPacketIO.scala index 99ec66a6..936541c0 100644 --- a/src/test/scala/chiselTests/VectorPacketIO.scala +++ b/src/test/scala/chiselTests/VectorPacketIO.scala @@ -27,8 +27,8 @@ class Packet extends Bundle { * The problem does not occur if the Vec is taken out */ class VectorPacketIO(n: Int) extends Bundle { - val ins = Vec(n, new DeqIO(new Packet())) - val outs = Vec(n, new EnqIO(new Packet())) + val ins = Vec(n, DeqIO(new Packet())) + val outs = Vec(n, EnqIO(new Packet())) } /** @@ -37,10 +37,11 @@ class VectorPacketIO(n: Int) extends Bundle { */ class BrokenVectorPacketModule extends Module { val n = 4 - val io = new VectorPacketIO(n) + val io = IO(new VectorPacketIO(n)) /* the following method of initializing the circuit may change in the future */ - io.outs.foreach(_.init()) + io.ins.foreach(_.noenq()) + io.outs.foreach(_.nodeq()) } class VectorPacketIOUnitTester extends BasicTester { -- 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 c5f9ea3133ef363ff8944e17d94fea79767b6bed Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Wed, 6 Jul 2016 10:01:23 -0700 Subject: Rename "Chisel" to "chisel3" (only git mv). --- .../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/chisel3/core/Aggregate.scala | 377 ++++++++++ .../src/main/scala/chisel3/core/Assert.scala | 73 ++ .../src/main/scala/chisel3/core/BiConnect.scala | 190 ++++++ .../src/main/scala/chisel3/core/Binder.scala | 64 ++ .../src/main/scala/chisel3/core/Binding.scala | 179 +++++ .../src/main/scala/chisel3/core/Bits.scala | 756 +++++++++++++++++++++ .../src/main/scala/chisel3/core/BlackBox.scala | 55 ++ .../src/main/scala/chisel3/core/Data.scala | 161 +++++ .../src/main/scala/chisel3/core/Mem.scala | 134 ++++ .../src/main/scala/chisel3/core/Module.scala | 119 ++++ .../src/main/scala/chisel3/core/MonoConnect.scala | 172 +++++ .../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 | 123 ++++ .../src/main/scala/chisel3/internal/Error.scala | 91 +++ .../main/scala/chisel3/internal/SourceInfo.scala | 51 ++ .../main/scala/chisel3/internal/firrtl/IR.scala | 188 +++++ .../internal/sourceinfo/SourceInfoTransform.scala | 156 ----- .../internal/sourceinfo/SourceInfoTransform.scala | 156 +++++ src/main/scala/Chisel/BitPat.scala | 88 --- 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/chisel3/Driver.scala | 132 ++++ .../compatibility/FileSystemUtilities.scala | 10 + src/main/scala/chisel3/compatibility/Main.scala | 17 + .../chisel3/compatibility/throwException.scala | 12 + .../scala/chisel3/internal/firrtl/Emitter.scala | 112 +++ src/main/scala/chisel3/package.scala | 31 + src/main/scala/chisel3/testers/BasicTester.scala | 38 ++ src/main/scala/chisel3/testers/TesterDriver.scala | 68 ++ src/main/scala/chisel3/util/Arbiter.scala | 117 ++++ src/main/scala/chisel3/util/BitPat.scala | 88 +++ src/main/scala/chisel3/util/Bitwise.scala | 71 ++ src/main/scala/chisel3/util/Cat.scala | 18 + src/main/scala/chisel3/util/CircuitMath.scala | 26 + src/main/scala/chisel3/util/Conditional.scala | 69 ++ src/main/scala/chisel3/util/Counter.scala | 44 ++ src/main/scala/chisel3/util/Decoupled.scala | 183 +++++ src/main/scala/chisel3/util/Enum.scala | 21 + .../scala/chisel3/util/ImplicitConversions.scala | 8 + src/main/scala/chisel3/util/LFSR.scala | 22 + src/main/scala/chisel3/util/Lookup.scala | 17 + src/main/scala/chisel3/util/Math.scala | 42 ++ src/main/scala/chisel3/util/Mux.scala | 61 ++ src/main/scala/chisel3/util/OneHot.scala | 62 ++ src/main/scala/chisel3/util/Reg.scala | 55 ++ src/main/scala/chisel3/util/TransitName.scala | 21 + src/main/scala/chisel3/util/Valid.scala | 59 ++ 88 files changed, 4518 insertions(+), 3913 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/chisel3/core/Aggregate.scala create mode 100644 chiselFrontend/src/main/scala/chisel3/core/Assert.scala create mode 100644 chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala create mode 100644 chiselFrontend/src/main/scala/chisel3/core/Binder.scala create mode 100644 chiselFrontend/src/main/scala/chisel3/core/Binding.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/MonoConnect.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/BitPat.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/chisel3/Driver.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/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/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/chisel3/core/Aggregate.scala b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala new file mode 100644 index 00000000..1eef5d69 --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel3/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/chisel3/core/Assert.scala b/chiselFrontend/src/main/scala/chisel3/core/Assert.scala new file mode 100644 index 00000000..c086f014 --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel3/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/chisel3/core/BiConnect.scala b/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala new file mode 100644 index 00000000..42d85bfb --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala @@ -0,0 +1,190 @@ +package Chisel + +import internal.Builder.pushCommand +import internal.firrtl.Connect +import scala.language.experimental.macros +import internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, UnlocatableSourceInfo, WireTransform, SourceInfoTransform} + +/** +* BiConnect.connect executes a bidirectional connection element-wise. +* +* Note that the arguments are left and right (not source and sink) so the +* intent is for the operation to be commutative. +* +* The connect operation will recurse down the left Data (with the right Data). +* An exception will be thrown if a movement through the left cannot be matched +* in the right (or if the right side has extra fields). +* +* See elemConnect for details on how the root connections are issued. +* +*/ + +object BiConnect { + // These are all the possible exceptions that can be thrown. + case class BiConnectException(message: String) extends Exception(message) + // These are from element-level connection + def BothDriversException = + BiConnectException(": Both Left and Right are drivers") + def NeitherDriverException = + BiConnectException(": Neither Left nor Right is a driver") + def UnknownDriverException = + BiConnectException(": Locally unclear whether Left or Right (both internal)") + def UnknownRelationException = + BiConnectException(": Left or Right unavailable to current module.") + // These are when recursing down aggregate types + def MismatchedVecException = + BiConnectException(": Left and Right are different length Vecs.") + def MissingLeftFieldException(field: String) = + BiConnectException(s".$field: Left Bundle missing field ($field).") + def MissingRightFieldException(field: String) = + BiConnectException(s": Right Bundle missing field ($field).") + def MismatchedException(left: String, right: String) = + BiConnectException(s": Left ($left) and Right ($right) have different types.") + + /** This function is what recursively tries to connect a left and right together + * + * There is some cleverness in the use of internal try-catch to catch exceptions + * during the recursive decent and then rethrow them with extra information added. + * This gives the user a 'path' to where in the connections things went wrong. + */ + def connect(sourceInfo: SourceInfo, left: Data, right: Data, context_mod: Module): Unit = + (left, right) match { + // Handle element case (root case) + case (left_e: Element, right_e: Element) => { + elemConnect(sourceInfo, left_e, right_e, context_mod) + // TODO(twigg): Verify the element-level classes are connectable + } + // Handle Vec case + case (left_v: Vec[Data @unchecked], right_v: Vec[Data @unchecked]) => { + if(left_v.length != right_v.length) { throw MismatchedVecException } + for(idx <- 0 until left_v.length) { + try { + connect(sourceInfo, left_v(idx), right_v(idx), context_mod) + } catch { + case BiConnectException(message) => throw BiConnectException(s"($idx)$message") + } + } + } + // Handle Bundle case + case (left_b: Bundle, right_b: Bundle) => { + // Verify right has no extra fields that left doesn't have + for((field, right_sub) <- right_b.elements) { + if(!left_b.elements.isDefinedAt(field)) throw MissingLeftFieldException(field) + } + // For each field in left, descend with right + for((field, left_sub) <- left_b.elements) { + try { + right_b.elements.get(field) match { + case Some(right_sub) => connect(sourceInfo, left_sub, right_sub, context_mod) + case None => throw MissingRightFieldException(field) + } + } catch { + case BiConnectException(message) => throw BiConnectException(s".$field$message") + } + } + } + // Left and right are different subtypes of Data so fail + case (left, right) => throw MismatchedException(left.toString, right.toString) + } + + // These functions (finally) issue the connection operation + // Issue with right as sink, left as source + private def issueConnectL2R(left: Element, right: Element)(implicit sourceInfo: SourceInfo): Unit = { + pushCommand(Connect(sourceInfo, right.lref, left.ref)) + } + // Issue with left as sink, right as source + private def issueConnectR2L(left: Element, right: Element)(implicit sourceInfo: SourceInfo): Unit = { + pushCommand(Connect(sourceInfo, left.lref, right.ref)) + } + + // This function checks if element-level connection operation allowed. + // Then it either issues it or throws the appropriate exception. + def elemConnect(implicit sourceInfo: SourceInfo, left: Element, right: Element, context_mod: Module): Unit = { + import Direction.{Input, Output} // Using extensively so import these + // If left or right have no location, assume in context module + // This can occur if one of them is a literal, unbound will error previously + val left_mod: Module = left.binding.location.getOrElse(context_mod) + val right_mod: Module = right.binding.location.getOrElse(context_mod) + + val left_direction: Option[Direction] = left.binding.direction + val right_direction: Option[Direction] = right.binding.direction + // None means internal + + // CASE: Context is same module as left node and right node is in a child module + if( (left_mod == context_mod) && + (right_mod._parent.map(_ == context_mod).getOrElse(false)) ) { + // Thus, right node better be a port node and thus have a direction hint + (left_direction, right_direction) match { + // CURRENT MOD CHILD MOD + case (Some(Input), Some(Input)) => issueConnectL2R(left, right) + case (None, Some(Input)) => issueConnectL2R(left, right) + + case (Some(Output), Some(Output)) => issueConnectR2L(left, right) + case (None, Some(Output)) => issueConnectR2L(left, right) + + case (Some(Input), Some(Output)) => throw BothDriversException + case (Some(Output), Some(Input)) => throw NeitherDriverException + case (_, None) => throw UnknownRelationException + } + } + + // CASE: Context is same module as right node and left node is in child module + else if( (right_mod == context_mod) && + (left_mod._parent.map(_ == context_mod).getOrElse(false)) ) { + // Thus, left node better be a port node and thus have a direction hint + (left_direction, right_direction) match { + // CHILD MOD CURRENT MOD + case (Some(Input), Some(Input)) => issueConnectR2L(left, right) + case (Some(Input), None) => issueConnectR2L(left, right) + + case (Some(Output), Some(Output)) => issueConnectL2R(left, right) + case (Some(Output), None) => issueConnectL2R(left, right) + + case (Some(Input), Some(Output)) => throw NeitherDriverException + case (Some(Output), Some(Input)) => throw BothDriversException + case (None, _) => throw UnknownRelationException + } + } + + // CASE: Context is same module that both left node and right node are in + else if( (context_mod == left_mod) && (context_mod == right_mod) ) { + (left_direction, right_direction) match { + // CURRENT MOD CURRENT MOD + case (Some(Input), Some(Output)) => issueConnectL2R(left, right) + case (Some(Input), None) => issueConnectL2R(left, right) + case (None, Some(Output)) => issueConnectL2R(left, right) + + case (Some(Output), Some(Input)) => issueConnectR2L(left, right) + case (Some(Output), None) => issueConnectR2L(left, right) + case (None, Some(Input)) => issueConnectR2L(left, right) + + case (Some(Input), Some(Input)) => throw BothDriversException + case (Some(Output), Some(Output)) => throw NeitherDriverException + case (None, None) => throw UnknownDriverException + } + } + + // CASE: Context is the parent module of both the module containing left node + // and the module containing right node + // Note: This includes case when left and right in same module but in parent + else if( (left_mod._parent.map(_ == context_mod).getOrElse(false)) && + (right_mod._parent.map(_ == context_mod).getOrElse(false)) + ) { + // Thus both nodes must be ports and have a direction hint + (left_direction, right_direction) match { + // CHILD MOD CHILD MOD + case (Some(Input), Some(Output)) => issueConnectR2L(left, right) + case (Some(Output), Some(Input)) => issueConnectL2R(left, right) + + case (Some(Input), Some(Input)) => throw NeitherDriverException + case (Some(Output), Some(Output)) => throw BothDriversException + case (_, None) => throw UnknownRelationException + case (None, _) => throw UnknownRelationException + } + } + + // Not quite sure where left and right are compared to current module + // so just error out + else throw UnknownRelationException + } +} diff --git a/chiselFrontend/src/main/scala/chisel3/core/Binder.scala b/chiselFrontend/src/main/scala/chisel3/core/Binder.scala new file mode 100644 index 00000000..ca074527 --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel3/core/Binder.scala @@ -0,0 +1,64 @@ +package Chisel + +/** +* A Binder is a function from UnboundBinding to some Binding. +* +* These are used exclusively by Binding.bind and sealed in order to keep +* all of them in one place. There are two flavors of Binders: +* Non-terminal (returns another UnboundBinding): These are used to reformat an +* UnboundBinding (like setting direction) before it is terminally bound. +* Terminal (returns any other Binding): Due to the nature of Bindings, once a +* Data is bound to anything but an UnboundBinding, it is forever locked to +* being that type (as it now represents something in the hardware graph). +* +* Note that some Binders require extra arguments to be constructed, like the +* enclosing Module. +*/ + +sealed trait Binder[Out <: Binding] extends Function1[UnboundBinding, Out]{ + def apply(in: UnboundBinding): Out +} + +// THE NON-TERMINAL BINDERS +// These 'rebind' to another unbound node of different direction! +case object InputBinder extends Binder[UnboundBinding] { + def apply(in: UnboundBinding) = UnboundBinding(Some(Direction.Input)) +} +case object OutputBinder extends Binder[UnboundBinding] { + def apply(in: UnboundBinding) = UnboundBinding(Some(Direction.Output)) +} +case object FlippedBinder extends Binder[UnboundBinding] { + def apply(in: UnboundBinding) = UnboundBinding(in.direction.map(_.flip)) + // TODO(twigg): flipping a None should probably be a warning/error +} +// The need for this should be transient. +case object NoDirectionBinder extends Binder[UnboundBinding] { + def apply(in: UnboundBinding) = UnboundBinding(None) +} + +// THE TERMINAL BINDERS +case object LitBinder extends Binder[LitBinding] { + def apply(in: UnboundBinding) = LitBinding() +} + +case class MemoryPortBinder(enclosure: Module) extends Binder[MemoryPortBinding] { + def apply(in: UnboundBinding) = MemoryPortBinding(enclosure) +} + +case class OpBinder(enclosure: Module) extends Binder[OpBinding] { + def apply(in: UnboundBinding) = OpBinding(enclosure) +} + +// Notice how PortBinder uses the direction of the UnboundNode +case class PortBinder(enclosure: Module) extends Binder[PortBinding] { + def apply(in: UnboundBinding) = PortBinding(enclosure, in.direction) +} + +case class RegBinder(enclosure: Module) extends Binder[RegBinding] { + def apply(in: UnboundBinding) = RegBinding(enclosure) +} + +case class WireBinder(enclosure: Module) extends Binder[WireBinding] { + def apply(in: UnboundBinding) = WireBinding(enclosure) +} + diff --git a/chiselFrontend/src/main/scala/chisel3/core/Binding.scala b/chiselFrontend/src/main/scala/chisel3/core/Binding.scala new file mode 100644 index 00000000..949ac9cd --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel3/core/Binding.scala @@ -0,0 +1,179 @@ +package Chisel + +/** + * The purpose of a Binding is to indicate what type of hardware 'entity' a + * specific Data's leaf Elements is actually bound to. All Data starts as being + * Unbound (and the whole point of cloneType is to return an unbound version). + * Then, specific API calls take a Data, and return a bound version (either by + * binding the original model or cloneType then binding the clone). For example, + * Reg[T<:Data](...) returns a T bound to RegBinding. + * + * It is considered invariant that all Elements of a single Data are bound to + * the same concrete type of Binding. + * + * These bindings can be checked (e.g. checkSynthesizable) to make sure certain + * operations are valid. For example, arithemetic operations or connections can + * only be executed between synthesizable nodes. These checks are to avoid + * undefined reference errors. + * + * Bindings can carry information about the particular element in the graph it + * represents like: + * - For ports (and unbound), the 'direction' + * - For (relevant) synthesizable nodes, the enclosing Module + * + * TODO(twigg): Enrich the bindings to carry more information like the hosting + * module (when applicable), direction (when applicable), literal info (when + * applicable). Can ensure applicable data only stored on relevant nodes. e.g. + * literal info on LitBinding, direction info on UnboundBinding and PortBinding, + * etc. + * + * TODO(twigg): Currently, bindings only apply at the Element level and an + * Aggregate is considered bound via its elements. May be appropriate to allow + * Aggregates to be bound along with the Elements. However, certain literal and + * port direction information doesn't quite make sense in aggregates. This would + * elegantly handle the empty Vec or Bundle problem though. + * + * TODO(twigg): Binding is currently done via allElements. It may be more + * elegant if this was instead done as a more explicit tree walk as that allows + * for better errors. + */ + +object Binding { + // Two bindings are 'compatible' if they are the same type. + // Check currently kind of weird: just ensures same class + private def compatible(a: Binding, b: Binding): Boolean = a.getClass == b.getClass + private def compatible(nodes: Seq[Binding]): Boolean = + if(nodes.size > 1) + (for((a,b) <- nodes zip nodes.tail) yield compatible(a,b)) + .fold(true)(_&&_) + else true + + case class BindingException(message: String) extends Exception(message) + def AlreadyBoundException(binding: String) = BindingException(s": Already bound to $binding") + def NotSynthesizableException = BindingException(s": Not bound to synthesizable node, currently only Type description") + + // This recursively walks down the Data tree to look at all the leaf 'Element's + // Will build up an error string in case something goes wrong + // TODO(twigg): Make member function of Data. + // Allows oddities like sample_element to be better hidden + private def walkToBinding(target: Data, checker: Element=>Unit): Unit = target match { + case (element: Element) => checker(element) + case (vec: Vec[Data @unchecked]) => { + try walkToBinding(vec.sample_element, checker) + catch { + case BindingException(message) => throw BindingException(s"(*)$message") + } + for(idx <- 0 until vec.length) { + try walkToBinding(vec(idx), checker) + catch { + case BindingException(message) => throw BindingException(s"($idx)$message") + } + } + } + case (bundle: Bundle) => { + for((field, subelem) <- bundle.elements) { + try walkToBinding(subelem, checker) + catch { + case BindingException(message) => throw BindingException(s".$field$message") + } + } + } + } + + // Use walkToBinding to actually rebind the node type + def bind[T<:Data](target: T, binder: Binder[_<:Binding], error_prelude: String): target.type = { + try walkToBinding( + target, + element => element.binding match { + case unbound @ UnboundBinding(_) => { + element.binding = binder(unbound) + } + case binding => throw AlreadyBoundException(binding.toString) + } + ) + catch { + case BindingException(message) => throw BindingException(s"$error_prelude$message") + } + target + } + + // Excepts if any root element is already bound + def checkUnbound(target: Data, error_prelude: String): Unit = { + try walkToBinding( + target, + element => element.binding match { + case unbound @ UnboundBinding(_) => {} + case binding => throw AlreadyBoundException(binding.toString) + } + ) + catch { + case BindingException(message) => throw BindingException(s"$error_prelude$message") + } + } + + // Excepts if any root element is unbound and thus not on the hardware graph + def checkSynthesizable(target: Data, error_prelude: String): Unit = + try walkToBinding( + target, + element => element.binding match { + case SynthesizableBinding() => {} // OK + case binding => throw NotSynthesizableException + } + ) + catch { + case BindingException(message) => throw BindingException(s"$error_prelude$message") + } +} + +// Location refers to 'where' in the Module hierarchy this lives +sealed trait Binding { + def location: Option[Module] + def direction: Option[Direction] +} + +// Constrained-ness refers to whether 'bound by Module boundaries' +// An unconstrained binding, like a literal, can be read by everyone +sealed trait UnconstrainedBinding extends Binding { + def location = None +} +// A constrained binding can only be read/written by specific modules +// Location will track where this Module is +sealed trait ConstrainedBinding extends Binding { + def enclosure: Module + def location = Some(enclosure) +} + +// An undirectioned binding means the element represents an internal node +// with no meaningful concept of a direction +sealed trait UndirectionedBinding extends Binding { def direction = None } + +// This is the default binding, represents data not yet positioned in the graph +case class UnboundBinding(direction: Option[Direction]) + extends Binding with UnconstrainedBinding + + +// A synthesizable binding is 'bound into' the hardware graph +object SynthesizableBinding { + def unapply(target: Binding): Boolean = target.isInstanceOf[SynthesizableBinding] + // Type check OK because Binding and SynthesizableBinding is sealed +} +sealed trait SynthesizableBinding extends Binding +case class LitBinding() // will eventually have literal info + extends SynthesizableBinding with UnconstrainedBinding with UndirectionedBinding + +case class MemoryPortBinding(enclosure: Module) + extends SynthesizableBinding with ConstrainedBinding with UndirectionedBinding + +// TODO(twigg): Ops between unenclosed nodes can also be unenclosed +// However, Chisel currently binds all op results to a module +case class OpBinding(enclosure: Module) + extends SynthesizableBinding with ConstrainedBinding with UndirectionedBinding + +case class PortBinding(enclosure: Module, direction: Option[Direction]) + extends SynthesizableBinding with ConstrainedBinding + +case class RegBinding(enclosure: Module) + extends SynthesizableBinding with ConstrainedBinding with UndirectionedBinding + +case class WireBinding(enclosure: Module) + extends SynthesizableBinding with ConstrainedBinding with UndirectionedBinding 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..bc8cc8e2 --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel3/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/chisel3/core/BlackBox.scala b/chiselFrontend/src/main/scala/chisel3/core/BlackBox.scala new file mode 100644 index 00000000..b634f021 --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel3/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/chisel3/core/Data.scala b/chiselFrontend/src/main/scala/chisel3/core/Data.scala new file mode 100644 index 00000000..d16843f7 --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel3/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/chisel3/core/Mem.scala b/chiselFrontend/src/main/scala/chisel3/core/Mem.scala new file mode 100644 index 00000000..e34d5499 --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel3/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/chisel3/core/Module.scala b/chiselFrontend/src/main/scala/chisel3/core/Module.scala new file mode 100644 index 00000000..e2101538 --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel3/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/chisel3/core/MonoConnect.scala b/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala new file mode 100644 index 00000000..27da965b --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala @@ -0,0 +1,172 @@ +package Chisel + +import internal.Builder.pushCommand +import internal.firrtl.Connect +import scala.language.experimental.macros +import internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, UnlocatableSourceInfo, WireTransform, SourceInfoTransform} + +/** +* MonoConnect.connect executes a mono-directional connection element-wise. +* +* Note that this isn't commutative. There is an explicit source and sink +* already determined before this function is called. +* +* The connect operation will recurse down the left Data (with the right Data). +* An exception will be thrown if a movement through the left cannot be matched +* in the right. The right side is allowed to have extra Bundle fields. +* Vecs must still be exactly the same size. +* +* See elemConnect for details on how the root connections are issued. +* +* Note that a valid sink must be writable so, one of these must hold: +* - Is an internal writable node (Reg or Wire) +* - Is an output of the current module +* - Is an input of a submodule of the current module +* +* Note that a valid source must be readable so, one of these must hold: +* - Is an internal readable node (Reg, Wire, Op) +* - Is a literal +* - Is a port of the current module or submodule of the current module +*/ + +object MonoConnect { + // These are all the possible exceptions that can be thrown. + case class MonoConnectException(message: String) extends Exception(message) + // These are from element-level connection + def UnreadableSourceException = + MonoConnectException(": Source is unreadable from current module.") + def UnwritableSinkException = + MonoConnectException(": Sink is unwriteable by current module.") + def UnknownRelationException = + MonoConnectException(": Sink or source unavailable to current module.") + // These are when recursing down aggregate types + def MismatchedVecException = + MonoConnectException(": Sink and Source are different length Vecs.") + def MissingFieldException(field: String) = + MonoConnectException(s": Source Bundle missing field ($field).") + def MismatchedException(sink: String, source: String) = + MonoConnectException(s": Sink ($sink) and Source ($source) have different types.") + + /** This function is what recursively tries to connect a sink and source together + * + * There is some cleverness in the use of internal try-catch to catch exceptions + * during the recursive decent and then rethrow them with extra information added. + * This gives the user a 'path' to where in the connections things went wrong. + */ + def connect(sourceInfo: SourceInfo, sink: Data, source: Data, context_mod: Module): Unit = + (sink, source) match { + // Handle element case (root case) + case (sink_e: Element, source_e: Element) => { + elemConnect(sourceInfo, sink_e, source_e, context_mod) + // TODO(twigg): Verify the element-level classes are connectable + } + // Handle Vec case + case (sink_v: Vec[Data @unchecked], source_v: Vec[Data @unchecked]) => { + if(sink_v.length != source_v.length) { throw MismatchedVecException } + for(idx <- 0 until sink_v.length) { + try { + connect(sourceInfo, sink_v(idx), source_v(idx), context_mod) + } catch { + case MonoConnectException(message) => throw MonoConnectException(s"($idx)$message") + } + } + } + // Handle Bundle case + case (sink_b: Bundle, source_b: Bundle) => { + // For each field, descend with right + for((field, sink_sub) <- sink_b.elements) { + try { + source_b.elements.get(field) match { + case Some(source_sub) => connect(sourceInfo, sink_sub, source_sub, context_mod) + case None => throw MissingFieldException(field) + } + } catch { + case MonoConnectException(message) => throw MonoConnectException(s".$field$message") + } + } + } + // Sink and source are different subtypes of data so fail + case (sink, source) => throw MismatchedException(sink.toString, source.toString) + } + + // This function (finally) issues the connection operation + private def issueConnect(sink: Element, source: Element)(implicit sourceInfo: SourceInfo): Unit = { + pushCommand(Connect(sourceInfo, sink.lref, source.ref)) + } + + // This function checks if element-level connection operation allowed. + // Then it either issues it or throws the appropriate exception. + def elemConnect(implicit sourceInfo: SourceInfo, sink: Element, source: Element, context_mod: Module): Unit = { + import Direction.{Input, Output} // Using extensively so import these + // If source has no location, assume in context module + // This can occur if is a literal, unbound will error previously + val sink_mod: Module = sink.binding.location.getOrElse(throw UnwritableSinkException) + val source_mod: Module = source.binding.location.getOrElse(context_mod) + + val sink_direction: Option[Direction] = sink.binding.direction + val source_direction: Option[Direction] = source.binding.direction + // None means internal + + // CASE: Context is same module that both left node and right node are in + if( (context_mod == sink_mod) && (context_mod == source_mod) ) { + (sink_direction, source_direction) match { + // SINK SOURCE + // CURRENT MOD CURRENT MOD + case (Some(Output), _) => issueConnect(sink, source) + case (None, _) => issueConnect(sink, source) + case (Some(Input), _) => throw UnwritableSinkException + } + } + + // CASE: Context is same module as sink node and right node is in a child module + else if( (sink_mod == context_mod) && + (source_mod._parent.map(_ == context_mod).getOrElse(false)) ) { + // Thus, right node better be a port node and thus have a direction + (sink_direction, source_direction) match { + // SINK SOURCE + // CURRENT MOD CHILD MOD + case (None, Some(Output)) => issueConnect(sink, source) + case (None, Some(Input)) => issueConnect(sink, source) + case (Some(Output), Some(Output)) => issueConnect(sink, source) + case (Some(Output), Some(Input)) => issueConnect(sink, source) + case (_, None) => throw UnreadableSourceException + case (Some(Input), _) => throw UnwritableSinkException + } + } + + // CASE: Context is same module as source node and sink node is in child module + else if( (source_mod == context_mod) && + (sink_mod._parent.map(_ == context_mod).getOrElse(false)) ) { + // Thus, left node better be a port node and thus have a direction + (sink_direction, source_direction) match { + // SINK SOURCE + // CHILD MOD CURRENT MOD + case (Some(Input), _) => issueConnect(sink, source) + case (Some(Output), _) => throw UnwritableSinkException + case (None, _) => throw UnwritableSinkException + } + } + + // CASE: Context is the parent module of both the module containing sink node + // and the module containing source node + // Note: This includes case when sink and source in same module but in parent + else if( (sink_mod._parent.map(_ == context_mod).getOrElse(false)) && + (source_mod._parent.map(_ == context_mod).getOrElse(false)) + ) { + // Thus both nodes must be ports and have a direction + (sink_direction, source_direction) match { + // SINK SOURCE + // CHILD MOD CHILD MOD + case (Some(Input), Some(Input)) => issueConnect(sink, source) + case (Some(Input), Some(Output)) => issueConnect(sink, source) + case (Some(Output), _) => throw UnwritableSinkException + case (_, None) => throw UnreadableSourceException + case (None, _) => throw UnwritableSinkException + } + } + + // Not quite sure where left and right are compared to current module + // so just error out + else throw UnknownRelationException + } +} 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..f068f637 --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel3/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/chisel3/core/Reg.scala b/chiselFrontend/src/main/scala/chisel3/core/Reg.scala new file mode 100644 index 00000000..c8faa5c9 --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel3/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/chisel3/core/SeqUtils.scala b/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala new file mode 100644 index 00000000..9a15fd5f --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel3/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/chisel3/core/When.scala b/chiselFrontend/src/main/scala/chisel3/core/When.scala new file mode 100644 index 00000000..90b3d1a5 --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel3/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/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala b/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala new file mode 100644 index 00000000..d0e28b7c --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel3/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 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/chisel3/internal/Error.scala b/chiselFrontend/src/main/scala/chisel3/internal/Error.scala new file mode 100644 index 00000000..6c4c0880 --- /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._ + +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..66bfc7a4 --- /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..62784cee --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala @@ -0,0 +1,188 @@ +// 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/chisel3/internal/sourceinfo/SourceInfoTransform.scala b/coreMacros/src/main/scala/chisel3/internal/sourceinfo/SourceInfoTransform.scala new file mode 100644 index 00000000..82ad5b9e --- /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/BitPat.scala b/src/main/scala/Chisel/BitPat.scala deleted file mode 100644 index 96206f63..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/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/chisel3/Driver.scala b/src/main/scala/chisel3/Driver.scala new file mode 100644 index 00000000..02204684 --- /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/FileSystemUtilities.scala b/src/main/scala/chisel3/compatibility/FileSystemUtilities.scala new file mode 100644 index 00000000..575ae138 --- /dev/null +++ b/src/main/scala/chisel3/compatibility/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/chisel3/compatibility/Main.scala b/src/main/scala/chisel3/compatibility/Main.scala new file mode 100644 index 00000000..a72debc3 --- /dev/null +++ b/src/main/scala/chisel3/compatibility/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/chisel3/compatibility/throwException.scala b/src/main/scala/chisel3/compatibility/throwException.scala new file mode 100644 index 00000000..702884aa --- /dev/null +++ b/src/main/scala/chisel3/compatibility/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/chisel3/internal/firrtl/Emitter.scala b/src/main/scala/chisel3/internal/firrtl/Emitter.scala new file mode 100644 index 00000000..7ca3268a --- /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..f05e8b5d --- /dev/null +++ b/src/main/scala/chisel3/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/chisel3/testers/BasicTester.scala b/src/main/scala/chisel3/testers/BasicTester.scala new file mode 100644 index 00000000..b8c1494a --- /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..a56bb8b7 --- /dev/null +++ b/src/main/scala/chisel3/testers/TesterDriver.scala @@ -0,0 +1,68 @@ +// 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..16ae9be5 --- /dev/null +++ b/src/main/scala/chisel3/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/chisel3/util/BitPat.scala b/src/main/scala/chisel3/util/BitPat.scala new file mode 100644 index 00000000..96206f63 --- /dev/null +++ b/src/main/scala/chisel3/util/BitPat.scala @@ -0,0 +1,88 @@ +// 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/chisel3/util/Bitwise.scala b/src/main/scala/chisel3/util/Bitwise.scala new file mode 100644 index 00000000..239a295e --- /dev/null +++ b/src/main/scala/chisel3/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/chisel3/util/Cat.scala b/src/main/scala/chisel3/util/Cat.scala new file mode 100644 index 00000000..dd706e62 --- /dev/null +++ b/src/main/scala/chisel3/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/chisel3/util/CircuitMath.scala b/src/main/scala/chisel3/util/CircuitMath.scala new file mode 100644 index 00000000..06cab903 --- /dev/null +++ b/src/main/scala/chisel3/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/chisel3/util/Conditional.scala b/src/main/scala/chisel3/util/Conditional.scala new file mode 100644 index 00000000..9cab25ef --- /dev/null +++ b/src/main/scala/chisel3/util/Conditional.scala @@ -0,0 +1,69 @@ +// 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/chisel3/util/Counter.scala b/src/main/scala/chisel3/util/Counter.scala new file mode 100644 index 00000000..872e830a --- /dev/null +++ b/src/main/scala/chisel3/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/chisel3/util/Decoupled.scala b/src/main/scala/chisel3/util/Decoupled.scala new file mode 100644 index 00000000..8e045855 --- /dev/null +++ b/src/main/scala/chisel3/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/chisel3/util/Enum.scala b/src/main/scala/chisel3/util/Enum.scala new file mode 100644 index 00000000..20057197 --- /dev/null +++ b/src/main/scala/chisel3/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/chisel3/util/ImplicitConversions.scala b/src/main/scala/chisel3/util/ImplicitConversions.scala new file mode 100644 index 00000000..6a230022 --- /dev/null +++ b/src/main/scala/chisel3/util/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/chisel3/util/LFSR.scala b/src/main/scala/chisel3/util/LFSR.scala new file mode 100644 index 00000000..839b1d1f --- /dev/null +++ b/src/main/scala/chisel3/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/chisel3/util/Lookup.scala b/src/main/scala/chisel3/util/Lookup.scala new file mode 100644 index 00000000..54922fc4 --- /dev/null +++ b/src/main/scala/chisel3/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/chisel3/util/Math.scala b/src/main/scala/chisel3/util/Math.scala new file mode 100644 index 00000000..5f8212d8 --- /dev/null +++ b/src/main/scala/chisel3/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/chisel3/util/Mux.scala b/src/main/scala/chisel3/util/Mux.scala new file mode 100644 index 00000000..9d92321a --- /dev/null +++ b/src/main/scala/chisel3/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/chisel3/util/OneHot.scala b/src/main/scala/chisel3/util/OneHot.scala new file mode 100644 index 00000000..73f27403 --- /dev/null +++ b/src/main/scala/chisel3/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/chisel3/util/Reg.scala b/src/main/scala/chisel3/util/Reg.scala new file mode 100644 index 00000000..6584a4bf --- /dev/null +++ b/src/main/scala/chisel3/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/chisel3/util/TransitName.scala b/src/main/scala/chisel3/util/TransitName.scala new file mode 100644 index 00000000..ec5a11cc --- /dev/null +++ b/src/main/scala/chisel3/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/chisel3/util/Valid.scala b/src/main/scala/chisel3/util/Valid.scala new file mode 100644 index 00000000..9e2202bb --- /dev/null +++ b/src/main/scala/chisel3/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 12810b5efe6a8f872fbc1c63cdfb835ca354624f Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Wed, 6 Jul 2016 09:31:47 -0700 Subject: Update Chisel -> chisel3 references. --- .../src/main/scala/chisel3/core/Aggregate.scala | 30 ++++---- .../src/main/scala/chisel3/core/Assert.scala | 24 +++++-- .../src/main/scala/chisel3/core/BiConnect.scala | 8 +-- .../src/main/scala/chisel3/core/Binder.scala | 2 +- .../src/main/scala/chisel3/core/Binding.scala | 2 +- .../src/main/scala/chisel3/core/Bits.scala | 46 ++++++------ .../src/main/scala/chisel3/core/BlackBox.scala | 28 +++++--- .../src/main/scala/chisel3/core/Data.scala | 38 +++++----- .../src/main/scala/chisel3/core/Mem.scala | 10 +-- .../src/main/scala/chisel3/core/Module.scala | 29 ++++---- .../src/main/scala/chisel3/core/MonoConnect.scala | 8 +-- .../src/main/scala/chisel3/core/Printf.scala | 12 ++-- .../src/main/scala/chisel3/core/Reg.scala | 13 ++-- .../src/main/scala/chisel3/core/SeqUtils.scala | 6 +- .../src/main/scala/chisel3/core/When.scala | 10 +-- .../src/main/scala/chisel3/internal/Builder.scala | 54 +++++++------- .../src/main/scala/chisel3/internal/Error.scala | 8 +-- .../main/scala/chisel3/internal/SourceInfo.scala | 4 +- .../main/scala/chisel3/internal/firrtl/IR.scala | 14 ++-- .../internal/sourceinfo/SourceInfoTransform.scala | 4 +- src/main/scala/chisel3/Driver.scala | 3 +- .../compatibility/FileSystemUtilities.scala | 4 +- src/main/scala/chisel3/compatibility/Main.scala | 4 +- .../chisel3/compatibility/throwException.scala | 4 +- .../scala/chisel3/internal/firrtl/Emitter.scala | 8 +-- src/main/scala/chisel3/package.scala | 82 +++++++++++++++++++++- src/main/scala/chisel3/testers/BasicTester.scala | 4 +- src/main/scala/chisel3/testers/TesterDriver.scala | 5 +- src/main/scala/chisel3/util/Arbiter.scala | 4 +- src/main/scala/chisel3/util/BitPat.scala | 5 +- src/main/scala/chisel3/util/Bitwise.scala | 5 +- src/main/scala/chisel3/util/Cat.scala | 5 +- src/main/scala/chisel3/util/CircuitMath.scala | 4 +- src/main/scala/chisel3/util/Conditional.scala | 8 ++- 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 | 9 ++- src/main/scala/chisel3/util/OneHot.scala | 4 +- src/main/scala/chisel3/util/Reg.scala | 4 +- src/main/scala/chisel3/util/TransitName.scala | 3 +- src/main/scala/chisel3/util/Valid.scala | 4 +- src/test/scala/chiselTests/Assert.scala | 5 +- 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 | 7 +- src/test/scala/chiselTests/Decoder.scala | 7 +- src/test/scala/chiselTests/DeqIOSpec.scala | 5 +- 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 | 5 +- src/test/scala/chiselTests/LFSR16.scala | 8 ++- 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 | 22 +++--- src/test/scala/chiselTests/OptionBundle.scala | 4 +- src/test/scala/chiselTests/Padding.scala | 3 +- .../scala/chiselTests/ParameterizedModule.scala | 4 +- src/test/scala/chiselTests/Printf.scala | 4 +- src/test/scala/chiselTests/Reg.scala | 5 +- src/test/scala/chiselTests/Risc.scala | 4 +- src/test/scala/chiselTests/SIntOps.scala | 5 +- src/test/scala/chiselTests/Stack.scala | 5 +- src/test/scala/chiselTests/Stop.scala | 4 +- src/test/scala/chiselTests/Tbl.scala | 6 +- src/test/scala/chiselTests/TesterDriverSpec.scala | 5 +- src/test/scala/chiselTests/UIntOps.scala | 5 +- src/test/scala/chiselTests/Vec.scala | 6 +- src/test/scala/chiselTests/VectorPacketIO.scala | 5 +- src/test/scala/chiselTests/VendingMachine.scala | 4 +- src/test/scala/chiselTests/When.scala | 6 +- 80 files changed, 461 insertions(+), 268 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala index 1eef5d69..a453d5e0 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala @@ -1,21 +1,21 @@ // See LICENSE for license details. -package Chisel +package chisel3.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 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. */ 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(_ + _) } @@ -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) @@ -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)) { @@ -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[Chisel] def addElt(name: String, elt: Data): Unit = + 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 = { @@ -372,6 +372,6 @@ class Bundle extends Aggregate(NO_DIR) { } } -private[Chisel] object Bundle { - val keywords = List("flip", "asInput", "asOutput", "cloneType", "toBits") +private[core] object Bundle { + val keywords = List("flip", "asInput", "asOutput", "cloneType", "toBits", "newType") } diff --git a/chiselFrontend/src/main/scala/chisel3/core/Assert.scala b/chiselFrontend/src/main/scala/chisel3/core/Assert.scala index c086f014..9e792a51 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 +package chisel3.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 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 @@ -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.forcedModule.reset) { + pushCommand(Stop(sourceInfo, Node(Builder.forcedModule.clock), code)) + } + } + + /** Terminate execution, indicating success. */ + def apply()(implicit sourceInfo: SourceInfo): Unit = { + stop(0) + } +} diff --git a/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala b/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala index 42d85bfb..cb76159a 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala @@ -1,9 +1,9 @@ -package Chisel +package chisel3.core -import internal.Builder.pushCommand -import internal.firrtl.Connect +import chisel3.internal.Builder.pushCommand +import chisel3.internal.firrtl.Connect import scala.language.experimental.macros -import internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, UnlocatableSourceInfo, WireTransform, SourceInfoTransform} +import chisel3.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, UnlocatableSourceInfo, WireTransform, SourceInfoTransform} /** * BiConnect.connect executes a bidirectional connection element-wise. diff --git a/chiselFrontend/src/main/scala/chisel3/core/Binder.scala b/chiselFrontend/src/main/scala/chisel3/core/Binder.scala index ca074527..c7346dce 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Binder.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Binder.scala @@ -1,4 +1,4 @@ -package Chisel +package chisel3.core /** * A Binder is a function from UnboundBinding to some Binding. diff --git a/chiselFrontend/src/main/scala/chisel3/core/Binding.scala b/chiselFrontend/src/main/scala/chisel3/core/Binding.scala index 949ac9cd..d8d9ebd2 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Binding.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Binding.scala @@ -1,4 +1,4 @@ -package Chisel +package chisel3.core /** * The purpose of a Binding is to indicate what type of hardware 'entity' a diff --git a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala index bc8cc8e2..e6a4be71 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 +package chisel3.core import scala.language.experimental.macros -import internal._ -import internal.Builder.pushOp -import internal.firrtl._ -import 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 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) @@ -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,13 +356,13 @@ 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" + private[core] 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 { @@ -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,16 +535,16 @@ 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" + 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 @@ -666,12 +666,12 @@ 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] } - 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 b634f021..f2d9558d 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 +package chisel3.core -import internal.Builder.pushCommand -import internal.firrtl.{ModuleIO, DefInvalid} -import 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 @@ -24,23 +24,31 @@ 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 = { - for ((name, port) <- ports) { - port.setRef(ModuleIO(this, _namespace.name(name))) - } + override private[core] def setRefs(): this.type = { // 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 } // 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/chisel3/core/Data.scala b/chiselFrontend/src/main/scala/chisel3/core/Data.scala index d16843f7..fcdc86bb 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 +package chisel3.core import scala.language.experimental.macros -import internal._ -import internal.Builder.pushCommand -import internal.firrtl._ -import 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 @@ -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,16 +51,16 @@ 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[Chisel] def ref: Arg = if (isLit) litArg.get else lref - private[Chisel] def cloneTypeWidth(width: Width): this.type - private[Chisel] def toType: String + private[core] def lref: Node = Node(this) + private[chisel3] def ref: Arg = if (isLit) litArg.get else lref + private[core] def cloneTypeWidth(width: Width): this.type + private[chisel3] def toType: String def := (that: Data)(implicit sourceInfo: SourceInfo): Unit = this badConnect that @@ -71,7 +71,7 @@ abstract class Data(dirArg: Direction) extends HasId { def litValue(): BigInt = litArg.get.num def isLit(): Boolean = litArg.isDefined - def width: Width + private[core] def width: Width final def getWidth: Int = width.get // While this being in the Data API doesn't really make sense (should be in @@ -83,7 +83,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. @@ -150,9 +150,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[Chisel] def cloneTypeWidth(width: Width): this.type = cloneType - private[Chisel] def toType = "Clock" + private[chisel3] override def flatten: IndexedSeq[Bits] = IndexedSeq() + private[core] def cloneTypeWidth(width: Width): this.type = cloneType + 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 e34d5499..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 +package chisel3.core import scala.language.experimental.macros -import internal._ -import internal.Builder.pushCommand -import internal.firrtl._ -import 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 e2101538..5d510112 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Module.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Module.scala @@ -1,15 +1,16 @@ // See LICENSE for license details. -package Chisel +package chisel3.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 chisel3.internal._ +import chisel3.internal.Builder.pushCommand +import chisel3.internal.Builder.dynamicContext +import chisel3.internal.firrtl._ +import chisel3.internal.firrtl.{Command, Component, DefInstance, DefInvalid, ModuleIO} +import chisel3.internal.sourceinfo.{SourceInfo, InstTransform, UnlocatableSourceInfo} object Module { /** A wrapper method that all Module instantiations must be wrapped in @@ -52,9 +53,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[Chisel] val _commands = ArrayBuffer[Command]() - private[Chisel] val _ids = ArrayBuffer[HasId]() + private[core] val _namespace = Builder.globalNamespace.child + private[chisel3] val _commands = ArrayBuffer[Command]() + private[core] val _ids = ArrayBuffer[HasId]() dynamicContext.currentModule = Some(this) /** Name of the instance. */ @@ -67,18 +68,18 @@ 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[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 +91,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/chisel3/core/MonoConnect.scala b/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala index 27da965b..64c71cb2 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala @@ -1,9 +1,9 @@ -package Chisel +package chisel3.core -import internal.Builder.pushCommand -import internal.firrtl.Connect +import chisel3.internal.Builder.pushCommand +import chisel3.internal.firrtl.Connect import scala.language.experimental.macros -import internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, UnlocatableSourceInfo, WireTransform, SourceInfoTransform} +import chisel3.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, UnlocatableSourceInfo, WireTransform, SourceInfoTransform} /** * MonoConnect.connect executes a mono-directional connection element-wise. diff --git a/chiselFrontend/src/main/scala/chisel3/core/Printf.scala b/chiselFrontend/src/main/scala/chisel3/core/Printf.scala index f068f637..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 +package chisel3.core import scala.language.experimental.macros -import internal._ -import internal.Builder.pushCommand -import internal.firrtl._ -import 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. @@ -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/chisel3/core/Reg.scala b/chiselFrontend/src/main/scala/chisel3/core/Reg.scala index c8faa5c9..14ae9650 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Reg.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Reg.scala @@ -1,14 +1,15 @@ // See LICENSE for license details. -package Chisel +package chisel3.core -import internal._ -import internal.Builder.pushCommand -import internal.firrtl._ -import 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[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/chisel3/core/SeqUtils.scala b/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala index 9a15fd5f..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 +package chisel3.core import scala.language.experimental.macros -import 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 90b3d1a5..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 +package chisel3.core import scala.language.experimental.macros -import internal._ -import internal.Builder.pushCommand -import internal.firrtl._ -import 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 d0e28b7c..0e0a88cc 100644 --- a/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala +++ b/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala @@ -1,29 +1,35 @@ // See LICENSE for license details. -package Chisel.internal +package chisel3.internal import scala.util.DynamicVariable import scala.collection.mutable.{ArrayBuffer, HashMap} -import Chisel._ -import Chisel.internal.firrtl._ +import chisel3._ +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[chisel3] 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) = { i += 1; s"${n}_${i}" } + 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 } } @@ -32,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 @@ -40,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 @@ -62,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) @@ -75,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]() @@ -90,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 6c4c0880..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._ +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 66bfc7a4..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 62784cee..64d7d5fd 100644 --- a/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala +++ b/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala @@ -1,9 +1,11 @@ // See LICENSE for license details. -package Chisel.internal.firrtl -import Chisel._ -import Chisel.internal._ -import Chisel.internal.sourceinfo.{SourceInfo, NoSourceInfo} +package chisel3.internal.firrtl + +import chisel3._ +import core._ +import chisel3.internal._ +import chisel3.internal.sourceinfo.{SourceInfo, NoSourceInfo} case class PrimOp(val name: String) { override def toString: String = name @@ -53,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 82ad5b9e..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 02204684..0979314f 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._ @@ -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, diff --git a/src/main/scala/chisel3/compatibility/FileSystemUtilities.scala b/src/main/scala/chisel3/compatibility/FileSystemUtilities.scala index 575ae138..cd47c731 100644 --- a/src/main/scala/chisel3/compatibility/FileSystemUtilities.scala +++ b/src/main/scala/chisel3/compatibility/FileSystemUtilities.scala @@ -1,6 +1,8 @@ // See LICENSE for license details. -package Chisel +package chisel3.compatibility + +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 a72debc3..a41599a3 100644 --- a/src/main/scala/chisel3/compatibility/Main.scala +++ b/src/main/scala/chisel3/compatibility/Main.scala @@ -1,9 +1,11 @@ // See LICENSE for license details. -package Chisel +package chisel3.compatibility import java.io.File +import chisel3._ + @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") diff --git a/src/main/scala/chisel3/compatibility/throwException.scala b/src/main/scala/chisel3/compatibility/throwException.scala index 702884aa..3e8b33e6 100644 --- a/src/main/scala/chisel3/compatibility/throwException.scala +++ b/src/main/scala/chisel3/compatibility/throwException.scala @@ -1,6 +1,8 @@ // See LICENSE for license details. -package Chisel +package chisel3.compatibility + +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 7ca3268a..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 f05e8b5d..35bbd1c4 100644 --- a/src/main/scala/chisel3/package.scala +++ b/src/main/scala/chisel3/package.scala @@ -1,12 +1,88 @@ -package object Chisel { +package object chisel3 { 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()) + + import util.BitPat + + + type Direction = chisel3.core.Direction + 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 + + /** + * These implicit classes allow one to convert scala.Int|scala.BigInt to + * Chisel.UInt|Chisel.SInt by calling .asUInt|.asSInt on them, respectively. + * The versions .asUInt(width)|.asSInt(width) are also available to explicitly + * mark a width for the new literal. + * + * Also provides .asBool to scala.Boolean and .asUInt to String + * + * Note that, for stylistic reasons, one hould avoid extracting immediately + * after this call using apply, ie. 0.asUInt(1)(0) due to potential for + * confusion (the 1 is a bit length and the 0 is a bit extraction position). + * Prefer storing the result and then extracting from it. + */ + implicit class addLiteraltoScalaInt(val target: Int) extends AnyVal { + def asUInt() = UInt.Lit(target) + def asSInt() = SInt.Lit(target) + def asUInt(width: Int) = UInt.Lit(target, width) + def asSInt(width: Int) = SInt.Lit(target, width) + + // These were recently added to chisel2/3 but are not to be used internally + @deprecated("asUInt should be used over U", "gchisel") + def U() = UInt.Lit(target) + @deprecated("asSInt should be used over S", "gchisel") + def S() = SInt.Lit(target) + @deprecated("asUInt should be used over U", "gchisel") + def U(width: Int) = UInt.Lit(target, width) + @deprecated("asSInt should be used over S", "gchisel") + def S(width: Int) = SInt.Lit(target, width) } implicit class fromIntToLiteral(val x: Int) extends AnyVal { def U: UInt = UInt(BigInt(x), Width()) @@ -23,7 +99,7 @@ package object Chisel { 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 index b8c1494a..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 a56bb8b7..586fa780 100644 --- a/src/main/scala/chisel3/testers/TesterDriver.scala +++ b/src/main/scala/chisel3/testers/TesterDriver.scala @@ -1,7 +1,8 @@ // See LICENSE for license details. -package Chisel.testers -import Chisel._ +package chisel3.testers + +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 16ae9be5..eb541977 100644 --- a/src/main/scala/chisel3/util/Arbiter.scala +++ b/src/main/scala/chisel3/util/Arbiter.scala @@ -3,7 +3,9 @@ /** Arbiters in all shapes and sizes. */ -package Chisel +package chisel3.util + +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 96206f63..9eb5cf67 100644 --- a/src/main/scala/chisel3/util/BitPat.scala +++ b/src/main/scala/chisel3/util/BitPat.scala @@ -1,10 +1,11 @@ // See LICENSE for license details. -package Chisel +package chisel3.util import scala.language.experimental.macros -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 239a295e..ab1ff550 100644 --- a/src/main/scala/chisel3/util/Bitwise.scala +++ b/src/main/scala/chisel3/util/Bitwise.scala @@ -3,7 +3,10 @@ /** Miscellaneous circuit generators operating on bits. */ -package Chisel +package chisel3.util + +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 dd706e62..469bf9ab 100644 --- a/src/main/scala/chisel3/util/Cat.scala +++ b/src/main/scala/chisel3/util/Cat.scala @@ -1,6 +1,9 @@ // See LICENSE for license details. -package Chisel +package chisel3.util + +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 06cab903..1174c71c 100644 --- a/src/main/scala/chisel3/util/CircuitMath.scala +++ b/src/main/scala/chisel3/util/CircuitMath.scala @@ -3,7 +3,9 @@ /** Circuit-land math operations. */ -package Chisel +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 diff --git a/src/main/scala/chisel3/util/Conditional.scala b/src/main/scala/chisel3/util/Conditional.scala index 9cab25ef..6218feb0 100644 --- a/src/main/scala/chisel3/util/Conditional.scala +++ b/src/main/scala/chisel3/util/Conditional.scala @@ -3,13 +3,15 @@ /** Conditional blocks. */ -package Chisel +package chisel3.util import scala.language.reflectiveCalls import scala.language.experimental.macros import scala.reflect.runtime.universe._ import scala.reflect.macros.blackbox._ +import chisel3._ + /** This is identical to [[Chisel.when when]] with the condition inverted */ object unless { // scalastyle:ignore object.name def apply(c: Bool)(block: => Unit) { @@ -59,7 +61,9 @@ object switch { // scalastyle:ignore object.name 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 )") + // TODO: remove when Chisel compatibility package is removed + case q"Chisel.`package`.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 872e830a..40615769 100644 --- a/src/main/scala/chisel3/util/Counter.scala +++ b/src/main/scala/chisel3/util/Counter.scala @@ -1,6 +1,8 @@ // See LICENSE for license details. -package Chisel +package chisel3.util + +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 8e045855..339fde7c 100644 --- a/src/main/scala/chisel3/util/Decoupled.scala +++ b/src/main/scala/chisel3/util/Decoupled.scala @@ -3,7 +3,9 @@ /** Wrappers for ready-valid (Decoupled) interfaces and associated circuit generators using them. */ -package Chisel +package chisel3.util + +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 20057197..4ecc243b 100644 --- a/src/main/scala/chisel3/util/Enum.scala +++ b/src/main/scala/chisel3/util/Enum.scala @@ -3,7 +3,9 @@ /** Enum generators, allowing circuit constants to have more meaningful names. */ -package Chisel +package chisel3.util + +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 6a230022..4d816a19 100644 --- a/src/main/scala/chisel3/util/ImplicitConversions.scala +++ b/src/main/scala/chisel3/util/ImplicitConversions.scala @@ -1,6 +1,8 @@ // See LICENSE for license details. -package Chisel +package chisel3.util + +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 839b1d1f..a30c276f 100644 --- a/src/main/scala/chisel3/util/LFSR.scala +++ b/src/main/scala/chisel3/util/LFSR.scala @@ -3,7 +3,9 @@ /** LFSRs in all shapes and sizes. */ -package Chisel +package chisel3.util + +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 54922fc4..9e909c0c 100644 --- a/src/main/scala/chisel3/util/Lookup.scala +++ b/src/main/scala/chisel3/util/Lookup.scala @@ -1,6 +1,8 @@ // See LICENSE for license details. -package Chisel +package chisel3.util + +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 5f8212d8..73665f0f 100644 --- a/src/main/scala/chisel3/util/Math.scala +++ b/src/main/scala/chisel3/util/Math.scala @@ -3,7 +3,9 @@ /** Scala-land math helper functions, like logs. */ -package Chisel +package chisel3.util + +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 9d92321a..9956a7e3 100644 --- a/src/main/scala/chisel3/util/Mux.scala +++ b/src/main/scala/chisel3/util/Mux.scala @@ -3,7 +3,10 @@ /** Mux circuit generators. */ -package Chisel +package chisel3.util + +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. @@ -37,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) @@ -51,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) diff --git a/src/main/scala/chisel3/util/OneHot.scala b/src/main/scala/chisel3/util/OneHot.scala index 73f27403..820c72d6 100644 --- a/src/main/scala/chisel3/util/OneHot.scala +++ b/src/main/scala/chisel3/util/OneHot.scala @@ -3,7 +3,9 @@ /** Circuit generators for working with one-hot representations. */ -package Chisel +package chisel3.util + +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 6584a4bf..81de4754 100644 --- a/src/main/scala/chisel3/util/Reg.scala +++ b/src/main/scala/chisel3/util/Reg.scala @@ -3,7 +3,9 @@ /** Variations and helpers for registers. */ -package Chisel +package chisel3.util + +import chisel3._ object RegNext { diff --git a/src/main/scala/chisel3/util/TransitName.scala b/src/main/scala/chisel3/util/TransitName.scala index ec5a11cc..f36f926f 100644 --- a/src/main/scala/chisel3/util/TransitName.scala +++ b/src/main/scala/chisel3/util/TransitName.scala @@ -1,5 +1,6 @@ -package Chisel +package chisel3.util +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 9e2202bb..78187ff6 100644 --- a/src/main/scala/chisel3/util/Valid.scala +++ b/src/main/scala/chisel3/util/Valid.scala @@ -3,7 +3,9 @@ /** Wrappers for valid interfaces and associated circuit generators using them. */ -package Chisel +package chisel3.util + +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 24eb8b55..3fed2bd4 100644 --- a/src/test/scala/chiselTests/Assert.scala +++ b/src/test/scala/chiselTests/Assert.scala @@ -3,8 +3,9 @@ package chiselTests import org.scalatest._ -import Chisel._ -import Chisel.testers.BasicTester +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 19aa956c..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 ca94087c..fdc5970e 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 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 d2e42fa9..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 da68b0cb..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 d79a2625..304fbcf5 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.testers.BasicTester +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 07a76cdc..69d8a44a 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.testers.BasicTester + +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 e5cdfd07..5586561b 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.testers.BasicTester + +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 8f7937ab..09891647 100644 --- a/src/test/scala/chiselTests/DeqIOSpec.scala +++ b/src/test/scala/chiselTests/DeqIOSpec.scala @@ -2,8 +2,9 @@ package chiselTests -import Chisel._ -import Chisel.testers.BasicTester +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 dd2f6572..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 6600df2a..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 a1bfffda..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 bc838766..83f60391 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 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 ed76a296..a1699441 100644 --- a/src/test/scala/chiselTests/LFSR16.scala +++ b/src/test/scala/chiselTests/LFSR16.scala @@ -1,8 +1,10 @@ // See LICENSE for license details. package chiselTests -import Chisel._ -import Chisel.testers.BasicTester + +import chisel3._ +import chisel3.testers.BasicTester +import chisel3.util._ class LFSR16 extends Module { val io = new Bundle { @@ -34,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 55b704a0..679b894c 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 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 88ba795b..23788b72 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 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 49ba13c7..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 2f464123..d5e9b998 100644 --- a/src/test/scala/chiselTests/MultiAssign.scala +++ b/src/test/scala/chiselTests/MultiAssign.scala @@ -3,29 +3,31 @@ package chiselTests import org.scalatest._ -import Chisel._ -import Chisel.testers.BasicTester + +import chisel3._ +import chisel3.testers.BasicTester +import chisel3.util._ class LastAssignTester() extends BasicTester { val cnt = Counter(2) val test = Wire(UInt(width=4)) - assert(test === UInt(7)) // allow read references before assign references + assert(test === UInt.Lit(7)) // allow read references before assign references - test := UInt(13) - assert(test === UInt(7)) // output value should be position-independent + test := UInt.Lit(13) + assert(test === UInt.Lit(7)) // output value should be position-independent - test := UInt(7) - assert(test === UInt(7)) // this obviously should work + test := UInt.Lit(7) + assert(test === UInt.Lit(7)) // this obviously should work - when(cnt.value === UInt(1)) { + when(cnt.value === UInt.Lit(1)) { stop() } } class ReassignmentTester() extends BasicTester { - val test = UInt(15) - test := UInt(7) + val test = UInt.Lit(15) + test := UInt.Lit(7) } class MultiAssignSpec extends ChiselFlatSpec { diff --git a/src/test/scala/chiselTests/OptionBundle.scala b/src/test/scala/chiselTests/OptionBundle.scala index c5a347e6..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 999b7d36..3fb0f955 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 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 35e3ba78..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 eb8b4b25..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 f2620d88..391dd7de 100644 --- a/src/test/scala/chiselTests/Reg.scala +++ b/src/test/scala/chiselTests/Reg.scala @@ -3,8 +3,9 @@ package chiselTests import org.scalatest._ -import Chisel._ -import Chisel.testers.BasicTester +import chisel3._ +import chisel3.core.DataMirror +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 3daa5bd2..f5e61115 100644 --- a/src/test/scala/chiselTests/Risc.scala +++ b/src/test/scala/chiselTests/Risc.scala @@ -1,7 +1,9 @@ // See LICENSE for license details. package chiselTests -import Chisel._ + +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 0835fb4d..6cd013f1 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 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 ac799c8a..cbd9f3e3 100644 --- a/src/test/scala/chiselTests/Stack.scala +++ b/src/test/scala/chiselTests/Stack.scala @@ -1,8 +1,11 @@ // See LICENSE for license details. package chiselTests + import scala.collection.mutable.Stack -import Chisel._ + +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 878f090c..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 c79eb8a4..d84cd85e 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.testers.BasicTester + +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 3c57daae..2f3e9368 100644 --- a/src/test/scala/chiselTests/TesterDriverSpec.scala +++ b/src/test/scala/chiselTests/TesterDriverSpec.scala @@ -2,8 +2,9 @@ package chiselTests -import Chisel._ -import Chisel.testers.BasicTester +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 bb0b0f06..c5069fc4 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 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 943d9e4b..7dd80a13 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.testers.BasicTester + +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 99ec66a6..07779faa 100644 --- a/src/test/scala/chiselTests/VectorPacketIO.scala +++ b/src/test/scala/chiselTests/VectorPacketIO.scala @@ -2,8 +2,9 @@ package chiselTests -import Chisel._ -import Chisel.testers.BasicTester +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 012fc493..f03cb881 100644 --- a/src/test/scala/chiselTests/VendingMachine.scala +++ b/src/test/scala/chiselTests/VendingMachine.scala @@ -1,7 +1,9 @@ // See LICENSE for license details. package chiselTests -import Chisel._ + +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 a6572706..5f3d3e61 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 chisel3._ +import chisel3.testers.BasicTester +import chisel3.util._ class WhenTester() extends BasicTester { val cnt = Counter(4) -- cgit v1.2.3 From 3120eefc8a73b5ab3d8f909445a3e004b5e60cc6 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Tue, 19 Jul 2016 15:08:22 -0700 Subject: Incorporate connection logic. Compiles but fails tests. --- .../src/main/scala/chisel3/core/Aggregate.scala | 70 ++++++---- .../src/main/scala/chisel3/core/Bits.scala | 149 ++++++++++++--------- .../src/main/scala/chisel3/core/Data.scala | 143 ++++++++++++++------ .../src/main/scala/chisel3/core/Module.scala | 2 +- src/main/scala/chisel3/package.scala | 45 ++++--- src/main/scala/chisel3/util/Decoupled.scala | 14 +- src/test/scala/chiselTests/Module.scala | 2 +- src/test/scala/chiselTests/MultiAssign.scala | 19 +-- src/test/scala/chiselTests/Reg.scala | 18 +-- 9 files changed, 284 insertions(+), 178 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala index a453d5e0..1b49e163 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala @@ -14,9 +14,9 @@ import chisel3.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, VecTransfo /** 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(_ + _) +sealed abstract class Aggregate extends Data { + private[chisel3] def cloneTypeWidth(width: Width): this.type = cloneType + private[chisel3] def width: Width = flatten.map(_.width).reduce(_ + _) } object Vec { @@ -105,28 +105,40 @@ object Vec { * 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] { + extends Aggregate 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 + /** + * sample_element 'tracks' all changes to the elements of self. + * For consistency, sample_element is always used for creating dynamically + * indexed ports and outputing the FIRRTL type. + * + * Needed specifically for the case when the Vec is length 0. + */ + private[core] val sample_element: T = gen + + // allElements current includes sample_element + // This is somewhat weird although I think the best course of action here is + // to deprecate allElements in favor of dispatched functions to Data or + // a pattern matched recursive descent + private[chisel3] final def allElements: Seq[Element] = + (sample_element +: self).flatMap(_.allElements) /** 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 + 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 := that.asInstanceOf[Data] - - override def := (that: Data)(implicit sourceInfo: SourceInfo): Unit = that match { - case _: Vec[_] => this connect that - case _ => this badConnect that - } + def <> (that: Vec[T])(implicit sourceInfo: SourceInfo): Unit = this bulkConnect that.asInstanceOf[Data] /** Strong bulk connect, assigning elements in this Vec from elements in a Seq. * @@ -144,9 +156,17 @@ sealed class Vec[T <: Data] private (gen: => T, val length: Int) /** Creates a dynamically indexed read or write accessor into the array. */ def apply(idx: UInt): T = { - val x = gen - x.setRef(this, idx) - x + Binding.checkSynthesizable(idx ,s"'idx' ($idx)") + val port = sample_element.cloneType + port.setRef(this, idx) //TODO(twigg): This is a bit too magical + + // Bind each element of port to being whatever the base type is + // Using the head element as the sample_element + for((port_elem, model_elem) <- port.allElements zip sample_element.allElements) { + port_elem.binding = model_elem.binding + } + + port } /** Creates a statically indexed read or write accessor into the array. @@ -162,8 +182,7 @@ sealed class Vec[T <: Data] private (gen: => T, val length: Int) override def cloneType: this.type = Vec(length, gen).asInstanceOf[this.type] - private val t = gen - private[chisel3] def toType: String = s"${t.toType}[$length]" + private[chisel3] def toType: String = s"${sample_element.toType}[$length]" private[chisel3] lazy val flatten: IndexedSeq[Bits] = (0 until length).flatMap(i => this.apply(i).flatten) @@ -256,7 +275,7 @@ trait VecLike[T <: Data] extends collection.IndexedSeq[T] with HasId { * 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) { +class Bundle extends Aggregate { private val _namespace = Builder.globalNamespace.child // TODO: replace with better defined FIRRTL weak-connect operator @@ -272,13 +291,6 @@ class Bundle extends Aggregate(NO_DIR) { * 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:_*) @@ -333,7 +345,7 @@ class Bundle extends Aggregate(NO_DIR) { } private[chisel3] def toType = { def eltPort(elt: Data): String = { - val flipStr = if (elt.isFlip) "flip " else "" + val flipStr: String = if(Data.isFlipped(elt)) "flip " else "" s"${flipStr}${elt.getRef.name} : ${elt.toType}" } s"{${namedElts.reverse.map(e => eltPort(e._2)).mkString(", ")}}" @@ -343,6 +355,8 @@ class Bundle extends Aggregate(NO_DIR) { namedElts += name -> elt private[chisel3] override def _onModuleClose: Unit = // scalastyle:ignore method.name for ((name, elt) <- namedElts) { elt.setRef(this, _namespace.name(name)) } + + private[chisel3] final def allElements: Seq[Element] = namedElts.flatMap(_._2.allElements) override def cloneType : this.type = { // If the user did not provide a cloneType method, try invoking one of @@ -373,5 +387,5 @@ class Bundle extends Aggregate(NO_DIR) { } private[core] object Bundle { - val keywords = List("flip", "asInput", "asOutput", "cloneType", "toBits", "newType") + val keywords = List("flip", "asInput", "asOutput", "cloneType", "toBits") } diff --git a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala index e6a4be71..b18a43d9 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala @@ -14,13 +14,35 @@ 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. */ -abstract class Element(dirArg: Direction, val width: Width) extends Data(dirArg) +abstract class Element(private[core] val width: Width) extends Data { + /** + * Elements can actually be bound to the hardware graph and thus must store + * that binding information. + */ + private[this] var _binding: Binding = UnboundBinding(None) + // Define setter/getter pairing + // Can only bind something that has not yet been bound. + private[core] def binding_=(target: Binding): Unit = _binding match { + case UnboundBinding(_) => { + _binding = target + _binding + } + case _ => throw Binding.AlreadyBoundException(_binding.toString) + // Other checks should have caught this. + } + private[core] def binding = _binding + + /** Return the binding for some bits. */ + def dir: Direction = binding.direction.get + + private[chisel3] final def allElements: Seq[Element] = Seq(this) +} /** 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) { +sealed abstract class Bits(width: Width, override val litArg: Option[LitArg]) + extends Element(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 @@ -31,8 +53,6 @@ sealed abstract class Bits(dirArg: Direction, width: Width, override val litArg: 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 @@ -52,7 +72,7 @@ sealed abstract class Bits(dirArg: Direction, width: Width, override val litArg: case KnownWidth(x) => require(x >= n, s"Can't head($n) for width $x < $n") case UnknownWidth() => } - binop(sourceInfo, UInt(width = n), HeadOp, n) + binop(sourceInfo, UInt(Width(n)), HeadOp, n) } /** Returns the specified bit on this wire as a [[Bool]], statically @@ -67,6 +87,7 @@ sealed abstract class Bits(dirArg: Direction, width: Width, override val litArg: if (isLit()) { Bool(((litValue() >> x.toInt) & 1) == 1) } else { + Binding.checkSynthesizable(this, s"'this' ($this)") pushOp(DefPrim(sourceInfo, Bool(), BitsExtractOp, this.ref, ILit(x), ILit(x))) } } @@ -108,7 +129,8 @@ sealed abstract class Bits(dirArg: Direction, width: Width, override val litArg: if (isLit()) { UInt((litValue >> y) & ((BigInt(1) << w) - 1), w) } else { - pushOp(DefPrim(sourceInfo, UInt(width = w), BitsExtractOp, this.ref, ILit(x), ILit(y))) + Binding.checkSynthesizable(this, s"'this' ($this)") + pushOp(DefPrim(sourceInfo, UInt(Width(w)), BitsExtractOp, this.ref, ILit(x), ILit(y))) } } @@ -118,17 +140,28 @@ 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[core] def unop[T <: Data](sourceInfo: SourceInfo, dest: T, op: PrimOp): T = + private[core] def unop[T <: Data](sourceInfo: SourceInfo, dest: T, op: PrimOp): T = { + Binding.checkSynthesizable(this, s"'this' ($this)") pushOp(DefPrim(sourceInfo, dest, op, this.ref)) - private[core] 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 = { + Binding.checkSynthesizable(this, s"'this' ($this)") pushOp(DefPrim(sourceInfo, dest, op, this.ref, ILit(other))) - private[core] 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 = { + Binding.checkSynthesizable(this, s"'this' ($this)") + Binding.checkSynthesizable(other, s"'other' ($other)") pushOp(DefPrim(sourceInfo, dest, op, this.ref, other.ref)) - - private[core] def compop(sourceInfo: SourceInfo, op: PrimOp, other: Bits): Bool = + } + private[core] def compop(sourceInfo: SourceInfo, op: PrimOp, other: Bits): Bool = { + Binding.checkSynthesizable(this, s"'this' ($this)") + Binding.checkSynthesizable(other, s"'other' ($other)") pushOp(DefPrim(sourceInfo, Bool(), op, this.ref, other.ref)) - private[core] def redop(sourceInfo: SourceInfo, op: PrimOp): Bool = + } + private[core] def redop(sourceInfo: SourceInfo, op: PrimOp): Bool = { + Binding.checkSynthesizable(this, s"'this' ($this)") pushOp(DefPrim(sourceInfo, Bool(), op, this.ref)) + } /** Returns this wire zero padded up to the specified width. * @@ -356,19 +389,19 @@ 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[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[core] def toType = s"UInt$width" +sealed class UInt private[core] (width: Width, lit: Option[ULit] = None) + extends Bits(width, lit) with Num[UInt] { - override private[chisel3] def fromInt(value: BigInt, width: Int): this.type = - UInt(value, width).asInstanceOf[this.type] + if (lit != None) { + this.binding = LitBinding() - override def := (that: Data)(implicit sourceInfo: SourceInfo): Unit = that match { - case _: UInt => this connect that - case _ => this badConnect that } + private[chisel3] override def cloneTypeWidth(w: Width): this.type = + new UInt(w).asInstanceOf[this.type] + private[chisel3] def toType = s"UInt$width" + + override private[chisel3] def fromInt(value: BigInt, width: Int): this.type = + UInt(value, width).asInstanceOf[this.type] // TODO: refactor to share documentation with Num or add independent scaladoc final def unary_- (): UInt = macro SourceInfoTransform.noArg @@ -442,7 +475,7 @@ sealed class UInt private[core] (dir: Direction, width: Width, lit: Option[ULit] final def unary_! () : Bool = macro SourceInfoTransform.noArg - def do_unary_! (implicit sourceInfo: SourceInfo) : Bool = this === Bits(0) + def do_unary_! (implicit sourceInfo: SourceInfo) : Bool = this === UInt(0, 1) override def do_<< (that: Int)(implicit sourceInfo: SourceInfo): UInt = binop(sourceInfo, UInt(this.width + that), ShiftLeftOp, that) @@ -484,12 +517,11 @@ sealed class UInt private[core] (dir: Direction, width: Width, lit: Option[ULit] // 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()) - + def apply(): UInt = apply(Width()) + /** Create a UInt port with specified width. */ + def apply(width: Width): UInt = new UInt(width) + /** Create a UInt with a specified width - compatibility with Chisel2. */ + def apply(dummy: Option[Direction] = None, width: Int): UInt = apply(Width(width)) /** Create a UInt literal with inferred width. */ def apply(value: BigInt): UInt = apply(value, Width()) /** Create a UInt literal with fixed width. */ @@ -497,16 +529,13 @@ private[core] sealed trait UIntFactory { /** 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)) + val result = new UInt(lit.width, Some(lit)) + // Bind result to being an Literal +// result.binding = LitBinding() + result } private def parse(n: String) = { @@ -533,16 +562,12 @@ private[core] sealed trait UIntFactory { 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[chisel3] def toType = s"SInt$width" +sealed class SInt private (width: Width, lit: Option[SLit] = None) + extends Bits(width, lit) with Num[SInt] { - override def := (that: Data)(implicit sourceInfo: SourceInfo): Unit = that match { - case _: SInt => this connect that - case _ => this badConnect that - } + private[chisel3] override def cloneTypeWidth(w: Width): this.type = + new SInt(w).asInstanceOf[this.type] + private[chisel3] def toType = s"SInt$width" override private[chisel3] def fromInt(value: BigInt, width: Int): this.type = SInt(value, width).asInstanceOf[this.type] @@ -639,25 +664,24 @@ sealed class SInt private (dir: Direction, width: Width, lit: Option[SLit] = Non 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()) + def apply(): SInt = apply(Width()) + /** Create a SInt type or port with fixed width. */ + def apply(width: Int): SInt = apply(Width(width)) + /** Create an SInt type with specified width. */ + def apply(width: Width): SInt = new SInt(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)) + val result = new SInt(lit.width, Some(lit)) + // Bind result to being an Literal + result.binding = LitBinding() + result } } @@ -665,10 +689,10 @@ object SInt { // 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 = { +sealed class Bool(lit: Option[ULit] = None) extends UInt(Width(1), lit) { + private[chisel3] override def cloneTypeWidth(w: Width): this.type = { require(!w.known || w.get == 1) - new Bool(dir).asInstanceOf[this.type] + new Bool().asInstanceOf[this.type] } override private[chisel3] def fromInt(value: BigInt, width: Int): this.type = { @@ -709,11 +733,11 @@ sealed class Bool(dir: Direction, lit: Option[ULit] = None) extends UInt(dir, Wi object Bool { /** Creates an empty Bool. */ - def apply(dir: Direction = NO_DIR): Bool = new Bool(dir) + def apply(): Bool = new Bool() /** Creates Bool literal. */ - def apply(x: Boolean): Bool = new Bool(NO_DIR, Some(ULit(if (x) 1 else 0, Width(1)))) + def apply(x: Boolean): Bool = new Bool(Some(ULit(if (x) 1 else 0, Width(1)))) } object Mux { @@ -742,6 +766,9 @@ object Mux { 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}") + Binding.checkSynthesizable(cond, s"'cond' ($cond)") + Binding.checkSynthesizable(con, s"'con' ($con)") + Binding.checkSynthesizable(alt, s"'alt' ($alt)") val d = alt.cloneTypeWidth(con.width max alt.width) pushOp(DefPrim(sourceInfo, d, MultiplexOp, cond.ref, con.ref, alt.ref)) } diff --git a/chiselFrontend/src/main/scala/chisel3/core/Data.scala b/chiselFrontend/src/main/scala/chisel3/core/Data.scala index fcdc86bb..4cc66cb5 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Data.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Data.scala @@ -13,18 +13,69 @@ 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 } +object Direction { + object Input extends Direction("input") { override def flip: Direction = Output } + object Output extends Direction("output") { override def flip: Direction = Input } +} @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, !_) +object DataMirror { + def widthOf(target: Data): Width = target.width +} + +/** +* Input, Output, and Flipped are used to define the directions of Module IOs. +* +* Note that they do not currently call target to be a newType or cloneType. +* This is nominally for performance reasons to avoid too many extra copies when +* something is flipped multiple times. +* +* Thus, an error will be thrown if these are used on bound Data +*/ +object Input { + def apply[T<:Data](target: T): T = + Binding.bind(target, InputBinder, "Error: Cannot set as input ") +} +object Output { + def apply[T<:Data](target: T): T = + Binding.bind(target, OutputBinder, "Error: Cannot set as output ") +} +object Flipped { + def apply[T<:Data](target: T): T = + Binding.bind(target, FlippedBinder, "Error: Cannot flip ") +} + +object Data { + /** + * This function returns true if the FIRRTL type of this Data should be flipped + * relative to other nodes. + * + * Note that the current scheme only applies Flip to Elements or Vec chains of + * Elements. + * + * A Bundle is never marked flip, instead preferring its root fields to be marked + * + * The Vec check is due to the fact that flip must be factored out of the vec, ie: + * must have flip field: Vec(UInt) instead of field: Vec(flip UInt) + */ + private[chisel3] def isFlipped(target: Data): Boolean = target match { + case (element: Element) => element.binding.direction == Some(Direction.Input) + case (vec: Vec[Data @unchecked]) => isFlipped(vec.sample_element) + case (bundle: Bundle) => false + } + + implicit class AddDirectionToData[T<:Data](val target: T) extends AnyVal { + @deprecated("Input(Data) should be used over Data.asInput", "gchisel") + def asInput: T = Input(target) + @deprecated("Output(Data) should be used over Data.asOutput", "gchisel") + def asOutput: T = Output(target) + @deprecated("Flipped(Data) should be used over Data.flip", "gchisel") + def flip(): T = Flipped(target) + } } /** This forms the root of the type system for wire data types. The data value @@ -32,41 +83,45 @@ trait Flipped extends Data { * 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, !_) +abstract class Data extends HasId { + // Return ALL elements at root of this type. + // Contasts with flatten, which returns just Bits + private[chisel3] def allElements: Seq[Element] 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[chisel3] def connect(that: Data)(implicit sourceInfo: SourceInfo): Unit = { + Binding.checkSynthesizable(this, s"'this' ($this)") + Binding.checkSynthesizable(that, s"'that' ($that)") + try { + MonoConnect.connect(sourceInfo, this, that, Builder.forcedModule) + } catch { + case MonoConnect.MonoConnectException(message) => + throwException( + s"Connection between sink ($this) and source ($that) failed @$message" + ) + } + } + private[chisel3] def bulkConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit = { + Binding.checkSynthesizable(this, s"'this' ($this)") + Binding.checkSynthesizable(that, s"'that' ($that)") + try { + BiConnect.connect(sourceInfo, this, that, Builder.forcedModule) + } catch { + case BiConnect.BiConnectException(message) => + throwException( + s"Connection between left ($this) and source ($that) failed @$message" + ) + } + } + private[chisel3] def lref: Node = Node(this) private[chisel3] def ref: Arg = if (isLit) litArg.get else lref - private[core] def cloneTypeWidth(width: Width): this.type + private[chisel3] def cloneTypeWidth(width: Width): this.type private[chisel3] 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 + final def := (that: Data)(implicit sourceInfo: SourceInfo): Unit = this connect that + final def <> (that: Data)(implicit sourceInfo: SourceInfo): Unit = this bulkConnect that def litArg(): Option[LitArg] = None def litValue(): BigInt = litArg.get.num def isLit(): Boolean = litArg.isDefined @@ -134,28 +189,34 @@ object Wire { def do_apply[T <: Data](t: T, init: T)(implicit sourceInfo: SourceInfo): T = { val x = Reg.makeType(t, null.asInstanceOf[T], init) + + // Bind each element of x to being a Wire + Binding.bind(x, WireBinder(Builder.forcedModule), "Error: t") + pushCommand(DefWire(sourceInfo, x)) pushCommand(DefInvalid(sourceInfo, x.ref)) if (init != null) { + Binding.checkSynthesizable(init, s"'init' ($init)") x := init } + x } } object Clock { - def apply(dir: Direction = NO_DIR): Clock = new Clock(dir) + def apply(): Clock = new Clock } // TODO: Document this. -sealed class Clock(dirArg: Direction) extends Element(dirArg, Width(1)) { - def cloneType: this.type = Clock(dirArg).asInstanceOf[this.type] +sealed class Clock extends Element(Width(1)) { + def cloneType: this.type = Clock().asInstanceOf[this.type] private[chisel3] override def flatten: IndexedSeq[Bits] = IndexedSeq() - private[core] def cloneTypeWidth(width: Width): this.type = cloneType + private[chisel3] def cloneTypeWidth(width: Width): this.type = cloneType private[chisel3] def toType = "Clock" - override def := (that: Data)(implicit sourceInfo: SourceInfo): Unit = that match { - case _: Clock => this connect that - case _ => this badConnect that + override def connect (that: Data)(implicit sourceInfo: SourceInfo): Unit = that match { + case _: Clock => super.connect(that)(sourceInfo) + case _ => super.badConnect(that)(sourceInfo) } } diff --git a/chiselFrontend/src/main/scala/chisel3/core/Module.scala b/chiselFrontend/src/main/scala/chisel3/core/Module.scala index 40102cd6..e8474e39 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Module.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Module.scala @@ -91,7 +91,7 @@ extends HasId { private[core] val _namespace = Builder.globalNamespace.child private[chisel3] val _commands = ArrayBuffer[Command]() - private[code] val _ids = ArrayBuffer[HasId]() + private[core] val _ids = ArrayBuffer[HasId]() Builder.currentModule = Some(this) /** Name of the instance. */ diff --git a/src/main/scala/chisel3/package.scala b/src/main/scala/chisel3/package.scala index 35bbd1c4..71ec0e92 100644 --- a/src/main/scala/chisel3/package.scala +++ b/src/main/scala/chisel3/package.scala @@ -3,15 +3,21 @@ package object chisel3 { 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()) import util.BitPat type Direction = chisel3.core.Direction + object Input { + def apply[T<:Data](target: T): T = chisel3.core.Input(target) + } + object Output { + def apply[T<:Data](target: T): T = chisel3.core.Output(target) + } + object Flipped { + def apply[T<:Data](target: T): T = chisel3.core.Flipped(target) + } + type Data = chisel3.core.Data val Wire = chisel3.core.Wire val Clock = chisel3.core.Clock @@ -63,30 +69,24 @@ package object chisel3 { * * Also provides .asBool to scala.Boolean and .asUInt to String * - * Note that, for stylistic reasons, one hould avoid extracting immediately + * Note that, for stylistic reasons, one should avoid extracting immediately * after this call using apply, ie. 0.asUInt(1)(0) due to potential for * confusion (the 1 is a bit length and the 0 is a bit extraction position). * Prefer storing the result and then extracting from it. */ - implicit class addLiteraltoScalaInt(val target: Int) extends AnyVal { - def asUInt() = UInt.Lit(target) - def asSInt() = SInt.Lit(target) - def asUInt(width: Int) = UInt.Lit(target, width) - def asSInt(width: Int) = SInt.Lit(target, width) - - // These were recently added to chisel2/3 but are not to be used internally - @deprecated("asUInt should be used over U", "gchisel") - def U() = UInt.Lit(target) - @deprecated("asSInt should be used over S", "gchisel") - def S() = SInt.Lit(target) - @deprecated("asUInt should be used over U", "gchisel") - def U(width: Int) = UInt.Lit(target, width) - @deprecated("asSInt should be used over S", "gchisel") - def S(width: Int) = SInt.Lit(target, width) - } implicit class fromIntToLiteral(val x: Int) extends AnyVal { def U: UInt = UInt(BigInt(x), Width()) def S: SInt = SInt(BigInt(x), Width()) + + def asUInt() = UInt(x, Width()) + def asSInt() = SInt(x, Width()) + def asUInt(width: Int) = UInt(x, width) + def asSInt(width: Int) = SInt(x, width) + } + + implicit class fromBigIntToLiteral(val x: BigInt) extends AnyVal { + def U: UInt = UInt(x, Width()) + def S: SInt = SInt(x, Width()) } implicit class fromStringToLiteral(val x: String) extends AnyVal { def U: UInt = UInt(x) @@ -104,4 +104,7 @@ package object chisel3 { def do_!= (that: BitPat)(implicit sourceInfo: SourceInfo): Bool = that != x def do_=/= (that: BitPat)(implicit sourceInfo: SourceInfo): Bool = that =/= x } + + val INPUT = chisel3.core.Direction.Input + val OUTPUT = chisel3.core.Direction.Output } diff --git a/src/main/scala/chisel3/util/Decoupled.scala b/src/main/scala/chisel3/util/Decoupled.scala index 73f58ed4..4a6b72e9 100644 --- a/src/main/scala/chisel3/util/Decoupled.scala +++ b/src/main/scala/chisel3/util/Decoupled.scala @@ -12,8 +12,8 @@ class DecoupledIO[+T <: Data](gen: T) extends Bundle { val ready = Input(Bool()) val valid = Output(Bool()) - val bits = Output(gen.newType) - override protected def cloneType: this.type = DecoupledIO(gen).asInstanceOf[this.type] + val bits = Output(gen.cloneType) + override def cloneType: this.type = DecoupledIO(gen).asInstanceOf[this.type] } object DecoupledIO { @@ -30,7 +30,7 @@ object DecoupledIO { * @return dat. */ def enq(dat: T): T = { - target.valid := true.asBool + target.valid := Bool(true) target.bits := dat dat } @@ -38,7 +38,7 @@ object DecoupledIO { /** Indicate no enqueue occurs. Valid is set to false, and all bits are set to zero. */ def noenq(): Unit = { - target.valid := false.asBool + target.valid := Bool(false) target.bits := target.bits.fromBits(0.asUInt) } @@ -48,17 +48,17 @@ object DecoupledIO { * @return the data for this device, */ def deq(): T = { - target.ready := true.asBool + target.ready := Bool(true) target.bits } /** Indicate no dequeue occurs. Ready is set to false */ def nodeq(): Unit = { - target.ready := false.asBool + target.ready := Bool(false) } } - override def cloneType: this.type = { new DeqIO(gen).asInstanceOf[this.type]; } +// override def cloneType: this.type = { DeqIO(gen).asInstanceOf[this.type]; } } object EnqIO { diff --git a/src/test/scala/chiselTests/Module.scala b/src/test/scala/chiselTests/Module.scala index 7c0bc40e..f1608d5b 100644 --- a/src/test/scala/chiselTests/Module.scala +++ b/src/test/scala/chiselTests/Module.scala @@ -41,7 +41,7 @@ class ModuleVecTester(c: ModuleVec) extends Tester(c) { class ModuleWire extends Module { val io = IO(new SimpleIO) - val inc = Wire(Module(new PlusOne).io.newType) + val inc = Wire(Module(new PlusOne).io.cloneType) inc.in := io.in io.out := inc.out } diff --git a/src/test/scala/chiselTests/MultiAssign.scala b/src/test/scala/chiselTests/MultiAssign.scala index d5e9b998..fc6c5edc 100644 --- a/src/test/scala/chiselTests/MultiAssign.scala +++ b/src/test/scala/chiselTests/MultiAssign.scala @@ -12,29 +12,30 @@ class LastAssignTester() extends BasicTester { val cnt = Counter(2) val test = Wire(UInt(width=4)) - assert(test === UInt.Lit(7)) // allow read references before assign references + assert(test === 7.U) // allow read references before assign references - test := UInt.Lit(13) - assert(test === UInt.Lit(7)) // output value should be position-independent + test := 13.U + assert(test === 7.U) // output value should be position-independent - test := UInt.Lit(7) - assert(test === UInt.Lit(7)) // this obviously should work + test := 7.U + assert(test === 7.U) // this obviously should work - when(cnt.value === UInt.Lit(1)) { + when(cnt.value === 1.U) { stop() } } class ReassignmentTester() extends BasicTester { - val test = UInt.Lit(15) - test := UInt.Lit(7) + val test = 15.U + test := 7.U } class MultiAssignSpec extends ChiselFlatSpec { "The last assignment" should "be used when multiple assignments happen" in { assertTesterPasses{ new LastAssignTester } } - "Reassignments to non-wire types" should "be disallowed" in { + intercept[chisel3.internal.ChiselException] { +// "Reassignments to non-wire types" should "be disallowed" in { assertTesterFails{ new ReassignmentTester } } } diff --git a/src/test/scala/chiselTests/Reg.scala b/src/test/scala/chiselTests/Reg.scala index 391dd7de..0caf6315 100644 --- a/src/test/scala/chiselTests/Reg.scala +++ b/src/test/scala/chiselTests/Reg.scala @@ -16,20 +16,20 @@ class RegSpec extends ChiselFlatSpec { "A Reg" should "be of the same type and width as outType, if specified" in { class RegOutTypeWidthTester extends BasicTester { - val reg = Reg(t=UInt(width=2), next=UInt(width=3), init=UInt(20)) - reg.width.get should be (2) + val reg = Reg(t=UInt(width=2), next=Wire(UInt(width=3)), init=UInt(20)) + reg.getWidth should be (2) } elaborate{ new RegOutTypeWidthTester } } "A Reg" should "be of unknown width if outType is not specified and width is not forced" in { class RegUnknownWidthTester extends BasicTester { - val reg1 = Reg(next=UInt(width=3), init=UInt(20)) - reg1.width.known should be (false) - val reg2 = Reg(init=UInt(20)) - reg2.width.known should be (false) - val reg3 = Reg(next=UInt(width=3), init=UInt(width=5)) - reg3.width.known should be (false) + val reg1 = Reg(next=Wire(UInt(width=3)), init=20.U) + DataMirror.widthOf(reg1).known should be (false) + val reg2 = Reg(init=20.U) + DataMirror.widthOf(reg2).known should be (false) + val reg3 = Reg(next=Wire(UInt(width=3)), init=5.U) + DataMirror.widthOf(reg3).known should be (false) } elaborate { new RegUnknownWidthTester } } @@ -37,7 +37,7 @@ class RegSpec extends ChiselFlatSpec { "A Reg" should "be of width of init if outType and next are missing and init is a literal of forced width" in { class RegForcedWidthTester extends BasicTester { val reg2 = Reg(init=UInt(20, width=7)) - reg2.width.get should be (7) + reg2.getWidth should be (7) } elaborate{ new RegForcedWidthTester } } -- cgit v1.2.3 From e27079d2957c689affce66f15e9d1bf29418ad34 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Tue, 19 Jul 2016 15:27:29 -0700 Subject: Remove explicit literal binding. --- chiselFrontend/src/main/scala/chisel3/core/Bits.scala | 4 ---- 1 file changed, 4 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala index b18a43d9..df1296dd 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala @@ -392,10 +392,6 @@ abstract trait Num[T <: Data] { sealed class UInt private[core] (width: Width, lit: Option[ULit] = None) extends Bits(width, lit) with Num[UInt] { - if (lit != None) { - this.binding = LitBinding() - - } private[chisel3] override def cloneTypeWidth(w: Width): this.type = new UInt(w).asInstanceOf[this.type] private[chisel3] def toType = s"UInt$width" -- cgit v1.2.3 From 21a3c12b309df88cdb8114c01ef35b044282d647 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Tue, 19 Jul 2016 16:16:35 -0700 Subject: Fix LitBinding and MultiAssign tests. --- chiselFrontend/src/main/scala/chisel3/core/Bits.scala | 2 +- src/test/scala/chiselTests/MultiAssign.scala | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala index df1296dd..1bdf66f1 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala @@ -530,7 +530,7 @@ private[core] sealed trait UIntFactory { val lit = ULit(value, width) val result = new UInt(lit.width, Some(lit)) // Bind result to being an Literal -// result.binding = LitBinding() + result.binding = LitBinding() result } diff --git a/src/test/scala/chiselTests/MultiAssign.scala b/src/test/scala/chiselTests/MultiAssign.scala index fc6c5edc..2399267e 100644 --- a/src/test/scala/chiselTests/MultiAssign.scala +++ b/src/test/scala/chiselTests/MultiAssign.scala @@ -34,8 +34,12 @@ class MultiAssignSpec extends ChiselFlatSpec { "The last assignment" should "be used when multiple assignments happen" in { assertTesterPasses{ new LastAssignTester } } - intercept[chisel3.internal.ChiselException] { -// "Reassignments to non-wire types" should "be disallowed" in { - assertTesterFails{ new ReassignmentTester } +} + +class IllegalAssignSpec extends ChiselFlatSpec { + "Reassignments to non-wire types" should "be disallowed" in { + intercept[chisel3.internal.ChiselException] { + assertTesterFails{ new ReassignmentTester } + } } } -- cgit v1.2.3 From 01e14c8c885527861152443f1233fa77b03cb8b5 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Tue, 19 Jul 2016 16:51:21 -0700 Subject: Merge in "complete" versions of Mem, Reg. --- .../src/main/scala/chisel3/core/Mem.scala | 31 +++++++++++++++------- .../src/main/scala/chisel3/core/Reg.scala | 22 +++++++++------ .../src/main/scala/chisel3/internal/Builder.scala | 6 ++++- 3 files changed, 41 insertions(+), 18 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/Mem.scala b/chiselFrontend/src/main/scala/chisel3/core/Mem.scala index 38f5ef14..5c1b5976 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Mem.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Mem.scala @@ -19,9 +19,11 @@ object Mem { * @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 mt = t.newType + Binding.bind(mt, NoDirectionBinder, "Error: fresh t") + // TODO(twigg): Remove need for this Binding + val mem = new Mem(mt, size) pushCommand(DefMemory(sourceInfo, mem, mt, size)) // TODO multi-clock mem @@ -60,7 +62,7 @@ sealed abstract class MemBase[T <: Data](t: T, val length: Int) extends HasId wi * * @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 + * @param mask write mask as a Seq 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 @@ -79,9 +81,17 @@ sealed abstract class MemBase[T <: Data](t: T, val length: Int) extends HasId wi 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 + private def makePort(sourceInfo: SourceInfo, idx: UInt, dir: MemPortDirection): T = { + Binding.checkSynthesizable(idx, s"'idx' ($idx)") + + val port = pushCommand( + DefMemPort(sourceInfo, + t.newType, Node(this), dir, idx.ref, Node(idx._parent.get.clock)) + ).id + // Bind each element of port to being a MemoryPort + Binding.bind(port, MemoryPortBinder(Builder.forcedModule), "Error: Fresh t") + port + } } /** A combinational-read, sequential-write memory. @@ -93,7 +103,7 @@ sealed abstract class MemBase[T <: Data](t: T, val length: Int) extends HasId wi * @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) +final class Mem[T <: Data] private (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") @@ -107,7 +117,10 @@ object SeqMem { 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 mt = t.newType + Binding.bind(mt, NoDirectionBinder, "Error: fresh t") + // TODO(twigg): Remove need for this Binding + val mem = new SeqMem(mt, size) pushCommand(DefSeqMemory(sourceInfo, mem, mt, size)) // TODO multi-clock mem @@ -124,7 +137,7 @@ object SeqMem { * @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) { +final class SeqMem[T <: Data] private (t: T, n: Int) extends MemBase[T](t, n) { def read(addr: UInt, enable: Bool): T = { implicit val sourceInfo = UnlocatableSourceInfo val a = Wire(UInt()) diff --git a/chiselFrontend/src/main/scala/chisel3/core/Reg.scala b/chiselFrontend/src/main/scala/chisel3/core/Reg.scala index 14ae9650..df760b5c 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Reg.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Reg.scala @@ -11,18 +11,17 @@ 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) { + Binding.checkUnbound(t, s"t ($t) must be unbound Type. Try using newType?") + t.newType + } 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 + // For e.g. Reg(init=0.asUInt(k)), fix the Reg's width to k + case Some(lit) if lit.forcedWidth => init.newType case _ => init.cloneTypeWidth(Width()) } - } else { - throwException("cannot infer type") } + else throw new Exception("cannot infer type") } /** Creates a register with optional next and initialization values. @@ -59,14 +58,21 @@ init: T = null): T = { // system improves, this may be changed. val x = makeType(t, next, init) val clock = Node(x._parent.get.clock) // TODO multi-clock + + // Bind each element of x to being a Reg + Binding.bind(x, RegBinder(Builder.forcedModule), "Error: t") + if (init == null) { pushCommand(DefReg(sourceInfo, x, clock)) } else { + Binding.checkSynthesizable(init, s"'init' ($init)") pushCommand(DefRegInit(sourceInfo, x, clock, Node(x._parent.get.reset), init.ref)) } if (next != null) { + Binding.checkSynthesizable(next, s"'next' ($next)") x := next } + x } } diff --git a/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala b/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala index e5b85736..168e19b2 100644 --- a/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala +++ b/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala @@ -124,7 +124,11 @@ private[chisel3] object Builder { forcedModule._commands += c c } - def pushOp[T <: Data](cmd: DefPrim[T]): T = pushCommand(cmd).id + def pushOp[T <: Data](cmd: DefPrim[T]): T = { + // Bind each element of the returned Data to being a Op + Binding.bind(cmd.id, OpBinder(forcedModule), "Error: During op creation, fresh result") + pushCommand(cmd).id + } def errors: ErrorLog = dynamicContext.errors def error(m: => String): Unit = errors.error(m) -- cgit v1.2.3 From f81202b896d30d90075be487895befa009b11733 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Tue, 19 Jul 2016 16:52:27 -0700 Subject: Fixes for only connectwrap version. --- chiselFrontend/src/main/scala/chisel3/core/Mem.scala | 10 +++++----- chiselFrontend/src/main/scala/chisel3/core/Reg.scala | 15 ++++++++------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/Mem.scala b/chiselFrontend/src/main/scala/chisel3/core/Mem.scala index 5c1b5976..a9854362 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Mem.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Mem.scala @@ -20,7 +20,7 @@ object Mem { */ 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.newType + val mt = t.cloneType Binding.bind(mt, NoDirectionBinder, "Error: fresh t") // TODO(twigg): Remove need for this Binding @@ -86,7 +86,7 @@ sealed abstract class MemBase[T <: Data](t: T, val length: Int) extends HasId wi val port = pushCommand( DefMemPort(sourceInfo, - t.newType, Node(this), dir, idx.ref, Node(idx._parent.get.clock)) + t.cloneType, Node(this), dir, idx.ref, Node(idx._parent.get.clock)) ).id // Bind each element of port to being a MemoryPort Binding.bind(port, MemoryPortBinder(Builder.forcedModule), "Error: Fresh t") @@ -103,7 +103,7 @@ sealed abstract class MemBase[T <: Data](t: T, val length: Int) extends HasId wi * @note when multiple conflicting writes are performed on a Mem element, the * result is undefined (unlike Vec, where the last assignment wins) */ -final class Mem[T <: Data] private (t: T, length: Int) extends MemBase(t, length) +sealed class Mem[T <: Data] private (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") @@ -117,7 +117,7 @@ object SeqMem { 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.newType + val mt = t.cloneType Binding.bind(mt, NoDirectionBinder, "Error: fresh t") // TODO(twigg): Remove need for this Binding @@ -137,7 +137,7 @@ object SeqMem { * @note when multiple conflicting writes are performed on a Mem element, the * result is undefined (unlike Vec, where the last assignment wins) */ -final class SeqMem[T <: Data] private (t: T, n: Int) extends MemBase[T](t, n) { +sealed class SeqMem[T <: Data] private (t: T, n: Int) extends MemBase[T](t, n) { def read(addr: UInt, enable: Bool): T = { implicit val sourceInfo = UnlocatableSourceInfo val a = Wire(UInt()) diff --git a/chiselFrontend/src/main/scala/chisel3/core/Reg.scala b/chiselFrontend/src/main/scala/chisel3/core/Reg.scala index df760b5c..b46b96ef 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Reg.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Reg.scala @@ -12,16 +12,18 @@ object Reg { init: T = null): T = { if (t ne null) { Binding.checkUnbound(t, s"t ($t) must be unbound Type. Try using newType?") - t.newType - } else if (next ne null) next.cloneTypeWidth(Width()) - else if (init 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=0.asUInt(k)), fix the Reg's width to k - case Some(lit) if lit.forcedWidth => init.newType + // 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") } - else throw new Exception("cannot infer type") } /** Creates a register with optional next and initialization values. @@ -72,7 +74,6 @@ init: T = null): T = { Binding.checkSynthesizable(next, s"'next' ($next)") x := next } - x } } -- cgit v1.2.3 From 28e80311f172ae4d1d477e8bb47ca3719c9a8fc5 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Wed, 20 Jul 2016 13:28:15 -0700 Subject: Compile ok. Need to convert UInt(x) into UInt.Lit(x) or UInt.width(x) --- .../src/main/scala/chisel3/core/Aggregate.scala | 7 +++++-- chiselFrontend/src/main/scala/chisel3/core/Bits.scala | 19 ++++++++++++++----- chiselFrontend/src/main/scala/chisel3/core/Data.scala | 13 ++++++++++++- src/main/scala/chisel3/package.scala | 8 +++++++- src/main/scala/chisel3/util/BitPat.scala | 4 ++-- src/main/scala/chisel3/util/Decoupled.scala | 6 +++++- src/main/scala/chisel3/util/Valid.scala | 6 +++++- src/test/scala/chiselTests/GCD.scala | 14 +++++++------- src/test/scala/chiselTests/Module.scala | 2 +- src/test/scala/chiselTests/Risc.scala | 12 ++++++------ 10 files changed, 64 insertions(+), 27 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala index 1b49e163..666d8283 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala @@ -179,8 +179,11 @@ sealed class Vec[T <: Data] private (gen: => T, val length: Int) @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] + override def cloneType: this.type = { + val clone = Vec(length, gen).asInstanceOf[this.type] + clone.unBind() + clone + } private[chisel3] def toType: String = s"${sample_element.toType}[$length]" private[chisel3] lazy val flatten: IndexedSeq[Bits] = diff --git a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala index 1bdf66f1..e8aae578 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala @@ -51,7 +51,11 @@ sealed abstract class Bits(width: Width, override val litArg: Option[LitArg]) private[chisel3] def flatten: IndexedSeq[Bits] = IndexedSeq(this) - def cloneType: this.type = cloneTypeWidth(width) + def cloneType: this.type = { + val clone = cloneTypeWidth(width) + clone.unBind() + clone + } final def tail(n: Int): UInt = macro SourceInfoTransform.nArg final def head(n: Int): UInt = macro SourceInfoTransform.nArg @@ -514,12 +518,12 @@ sealed class UInt private[core] (width: Width, lit: Option[ULit] = None) private[core] sealed trait UIntFactory { /** Create a UInt type with inferred width. */ def apply(): UInt = apply(Width()) + /** Create a UInt type or port with fixed width. */ + def apply(width: Int): UInt = apply(Width(width)) /** Create a UInt port with specified width. */ def apply(width: Width): UInt = new UInt(width) /** Create a UInt with a specified width - compatibility with Chisel2. */ - def apply(dummy: Option[Direction] = None, width: Int): UInt = apply(Width(width)) - /** Create a UInt literal with inferred width. */ - def apply(value: BigInt): UInt = apply(value, Width()) + def apply(dummy: Direction, width: Int): UInt = apply(Width(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. */ @@ -733,7 +737,12 @@ object Bool { /** Creates Bool literal. */ - def apply(x: Boolean): Bool = new Bool(Some(ULit(if (x) 1 else 0, Width(1)))) + def apply(x: Boolean): Bool = { + val result = new Bool(Some(ULit(if (x) 1 else 0, Width(1)))) + // Bind result to being an Literal + result.binding = LitBinding() + result + } } object Mux { diff --git a/chiselFrontend/src/main/scala/chisel3/core/Data.scala b/chiselFrontend/src/main/scala/chisel3/core/Data.scala index 4cc66cb5..79119114 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Data.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Data.scala @@ -174,6 +174,13 @@ abstract class Data extends HasId { */ @deprecated("Use asBits, which makes the reinterpret cast more explicit and actually returns Bits", "chisel3") def toBits(): UInt = SeqUtils.do_asUInt(this.flatten)(DeprecatedSourceInfo) + + protected def unBind(): Unit = { + //TODO(twigg): Do recursively for better error messages + for(elem <- this.allElements) { + elem.binding = UnboundBinding(elem.binding.direction) + } + } } object Wire { @@ -210,7 +217,11 @@ object Clock { // TODO: Document this. sealed class Clock extends Element(Width(1)) { - def cloneType: this.type = Clock().asInstanceOf[this.type] + def cloneType: this.type = { + val clone = Clock().asInstanceOf[this.type] + clone.unBind() + clone + } private[chisel3] override def flatten: IndexedSeq[Bits] = IndexedSeq() private[chisel3] def cloneTypeWidth(width: Width): this.type = cloneType private[chisel3] def toType = "Clock" diff --git a/src/main/scala/chisel3/package.scala b/src/main/scala/chisel3/package.scala index 71ec0e92..86fce6a2 100644 --- a/src/main/scala/chisel3/package.scala +++ b/src/main/scala/chisel3/package.scala @@ -1,9 +1,10 @@ +// See LICENSE for license details. + package object chisel3 { import scala.language.experimental.macros import internal.firrtl.Width import internal.sourceinfo.{SourceInfo, SourceInfoTransform} - import util.BitPat @@ -87,6 +88,11 @@ package object chisel3 { implicit class fromBigIntToLiteral(val x: BigInt) extends AnyVal { def U: UInt = UInt(x, Width()) def S: SInt = SInt(x, Width()) + + def asUInt() = UInt(x, Width()) + def asSInt() = SInt(x, Width()) + def asUInt(width: Int) = UInt(x, width) + def asSInt(width: Int) = SInt(x, width) } implicit class fromStringToLiteral(val x: String) extends AnyVal { def U: UInt = UInt(x) diff --git a/src/main/scala/chisel3/util/BitPat.scala b/src/main/scala/chisel3/util/BitPat.scala index 9eb5cf67..3ae192a2 100644 --- a/src/main/scala/chisel3/util/BitPat.scala +++ b/src/main/scala/chisel3/util/BitPat.scala @@ -75,7 +75,7 @@ object BitPat { // 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)). + * BitPat(0b10?1) === 0b1001.asUInt and 0b1011.asUInt. */ sealed class BitPat(val value: BigInt, val mask: BigInt, width: Int) { def getWidth: Int = width @@ -83,7 +83,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 = value.asUInt === (that & mask.asUInt) 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/Decoupled.scala b/src/main/scala/chisel3/util/Decoupled.scala index 4a6b72e9..fb1ee6b9 100644 --- a/src/main/scala/chisel3/util/Decoupled.scala +++ b/src/main/scala/chisel3/util/Decoupled.scala @@ -58,7 +58,11 @@ object DecoupledIO { target.ready := Bool(false) } } -// override def cloneType: this.type = { DeqIO(gen).asInstanceOf[this.type]; } +// override def cloneType: this.type = { +// val clone = DeqIO(gen).asInstanceOf[this.type] +// clone.unBind() +// clone +// } } object EnqIO { diff --git a/src/main/scala/chisel3/util/Valid.scala b/src/main/scala/chisel3/util/Valid.scala index 4078a76a..5641f0f2 100644 --- a/src/main/scala/chisel3/util/Valid.scala +++ b/src/main/scala/chisel3/util/Valid.scala @@ -13,7 +13,11 @@ class Valid[+T <: Data](gen: T) extends Bundle val valid = Output(Bool()) val bits = Output(gen.cloneType) def fire(dummy: Int = 0): Bool = valid - override def cloneType: this.type = Valid(gen).asInstanceOf[this.type] + override def cloneType: this.type = { + val clone = Valid(gen).asInstanceOf[this.type] + clone.unBind() + clone + } } /** Adds a valid protocol to any interface */ diff --git a/src/test/scala/chiselTests/GCD.scala b/src/test/scala/chiselTests/GCD.scala index a8b907af..7c04ae00 100644 --- a/src/test/scala/chiselTests/GCD.scala +++ b/src/test/scala/chiselTests/GCD.scala @@ -21,18 +21,18 @@ class GCD extends Module { .otherwise { y := y -% x } when (io.e) { x := io.a; y := io.b } io.z := x - io.v := y === UInt(0) + io.v := y === 0.U } class GCDTester(a: Int, b: Int, z: Int) extends BasicTester { val dut = Module(new GCD) - val first = Reg(init=Bool(true)) - dut.io.a := UInt(a) - dut.io.b := UInt(b) + val first = Reg(init=true.B) + dut.io.a := a.U + dut.io.b := b.U dut.io.e := first - when(first) { first := Bool(false) } - when(dut.io.v) { - assert(dut.io.z === UInt(z)) + when(first) { first := false.B } + when(!first && dut.io.v) { + assert(dut.io.z === z.U) stop() } } diff --git a/src/test/scala/chiselTests/Module.scala b/src/test/scala/chiselTests/Module.scala index f1608d5b..857aeda3 100644 --- a/src/test/scala/chiselTests/Module.scala +++ b/src/test/scala/chiselTests/Module.scala @@ -11,7 +11,7 @@ class SimpleIO extends Bundle { class PlusOne extends Module { val io = IO(new SimpleIO) - io.out := io.in + UInt(1) + io.out := io.in + 1.asUInt } class ModuleVec(val n: Int) extends Module { diff --git a/src/test/scala/chiselTests/Risc.scala b/src/test/scala/chiselTests/Risc.scala index fafec95a..c110d37e 100644 --- a/src/test/scala/chiselTests/Risc.scala +++ b/src/test/scala/chiselTests/Risc.scala @@ -27,13 +27,13 @@ class Risc extends Module { val rai = inst(15, 8) val rbi = inst( 7, 0) - val ra = Mux(rai === Bits(0), Bits(0), file(rai)) - val rb = Mux(rbi === Bits(0), Bits(0), file(rbi)) + val ra = Mux(rai === 0.asUInt(), 0.asUInt(), file(rai)) + val rb = Mux(rbi === 0.asUInt(), 0.asUInt(), file(rbi)) val rc = Wire(Bits(width = 32)) io.valid := Bool(false) - io.out := Bits(0) - rc := Bits(0) + io.out := 0.asUInt() + rc := 0.asUInt() when (io.isWr) { code(io.wrAddr) := io.wrData @@ -45,12 +45,12 @@ class Risc extends Module { is(imm_op) { rc := (rai << 8) | rbi } } io.out := rc - when (rci === UInt(255)) { + when (rci === 255.asUInt()) { io.valid := Bool(true) } .otherwise { file(rci) := rc } - pc := pc +% UInt(1) + pc := pc +% 1.asUInt() } } -- 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 From 2dce378deda1cc33833eb378c89a1c5415817bae Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Wed, 20 Jul 2016 14:49:35 -0700 Subject: Distinguish between ?Int.Lit and ?Int.width --- .../src/main/scala/chisel3/core/Aggregate.scala | 2 +- .../src/main/scala/chisel3/core/Bits.scala | 60 +++++++++++++++------- .../src/main/scala/chisel3/core/Mem.scala | 2 +- .../src/main/scala/chisel3/core/SeqUtils.scala | 4 +- .../src/main/scala/chisel3/core/When.scala | 4 +- src/main/scala/chisel3/package.scala | 2 +- src/main/scala/chisel3/util/Arbiter.scala | 12 ++--- src/main/scala/chisel3/util/CircuitMath.scala | 4 +- src/main/scala/chisel3/util/Counter.scala | 10 ++-- src/main/scala/chisel3/util/Decoupled.scala | 4 +- .../scala/chisel3/util/ImplicitConversions.scala | 2 +- src/main/scala/chisel3/util/OneHot.scala | 4 +- src/test/scala/chiselTests/Assert.scala | 4 +- src/test/scala/chiselTests/BlackBox.scala | 30 +++++------ src/test/scala/chiselTests/BundleWire.scala | 8 +-- src/test/scala/chiselTests/ComplexAssign.scala | 12 ++--- src/test/scala/chiselTests/Counter.scala | 8 +-- src/test/scala/chiselTests/Decoder.scala | 4 +- src/test/scala/chiselTests/Direction.scala | 8 +-- .../scala/chiselTests/EnableShiftRegister.scala | 4 +- src/test/scala/chiselTests/GCD.scala | 6 +-- src/test/scala/chiselTests/LFSR16.scala | 2 +- src/test/scala/chiselTests/MemorySearch.scala | 10 ++-- src/test/scala/chiselTests/Module.scala | 8 +-- src/test/scala/chiselTests/MulLookup.scala | 12 ++--- src/test/scala/chiselTests/Padding.scala | 6 +-- src/test/scala/chiselTests/Printf.scala | 6 +-- src/test/scala/chiselTests/Reg.scala | 2 +- src/test/scala/chiselTests/Risc.scala | 4 +- src/test/scala/chiselTests/SIntOps.scala | 26 +++++----- src/test/scala/chiselTests/Stack.scala | 16 +++--- src/test/scala/chiselTests/Tbl.scala | 10 ++-- src/test/scala/chiselTests/TesterDriverSpec.scala | 6 +-- src/test/scala/chiselTests/UIntOps.scala | 24 ++++----- src/test/scala/chiselTests/Vec.scala | 6 +-- src/test/scala/chiselTests/When.scala | 36 ++++++------- 36 files changed, 195 insertions(+), 173 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala index 666d8283..a80dfec8 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala @@ -241,7 +241,7 @@ trait VecLike[T <: Data] extends collection.IndexedSeq[T] with HasId { /** 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)) + private def indexWhereHelper(p: T => Bool) = this map p zip (0 until length).map(i => UInt.Lit(i)) /** Outputs the index of the first element for which p outputs true. */ diff --git a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala index e8aae578..3580b5f3 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala @@ -270,9 +270,9 @@ sealed abstract class Bits(width: Width, override val litArg: Option[LitArg]) def do_toBool(implicit sourceInfo: SourceInfo): Bool = { width match { - case KnownWidth(1) => this(0) - case _ => throwException(s"can't covert UInt<$width> to Bool") - } + 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 @@ -407,8 +407,8 @@ sealed class UInt private[core] (width: Width, lit: Option[ULit] = None) 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 + def do_unary_- (implicit sourceInfo: SourceInfo) : UInt = UInt.Lit(0) - this + def do_unary_-% (implicit sourceInfo: SourceInfo): UInt = UInt.Lit(0) -% this override def do_+ (that: UInt)(implicit sourceInfo: SourceInfo): UInt = this +% that override def do_- (that: UInt)(implicit sourceInfo: SourceInfo): UInt = this -% that @@ -456,8 +456,8 @@ sealed class UInt private[core] (width: Width, lit: Option[ULit] = None) 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_orR(implicit sourceInfo: SourceInfo): Bool = this != UInt.Lit(0) + def do_andR(implicit sourceInfo: SourceInfo): Bool = ~this === UInt.Lit(0) def do_xorR(implicit sourceInfo: SourceInfo): Bool = redop(sourceInfo, XorReduceOp) override def do_< (that: UInt)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, LessOp, that) @@ -523,14 +523,25 @@ private[core] sealed trait UIntFactory { /** Create a UInt port with specified width. */ def apply(width: Width): UInt = new UInt(width) /** Create a UInt with a specified width - compatibility with Chisel2. */ + def width(width: Int): UInt = apply(Width(width)) + /** Create a UInt port with specified width. */ + def width(width: Width): UInt = new UInt(width) + /** Create a UInt with a specified width - compatibility with Chisel2. */ def apply(dummy: Direction, width: Int): UInt = apply(Width(width)) /** Create a UInt literal with fixed width. */ - def apply(value: BigInt, width: Int): UInt = apply(value, Width(width)) + def apply(value: BigInt, width: Int): UInt = Lit(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): UInt = Lit(n) /** Create a UInt literal with specified width. */ - def apply(value: BigInt, width: Width): UInt = { + def apply(value: BigInt, width: Width): UInt = Lit(value, width) + def Lit(value: BigInt, width: Int): UInt = Lit(value, Width(width)) + /** Create a UInt literal with inferred width. */ + def Lit(value: BigInt): UInt = Lit(value, Width()) + def Lit(n: String): UInt = Lit(parse(n), parsedWidth(n)) + /** Create a UInt literal with fixed width. */ + def Lit(n: String, width: Int): UInt = Lit(parse(n), width) + /** Create a UInt literal with specified width. */ + def Lit(value: BigInt, width: Width): UInt = { val lit = ULit(value, width) val result = new UInt(lit.width, Some(lit)) // Bind result to being an Literal @@ -575,8 +586,8 @@ sealed class SInt private (width: Width, lit: Option[SLit] = None) 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 + def unary_- (implicit sourceInfo: SourceInfo): SInt = SInt.Lit(0) - this + def unary_-% (implicit sourceInfo: SourceInfo): SInt = SInt.Lit(0) -% this /** add (default - no growth) operator */ override def do_+ (that: SInt)(implicit sourceInfo: SourceInfo): SInt = @@ -643,7 +654,7 @@ sealed class SInt private (width: Width, lit: Option[SLit] = None) final def abs(): UInt = macro SourceInfoTransform.noArg - def do_abs(implicit sourceInfo: SourceInfo): UInt = Mux(this < SInt(0), (-this).asUInt, this.asUInt) + def do_abs(implicit sourceInfo: SourceInfo): UInt = Mux(this < SInt.Lit(0), (-this).asUInt, this.asUInt) override def do_<< (that: Int)(implicit sourceInfo: SourceInfo): SInt = binop(sourceInfo, SInt(this.width + that), ShiftLeftOp, that) @@ -669,14 +680,24 @@ object SInt { def apply(width: Int): SInt = apply(Width(width)) /** Create an SInt type with specified width. */ def apply(width: Width): SInt = new SInt(width) + /** Create a SInt type or port with fixed width. */ + def width(width: Int): SInt = apply(Width(width)) + /** Create an SInt type with specified width. */ + def width(width: Width): SInt = new SInt(width) /** Create an SInt literal with inferred width. */ - def apply(value: BigInt): SInt = apply(value, Width()) + def apply(value: BigInt): SInt = Lit(value) /** Create an SInt literal with fixed width. */ - def apply(value: BigInt, width: Int): SInt = apply(value, Width(width)) + def apply(value: BigInt, width: Int): SInt = Lit(value, width) /** Create an SInt literal with specified width. */ - def apply(value: BigInt, width: Width): SInt = { + def apply(value: BigInt, width: Width): SInt = Lit(value, width) + + def Lit(value: BigInt): SInt = Lit(value, Width()) + def Lit(value: BigInt, width: Int): SInt = Lit(value, Width(width)) + /** Create an SInt literal with specified width. */ + def Lit(value: BigInt, width: Width): SInt = { + val lit = SLit(value, width) val result = new SInt(lit.width, Some(lit)) // Bind result to being an Literal @@ -737,7 +758,8 @@ object Bool { /** Creates Bool literal. */ - def apply(x: Boolean): Bool = { + def apply(x: Boolean): Bool = Lit(x) + def Lit(x: Boolean): Bool = { val result = new Bool(Some(ULit(if (x) 1 else 0, Width(1)))) // Bind result to being an Literal result.binding = LitBinding() @@ -754,7 +776,7 @@ object Mux { * @param alt the value chosen when `cond` is false * @example * {{{ - * val muxOut = Mux(data_in === UInt(3), UInt(3, 4), UInt(0, 4)) + * val muxOut = Mux(data_in === UInt.Lit(3), UInt(3, 4), UInt(0, 4)) * }}} */ def apply[T <: Data](cond: Bool, con: T, alt: T): T = macro MuxTransform.apply[T] diff --git a/chiselFrontend/src/main/scala/chisel3/core/Mem.scala b/chiselFrontend/src/main/scala/chisel3/core/Mem.scala index a9854362..a4e6bee3 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Mem.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Mem.scala @@ -36,7 +36,7 @@ sealed abstract class MemBase[T <: Data](t: T, val length: Int) extends HasId wi /** 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)) + def apply(idx: Int): T = apply(UInt.Lit(idx)) /** Creates a read/write accessor into the memory with dynamic addressing. * See the class documentation of the memory for more detailed information. diff --git a/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala b/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala index 91cb9e89..c1ec6b90 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala @@ -25,11 +25,11 @@ private[chisel3] object SeqUtils { def do_count(in: Seq[Bool])(implicit sourceInfo: SourceInfo): UInt = { if (in.size == 0) { - UInt(0) + UInt.Lit(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))) + count(in.slice(0, in.size/2)) + (UInt.Lit(0) ## count(in.slice(in.size/2, in.size))) } } diff --git a/chiselFrontend/src/main/scala/chisel3/core/When.scala b/chiselFrontend/src/main/scala/chisel3/core/When.scala index 196e7903..7049eb82 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/When.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/When.scala @@ -18,9 +18,9 @@ object when { // scalastyle:ignore object.name * * @example * {{{ - * when ( myData === UInt(3) ) { + * when ( myData === UInt.Lit(3) ) { * // Some logic to run when myData equals 3. - * } .elsewhen ( myData === UInt(1) ) { + * } .elsewhen ( myData === UInt.Lit(1) ) { * // Some logic to run when myData equals 1. * } .otherwise { * // Some logic to run when myData is neither 3 nor 1. diff --git a/src/main/scala/chisel3/package.scala b/src/main/scala/chisel3/package.scala index 86fce6a2..e43434c0 100644 --- a/src/main/scala/chisel3/package.scala +++ b/src/main/scala/chisel3/package.scala @@ -95,7 +95,7 @@ package object chisel3 { def asSInt(width: Int) = SInt(x, width) } implicit class fromStringToLiteral(val x: String) extends AnyVal { - def U: UInt = UInt(x) + def U: UInt = UInt.Lit(x) } implicit class fromBooleanToLiteral(val x: Boolean) extends AnyVal { def B: Bool = Bool(x) diff --git a/src/main/scala/chisel3/util/Arbiter.scala b/src/main/scala/chisel3/util/Arbiter.scala index a5397682..44cc88b6 100644 --- a/src/main/scala/chisel3/util/Arbiter.scala +++ b/src/main/scala/chisel3/util/Arbiter.scala @@ -36,7 +36,7 @@ abstract class LockingArbiterLike[T <: Data](gen: T, n: Int, count: Int, needsLo if (count > 1) { val lockCount = Counter(count) val lockIdx = Reg(UInt()) - val locked = lockCount.value =/= UInt(0) + val locked = lockCount.value =/= UInt.Lit(0) val wantsLock = needsLock.map(_(io.out.bits)).getOrElse(Bool(true)) when (io.out.firing && wantsLock) { @@ -46,7 +46,7 @@ abstract class LockingArbiterLike[T <: Data](gen: T, n: Int, count: Int, needsLo 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 + in.ready := Mux(locked, lockIdx === UInt.Lit(i), g) && io.out.ready } else { for ((in, g) <- io.in zip grant) in.ready := g && io.out.ready @@ -66,9 +66,9 @@ class LockingRRArbiter[T <: Data](gen: T, n: Int, count: Int, needsLock: Option[ 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) } + when (io.in(i).valid) { choice := UInt.Lit(i) } for (i <- n-1 to 1 by -1) - when (validMask(i)) { choice := UInt(i) } + when (validMask(i)) { choice := UInt.Lit(i) } } class LockingArbiter[T <: Data](gen: T, n: Int, count: Int, needsLock: Option[T => Bool] = None) @@ -77,7 +77,7 @@ class LockingArbiter[T <: Data](gen: T, n: Int, count: Int, needsLock: Option[T 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) } + when (io.in(i).valid) { choice := UInt.Lit(i) } } /** Hardware module that is used to sequence n producers into 1 consumer. @@ -107,7 +107,7 @@ class Arbiter[T <: Data](gen: T, n: Int) extends Module { 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.chosen := UInt.Lit(i) io.out.bits := io.in(i).bits } } diff --git a/src/main/scala/chisel3/util/CircuitMath.scala b/src/main/scala/chisel3/util/CircuitMath.scala index 1174c71c..5e93b009 100644 --- a/src/main/scala/chisel3/util/CircuitMath.scala +++ b/src/main/scala/chisel3/util/CircuitMath.scala @@ -11,12 +11,12 @@ import chisel3._ * 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*/ + * @note Truncation is used so Log2(UInt.Lit(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) + UInt.Lit(0) } else if (width == 2) { x(1) } else { diff --git a/src/main/scala/chisel3/util/Counter.scala b/src/main/scala/chisel3/util/Counter.scala index 40615769..05d8fba8 100644 --- a/src/main/scala/chisel3/util/Counter.scala +++ b/src/main/scala/chisel3/util/Counter.scala @@ -10,17 +10,17 @@ import chisel3._ */ class Counter(val n: Int) { require(n >= 0) - val value = if (n > 1) Reg(init=UInt(0, log2Up(n))) else UInt(0) + val value = if (n > 1) Reg(init=UInt(0, log2Up(n))) else UInt.Lit(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) + val wrap = value === UInt.Lit(n-1) + value := value + UInt.Lit(1) if (!isPow2(n)) { - when (wrap) { value := UInt(0) } + when (wrap) { value := UInt.Lit(0) } } wrap } else { @@ -33,7 +33,7 @@ class Counter(val n: Int) { * Example Usage: * {{{ val countOn = Bool(true) // increment counter every clock cycle * val myCounter = Counter(countOn, n) - * when ( myCounter.value === UInt(3) ) { ... } }}}*/ + * when ( myCounter.value === UInt.Lit(3) ) { ... } }}}*/ object Counter { def apply(n: Int): Counter = new Counter(n) diff --git a/src/main/scala/chisel3/util/Decoupled.scala b/src/main/scala/chisel3/util/Decoupled.scala index fb1ee6b9..5958c744 100644 --- a/src/main/scala/chisel3/util/Decoupled.scala +++ b/src/main/scala/chisel3/util/Decoupled.scala @@ -153,9 +153,9 @@ extends Module(override_reset=override_reset) { } else { io.count := Mux(ptr_match, Mux(maybe_full, - UInt(entries), UInt(0)), + UInt.Lit(entries), UInt.Lit(0)), Mux(deq_ptr.value > enq_ptr.value, - UInt(entries) + ptr_diff, ptr_diff)) + UInt.Lit(entries) + ptr_diff, ptr_diff)) } } diff --git a/src/main/scala/chisel3/util/ImplicitConversions.scala b/src/main/scala/chisel3/util/ImplicitConversions.scala index 4d816a19..3a9089c5 100644 --- a/src/main/scala/chisel3/util/ImplicitConversions.scala +++ b/src/main/scala/chisel3/util/ImplicitConversions.scala @@ -5,6 +5,6 @@ package chisel3.util import chisel3._ object ImplicitConversions { - implicit def intToUInt(x: Int): UInt = UInt(x) + implicit def intToUInt(x: Int): UInt = UInt.Lit(x) implicit def booleanToBool(x: Boolean): Bool = Bool(x) } diff --git a/src/main/scala/chisel3/util/OneHot.scala b/src/main/scala/chisel3/util/OneHot.scala index 820c72d6..8a5caf44 100644 --- a/src/main/scala/chisel3/util/OneHot.scala +++ b/src/main/scala/chisel3/util/OneHot.scala @@ -41,9 +41,9 @@ object UIntToOH { def apply(in: UInt, width: Int = -1): UInt = if (width == -1) { - UInt(1) << in + UInt.Lit(1) << in } else { - (UInt(1) << in(log2Up(width)-1,0))(width-1,0) + (UInt.Lit(1) << in(log2Up(width)-1,0))(width-1,0) } } diff --git a/src/test/scala/chiselTests/Assert.scala b/src/test/scala/chiselTests/Assert.scala index efc2e1e7..bf3c8092 100644 --- a/src/test/scala/chiselTests/Assert.scala +++ b/src/test/scala/chiselTests/Assert.scala @@ -27,8 +27,8 @@ class SucceedingAssertTester() extends BasicTester { class PipelinedResetModule extends Module { val io = IO(new Bundle { }) - val a = Reg(init = UInt(0xbeef)) - val b = Reg(init = UInt(0xbeef)) + val a = Reg(init = UInt.Lit(0xbeef)) + val b = Reg(init = UInt.Lit(0xbeef)) assert(a === b) } diff --git a/src/test/scala/chiselTests/BlackBox.scala b/src/test/scala/chiselTests/BlackBox.scala index c1154883..9b43f0ef 100644 --- a/src/test/scala/chiselTests/BlackBox.scala +++ b/src/test/scala/chiselTests/BlackBox.scala @@ -35,11 +35,11 @@ class BlackBoxTester extends BasicTester { val blackBoxPos = Module(new BlackBoxInverter) val blackBoxNeg = Module(new BlackBoxInverter) - blackBoxPos.io.in := UInt(1) - blackBoxNeg.io.in := UInt(0) + blackBoxPos.io.in := UInt.Lit(1) + blackBoxNeg.io.in := UInt.Lit(0) - assert(blackBoxNeg.io.out === UInt(1)) - assert(blackBoxPos.io.out === UInt(0)) + assert(blackBoxNeg.io.out === UInt.Lit(1)) + assert(blackBoxPos.io.out === UInt.Lit(0)) stop() } @@ -54,15 +54,15 @@ class MultiBlackBoxTester extends BasicTester { val blackBoxPassPos = Module(new BlackBoxPassthrough) val blackBoxPassNeg = Module(new BlackBoxPassthrough) - blackBoxInvPos.io.in := UInt(1) - blackBoxInvNeg.io.in := UInt(0) - blackBoxPassPos.io.in := UInt(1) - blackBoxPassNeg.io.in := UInt(0) + blackBoxInvPos.io.in := UInt.Lit(1) + blackBoxInvNeg.io.in := UInt.Lit(0) + blackBoxPassPos.io.in := UInt.Lit(1) + blackBoxPassNeg.io.in := UInt.Lit(0) - assert(blackBoxInvNeg.io.out === UInt(1)) - assert(blackBoxInvPos.io.out === UInt(0)) - assert(blackBoxPassNeg.io.out === UInt(0)) - assert(blackBoxPassPos.io.out === UInt(1)) + assert(blackBoxInvNeg.io.out === UInt.Lit(1)) + assert(blackBoxInvPos.io.out === UInt.Lit(0)) + assert(blackBoxPassNeg.io.out === UInt.Lit(0)) + assert(blackBoxPassPos.io.out === UInt.Lit(1)) stop() } @@ -77,7 +77,7 @@ class BlackBoxWithClockTester extends BasicTester { blackBox.io.in := impetus model := impetus - when(cycles > UInt(0)) { + when(cycles > UInt.Lit(0)) { assert(blackBox.io.out === model) } when(end) { stop() } @@ -98,8 +98,8 @@ class BlackBoxWithParamsTester extends BasicTester { val (cycles, end) = Counter(Bool(true), 4) - assert(blackBoxOne.io.out === UInt(1)) - assert(blackBoxFour.io.out === UInt(4)) + assert(blackBoxOne.io.out === UInt.Lit(1)) + assert(blackBoxFour.io.out === UInt.Lit(4)) when(end) { stop() } } diff --git a/src/test/scala/chiselTests/BundleWire.scala b/src/test/scala/chiselTests/BundleWire.scala index 029407dd..2f6322b1 100644 --- a/src/test/scala/chiselTests/BundleWire.scala +++ b/src/test/scala/chiselTests/BundleWire.scala @@ -25,11 +25,11 @@ class BundleWire(n: Int) extends Module { class BundleWireTester(n: Int, x: Int, y: Int) extends BasicTester { val dut = Module(new BundleWire(n)) - dut.io.in.x := UInt(x) - dut.io.in.y := UInt(y) + dut.io.in.x := UInt.Lit(x) + dut.io.in.y := UInt.Lit(y) for (elt <- dut.io.outs) { - assert(elt.x === UInt(x)) - assert(elt.y === UInt(y)) + assert(elt.x === UInt.Lit(x)) + assert(elt.y === UInt.Lit(y)) } stop() } diff --git a/src/test/scala/chiselTests/ComplexAssign.scala b/src/test/scala/chiselTests/ComplexAssign.scala index e5d1fbea..638ef9b7 100644 --- a/src/test/scala/chiselTests/ComplexAssign.scala +++ b/src/test/scala/chiselTests/ComplexAssign.scala @@ -26,19 +26,19 @@ class ComplexAssign(w: Int) extends Module { io.out.re := tmp.re io.out.im := tmp.im } .otherwise { - io.out.re := UInt(0) - io.out.im := UInt(0) + io.out.re := UInt.Lit(0) + io.out.im := UInt.Lit(0) } } class ComplexAssignTester(enList: List[Boolean], re: Int, im: Int) extends BasicTester { val (cnt, wrap) = Counter(Bool(true), enList.size) val dut = Module(new ComplexAssign(32)) - dut.io.in.re := UInt(re) - dut.io.in.im := UInt(im) + dut.io.in.re := UInt.Lit(re) + dut.io.in.im := UInt.Lit(im) dut.io.e := Vec(enList.map(Bool(_)))(cnt) - val re_correct = dut.io.out.re === Mux(dut.io.e, dut.io.in.re, UInt(0)) - val im_correct = dut.io.out.im === Mux(dut.io.e, dut.io.in.im, UInt(0)) + val re_correct = dut.io.out.re === Mux(dut.io.e, dut.io.in.re, UInt.Lit(0)) + val im_correct = dut.io.out.im === Mux(dut.io.e, dut.io.in.im, UInt.Lit(0)) assert(re_correct && im_correct) when(wrap) { stop() diff --git a/src/test/scala/chiselTests/Counter.scala b/src/test/scala/chiselTests/Counter.scala index 69d8a44a..af2fa550 100644 --- a/src/test/scala/chiselTests/Counter.scala +++ b/src/test/scala/chiselTests/Counter.scala @@ -12,20 +12,20 @@ import chisel3.util._ class CountTester(max: Int) extends BasicTester { val cnt = Counter(max) when(Bool(true)) { cnt.inc() } - when(cnt.value === UInt(max-1)) { + when(cnt.value === UInt.Lit(max-1)) { stop() } } class EnableTester(seed: Int) extends BasicTester { - val ens = Reg(init = UInt(seed)) + val ens = Reg(init = UInt.Lit(seed)) ens := ens >> 1 val (cntEnVal, _) = Counter(ens(0), 32) val (_, done) = Counter(Bool(true), 33) when(done) { - assert(cntEnVal === UInt(popCount(seed))) + assert(cntEnVal === UInt.Lit(popCount(seed))) stop() } } @@ -33,7 +33,7 @@ class EnableTester(seed: Int) extends BasicTester { class WrapTester(max: Int) extends BasicTester { val (cnt, wrap) = Counter(Bool(true), max) when(wrap) { - assert(cnt === UInt(max - 1)) + assert(cnt === UInt.Lit(max - 1)) stop() } } diff --git a/src/test/scala/chiselTests/Decoder.scala b/src/test/scala/chiselTests/Decoder.scala index 4a872245..ee892fc5 100644 --- a/src/test/scala/chiselTests/Decoder.scala +++ b/src/test/scala/chiselTests/Decoder.scala @@ -12,7 +12,7 @@ import chisel3.util._ class Decoder(bitpats: List[String]) extends Module { val io = IO(new Bundle { - val inst = Input(UInt(32)) + val inst = Input(UInt.width(32)) val matched = Output(Bool()) }) io.matched := Vec(bitpats.map(BitPat(_) === io.inst)).reduce(_||_) @@ -24,7 +24,7 @@ class DecoderTester(pairs: List[(String, String)]) extends BasicTester { val dut = Module(new Decoder(bitpats)) dut.io.inst := Vec(insts.map(UInt(_)))(cnt) when(!dut.io.matched) { - assert(cnt === UInt(0)) + assert(cnt === UInt.Lit(0)) stop() } when(wrap) { diff --git a/src/test/scala/chiselTests/Direction.scala b/src/test/scala/chiselTests/Direction.scala index 682103f7..e22e120b 100644 --- a/src/test/scala/chiselTests/Direction.scala +++ b/src/test/scala/chiselTests/Direction.scala @@ -9,17 +9,17 @@ import chisel3.testers.BasicTester class DirectionHaver extends Module { val io = IO(new Bundle { - val in = Input(UInt(32)) - val out = Output(UInt(32)) + val in = Input(UInt.width(32)) + val out = Output(UInt.width(32)) }) } class GoodDirection extends DirectionHaver { - io.out := UInt(0) + io.out := UInt.Lit(0) } class BadDirection extends DirectionHaver { - io.in := UInt(0) + io.in := UInt.Lit(0) } class DirectionSpec extends ChiselPropSpec { diff --git a/src/test/scala/chiselTests/EnableShiftRegister.scala b/src/test/scala/chiselTests/EnableShiftRegister.scala index 26af944f..5f3e0dd1 100644 --- a/src/test/scala/chiselTests/EnableShiftRegister.scala +++ b/src/test/scala/chiselTests/EnableShiftRegister.scala @@ -6,9 +6,9 @@ import chisel3.testers.BasicTester class EnableShiftRegister extends Module { val io = IO(new Bundle { - val in = Input(UInt(4)) + val in = Input(UInt.width(4)) val shift = Input(Bool()) - val out = Output(UInt(4)) + val out = Output(UInt.width(4)) }) val r0 = Reg(init = UInt(0, 4)) val r1 = Reg(init = UInt(0, 4)) diff --git a/src/test/scala/chiselTests/GCD.scala b/src/test/scala/chiselTests/GCD.scala index 7c04ae00..d0d945b7 100644 --- a/src/test/scala/chiselTests/GCD.scala +++ b/src/test/scala/chiselTests/GCD.scala @@ -9,10 +9,10 @@ import org.scalatest.prop._ class GCD extends Module { val io = IO(new Bundle { - val a = Input(UInt(32)) - val b = Input(UInt(32)) + val a = Input(UInt.width(32)) + val b = Input(UInt.width(32)) val e = Input(Bool()) - val z = Output(UInt(32)) + val z = Output(UInt.width(32)) val v = Output(Bool()) }) val x = Reg(UInt(width = 32)) diff --git a/src/test/scala/chiselTests/LFSR16.scala b/src/test/scala/chiselTests/LFSR16.scala index 2d5e7f3e..b13b67e3 100644 --- a/src/test/scala/chiselTests/LFSR16.scala +++ b/src/test/scala/chiselTests/LFSR16.scala @@ -9,7 +9,7 @@ import chisel3.util._ class LFSR16 extends Module { val io = IO(new Bundle { val inc = Input(Bool()) - val out = Output(UInt(16)) + val out = Output(UInt.width(16)) }) val res = Reg(init = UInt(1, 16)) when (io.inc) { diff --git a/src/test/scala/chiselTests/MemorySearch.scala b/src/test/scala/chiselTests/MemorySearch.scala index 770be326..e4063532 100644 --- a/src/test/scala/chiselTests/MemorySearch.scala +++ b/src/test/scala/chiselTests/MemorySearch.scala @@ -7,21 +7,21 @@ import chisel3.testers.BasicTester class MemorySearch extends Module { val io = IO(new Bundle { - val target = Input(UInt(4)) + val target = Input(UInt.width(4)) val en = Input(Bool()) val done = Output(Bool()) - val address = Output(UInt(3)) + val address = Output(UInt.width(3)) }) val vals = Array(0, 4, 15, 14, 2, 5, 13) val index = Reg(init = UInt(0, width = 3)) val elts = Vec(vals.map(UInt(_,4))) // val elts = Mem(UInt(width = 32), 8) TODO ???? val elt = elts(index) - val end = !io.en && ((elt === io.target) || (index === UInt(7))) + val end = !io.en && ((elt === io.target) || (index === UInt.Lit(7))) when (io.en) { - index := UInt(0) + index := UInt.Lit(0) } .elsewhen (!end) { - index := index +% UInt(1) + index := index +% UInt.Lit(1) } io.done := end io.address := index diff --git a/src/test/scala/chiselTests/Module.scala b/src/test/scala/chiselTests/Module.scala index 857aeda3..59451a2b 100644 --- a/src/test/scala/chiselTests/Module.scala +++ b/src/test/scala/chiselTests/Module.scala @@ -5,8 +5,8 @@ package chiselTests import chisel3._ class SimpleIO extends Bundle { - val in = Input(UInt(32)) - val out = Output(UInt(32)) + val in = Input(UInt.width(32)) + val out = Output(UInt.width(32)) } class PlusOne extends Module { @@ -16,8 +16,8 @@ class PlusOne extends Module { class ModuleVec(val n: Int) extends Module { val io = IO(new Bundle { - val ins = Input(Vec(n, UInt(32))) - val outs = Output(Vec(n, UInt(32))) + val ins = Input(Vec(n, UInt.Lit(32))) + val outs = Output(Vec(n, UInt.Lit(32))) }) val pluses = Vec.fill(n){ Module(new PlusOne).io } for (i <- 0 until n) { diff --git a/src/test/scala/chiselTests/MulLookup.scala b/src/test/scala/chiselTests/MulLookup.scala index b22b2820..16a29104 100644 --- a/src/test/scala/chiselTests/MulLookup.scala +++ b/src/test/scala/chiselTests/MulLookup.scala @@ -9,9 +9,9 @@ import chisel3.testers.BasicTester class MulLookup(val w: Int) extends Module { val io = IO(new Bundle { - val x = Input(UInt(w)) - val y = Input(UInt(w)) - val z = Output(UInt(2 * w)) + val x = Input(UInt.width(w)) + val y = Input(UInt.width(w)) + val z = Output(UInt.width(2 * w)) }) val tbl = Vec( for { @@ -24,9 +24,9 @@ class MulLookup(val w: Int) extends Module { class MulLookupTester(w: Int, x: Int, y: Int) extends BasicTester { val dut = Module(new MulLookup(w)) - dut.io.x := UInt(x) - dut.io.y := UInt(y) - assert(dut.io.z === UInt(x * y)) + dut.io.x := UInt.Lit(x) + dut.io.y := UInt.Lit(y) + assert(dut.io.z === UInt.Lit(x * y)) stop() } diff --git a/src/test/scala/chiselTests/Padding.scala b/src/test/scala/chiselTests/Padding.scala index 6c92e87b..42df6802 100644 --- a/src/test/scala/chiselTests/Padding.scala +++ b/src/test/scala/chiselTests/Padding.scala @@ -6,9 +6,9 @@ import chisel3._ class Padder extends Module { val io = IO(new Bundle { - val a = Input(UInt(4)) - val asp = Output(SInt(8)) - val aup = Output(UInt(8)) + val a = Input(UInt.width(4)) + val asp = Output(SInt.width(8)) + val aup = Output(UInt.width(8)) }) io.asp := io.a.asSInt io.aup := io.a.asUInt diff --git a/src/test/scala/chiselTests/Printf.scala b/src/test/scala/chiselTests/Printf.scala index c872fde4..92b6fee1 100644 --- a/src/test/scala/chiselTests/Printf.scala +++ b/src/test/scala/chiselTests/Printf.scala @@ -7,7 +7,7 @@ import chisel3._ import chisel3.testers.BasicTester class SinglePrintfTester() extends BasicTester { - val x = UInt(254) + val x = UInt.Lit(254) printf("x=%x", x) stop() } @@ -18,8 +18,8 @@ class ASCIIPrintfTester() extends BasicTester { } class MultiPrintfTester() extends BasicTester { - val x = UInt(254) - val y = UInt(255) + val x = UInt.Lit(254) + val y = UInt.Lit(255) printf("x=%x y=%x", x, y) stop() } diff --git a/src/test/scala/chiselTests/Reg.scala b/src/test/scala/chiselTests/Reg.scala index 0caf6315..5d4bd18d 100644 --- a/src/test/scala/chiselTests/Reg.scala +++ b/src/test/scala/chiselTests/Reg.scala @@ -16,7 +16,7 @@ class RegSpec extends ChiselFlatSpec { "A Reg" should "be of the same type and width as outType, if specified" in { class RegOutTypeWidthTester extends BasicTester { - val reg = Reg(t=UInt(width=2), next=Wire(UInt(width=3)), init=UInt(20)) + val reg = Reg(t=UInt(width=2), next=Wire(UInt(width=3)), init=UInt.Lit(20)) reg.getWidth should be (2) } elaborate{ new RegOutTypeWidthTester } diff --git a/src/test/scala/chiselTests/Risc.scala b/src/test/scala/chiselTests/Risc.scala index c110d37e..156e5df2 100644 --- a/src/test/scala/chiselTests/Risc.scala +++ b/src/test/scala/chiselTests/Risc.scala @@ -8,7 +8,7 @@ import chisel3.util._ class Risc extends Module { val io = IO(new Bundle { val isWr = Input(Bool()) - val wrAddr = Input(UInt(8)) + val wrAddr = Input(UInt.width(8)) val wrData = Input(Bits(32)) val boot = Input(Bool()) val valid = Output(Bool()) @@ -38,7 +38,7 @@ class Risc extends Module { when (io.isWr) { code(io.wrAddr) := io.wrData } .elsewhen (io.boot) { - pc := UInt(0) + pc := UInt.Lit(0) } .otherwise { switch(op) { is(add_op) { rc := ra +% rb } diff --git a/src/test/scala/chiselTests/SIntOps.scala b/src/test/scala/chiselTests/SIntOps.scala index a98edf9b..d827c096 100644 --- a/src/test/scala/chiselTests/SIntOps.scala +++ b/src/test/scala/chiselTests/SIntOps.scala @@ -7,22 +7,22 @@ import chisel3.testers.BasicTester class SIntOps extends Module { val io = IO(new Bundle { - val a = Input(SInt(16)) - val b = Input(SInt(16)) - val addout = Output(SInt(16)) - val subout = Output(SInt(16)) - val timesout = Output(SInt(16)) - val divout = Output(SInt(16)) - val modout = Output(SInt(16)) - val lshiftout = Output(SInt(16)) - val rshiftout = Output(SInt(16)) + val a = Input(SInt.width(16)) + val b = Input(SInt.width(16)) + val addout = Output(SInt.width(16)) + val subout = Output(SInt.width(16)) + val timesout = Output(SInt.width(16)) + val divout = Output(SInt.width(16)) + val modout = Output(SInt.width(16)) + val lshiftout = Output(SInt.width(16)) + val rshiftout = Output(SInt.width(16)) val lessout = Output(Bool()) val greatout = Output(Bool()) val eqout = Output(Bool()) val noteqout = Output(Bool()) val lesseqout = Output(Bool()) val greateqout = Output(Bool()) - val negout = Output(SInt(16)) + val negout = Output(SInt.width(16)) }) val a = io.a @@ -32,9 +32,9 @@ class SIntOps extends Module { io.subout := a -% b // TODO: //io.timesout := (a * b)(15, 0) - //io.divout := a / Mux(b === SInt(0), SInt(1), b) + //io.divout := a / Mux(b === SInt.Lit(0), SInt.Lit(1), b) //io.divout := (a / b)(15, 0) - //io.modout := SInt(0) + //io.modout := SInt.Lit(0) //io.lshiftout := (a << 12)(15, 0) // (a << ub(3, 0))(15, 0).toSInt io.rshiftout := (a >> 8) // (a >> ub).toSInt io.lessout := a < b @@ -44,7 +44,7 @@ class SIntOps extends Module { io.lesseqout := a <= b io.greateqout := a >= b // io.negout := -a(15, 0).toSInt - io.negout := (SInt(0) -% a) + io.negout := (SInt.Lit(0) -% a) } /* diff --git a/src/test/scala/chiselTests/Stack.scala b/src/test/scala/chiselTests/Stack.scala index 683c5224..440228c9 100644 --- a/src/test/scala/chiselTests/Stack.scala +++ b/src/test/scala/chiselTests/Stack.scala @@ -12,8 +12,8 @@ class ChiselStack(val depth: Int) extends Module { val push = Input(Bool()) val pop = Input(Bool()) val en = Input(Bool()) - val dataIn = Input(UInt(32)) - val dataOut = Output(UInt(32)) + val dataIn = Input(UInt.width(32)) + val dataOut = Output(UInt.width(32)) }) val stack_mem = Mem(depth, UInt(width = 32)) @@ -21,14 +21,14 @@ class ChiselStack(val depth: Int) extends Module { val out = Reg(init = UInt(0, width = 32)) when (io.en) { - when(io.push && (sp < UInt(depth))) { + when(io.push && (sp < UInt.Lit(depth))) { stack_mem(sp) := io.dataIn - sp := sp +% UInt(1) - } .elsewhen(io.pop && (sp > UInt(0))) { - sp := sp -% UInt(1) + sp := sp +% UInt.Lit(1) + } .elsewhen(io.pop && (sp > UInt.Lit(0))) { + sp := sp -% UInt.Lit(1) } - when (sp > UInt(0)) { - out := stack_mem(sp -% UInt(1)) + when (sp > UInt.Lit(0)) { + out := stack_mem(sp -% UInt.Lit(1)) } } io.dataOut := out diff --git a/src/test/scala/chiselTests/Tbl.scala b/src/test/scala/chiselTests/Tbl.scala index 6ebe0875..75c4278f 100644 --- a/src/test/scala/chiselTests/Tbl.scala +++ b/src/test/scala/chiselTests/Tbl.scala @@ -14,8 +14,8 @@ class Tbl(w: Int, n: Int) extends Module { val wi = Input(UInt(log2Up(n))) val ri = Input(UInt(log2Up(n))) val we = Input(Bool()) - val d = Input(UInt(w)) - val o = Output(UInt(w)) + val d = Input(UInt.width(w)) + val o = Output(UInt.width(w)) }) val m = Mem(n, UInt(width = w)) io.o := m(io.ri) @@ -32,13 +32,13 @@ class TblTester(w: Int, n: Int, idxs: List[Int], values: List[Int]) extends Basi val dut = Module(new Tbl(w, n)) val vvalues = Vec(values.map(UInt(_))) val vidxs = Vec(idxs.map(UInt(_))) - val prev_idx = vidxs(cnt - UInt(1)) - val prev_value = vvalues(cnt - UInt(1)) + val prev_idx = vidxs(cnt - UInt.Lit(1)) + val prev_value = vvalues(cnt - UInt.Lit(1)) dut.io.wi := vidxs(cnt) dut.io.ri := prev_idx dut.io.we := Bool(true) //TODO enSequence dut.io.d := vvalues(cnt) - when (cnt > UInt(0)) { + when (cnt > UInt.Lit(0)) { when (prev_idx === vidxs(cnt)) { assert(dut.io.o === vvalues(cnt)) } .otherwise { diff --git a/src/test/scala/chiselTests/TesterDriverSpec.scala b/src/test/scala/chiselTests/TesterDriverSpec.scala index 2f3e9368..4c1e41c8 100644 --- a/src/test/scala/chiselTests/TesterDriverSpec.scala +++ b/src/test/scala/chiselTests/TesterDriverSpec.scala @@ -20,17 +20,17 @@ class FinishTester extends BasicTester { stop() } - val test_wire = Wire(UInt(1, width = test_wire_width)) + val test_wire = UInt(1, width = test_wire_width) // though we just set test_wire to 1, the assert below will pass because // the finish will change its value - assert(test_wire === UInt(test_wire_override_value)) + assert(test_wire === UInt.Lit(test_wire_override_value)) /** In finish we use last connect semantics to alter the test_wire in the circuit * with a new value */ override def finish(): Unit = { - test_wire := UInt(test_wire_override_value) + test_wire := UInt.Lit(test_wire_override_value) } } diff --git a/src/test/scala/chiselTests/UIntOps.scala b/src/test/scala/chiselTests/UIntOps.scala index ca83ee1d..812f822d 100644 --- a/src/test/scala/chiselTests/UIntOps.scala +++ b/src/test/scala/chiselTests/UIntOps.scala @@ -8,15 +8,15 @@ import chisel3.testers.BasicTester class UIntOps extends Module { val io = IO(new Bundle { - val a = Input(UInt(16)) - val b = Input(UInt(16)) - val addout = Output(UInt(16)) - val subout = Output(UInt(16)) - val timesout = Output(UInt(16)) - val divout = Output(UInt(16)) - val modout = Output(UInt(16)) - val lshiftout = Output(UInt(16)) - val rshiftout = Output(UInt(16)) + val a = Input(UInt.width(16)) + val b = Input(UInt.width(16)) + val addout = Output(UInt.width(16)) + val subout = Output(UInt.width(16)) + val timesout = Output(UInt.width(16)) + val divout = Output(UInt.width(16)) + val modout = Output(UInt.width(16)) + val lshiftout = Output(UInt.width(16)) + val rshiftout = Output(UInt.width(16)) val lessout = Output(Bool()) val greatout = Output(Bool()) val eqout = Output(Bool()) @@ -31,10 +31,10 @@ class UIntOps extends Module { io.addout := a +% b io.subout := a -% b io.timesout := (a * b)(15, 0) - io.divout := a / Mux(b === UInt(0), UInt(1), b) + io.divout := a / Mux(b === UInt.Lit(0), UInt.Lit(1), b) // io.modout := a % b // TODO: - io.modout := UInt(0) + io.modout := UInt.Lit(0) io.lshiftout := (a << b(3, 0))(15, 0) io.rshiftout := a >> b io.lessout := a < b @@ -78,7 +78,7 @@ class UIntOpsTester(c: UIntOps) extends Tester(c) { class GoodBoolConversion extends Module { val io = IO(new Bundle { - val u = Input(UInt(1)) + val u = Input(UInt.width(1)) val b = Output(Bool()) }) io.b := io.u.toBool diff --git a/src/test/scala/chiselTests/Vec.scala b/src/test/scala/chiselTests/Vec.scala index b90c1f09..cdb1ba8d 100644 --- a/src/test/scala/chiselTests/Vec.scala +++ b/src/test/scala/chiselTests/Vec.scala @@ -12,7 +12,7 @@ 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? for ((a,b) <- v.zip(values)) { - assert(a === UInt(b)) + assert(a === UInt.Lit(b)) } stop() } @@ -34,8 +34,8 @@ class ShiftRegisterTester(n: Int) extends BasicTester { val shifter = Reg(Vec(n, UInt(width = log2Up(n)))) (shifter, shifter drop 1).zipped.foreach(_ := _) shifter(n-1) := cnt - when (cnt >= UInt(n)) { - val expected = cnt - UInt(n) + when (cnt >= UInt.Lit(n)) { + val expected = cnt - UInt.Lit(n) assert(shifter(0) === expected) } when (wrap) { diff --git a/src/test/scala/chiselTests/When.scala b/src/test/scala/chiselTests/When.scala index 5f3d3e61..58aa43e7 100644 --- a/src/test/scala/chiselTests/When.scala +++ b/src/test/scala/chiselTests/When.scala @@ -13,19 +13,19 @@ class WhenTester() extends BasicTester { when(Bool(true)) { cnt.inc() } val out = Wire(UInt(width=3)) - when(cnt.value === UInt(0)) { - out := UInt(1) - } .elsewhen (cnt.value === UInt(1)) { - out := UInt(2) - } .elsewhen (cnt.value === UInt(2)) { - out := UInt(3) + when(cnt.value === UInt.Lit(0)) { + out := UInt.Lit(1) + } .elsewhen (cnt.value === UInt.Lit(1)) { + out := UInt.Lit(2) + } .elsewhen (cnt.value === UInt.Lit(2)) { + out := UInt.Lit(3) } .otherwise { - out := UInt(0) + out := UInt.Lit(0) } - assert(out === cnt.value + UInt(1)) + assert(out === cnt.value + UInt.Lit(1)) - when(cnt.value === UInt(3)) { + when(cnt.value === UInt.Lit(3)) { stop() } } @@ -35,19 +35,19 @@ class OverlappedWhenTester() extends BasicTester { when(Bool(true)) { cnt.inc() } val out = Wire(UInt(width=3)) - when(cnt.value <= UInt(0)) { - out := UInt(1) - } .elsewhen (cnt.value <= UInt(1)) { - out := UInt(2) - } .elsewhen (cnt.value <= UInt(2)) { - out := UInt(3) + when(cnt.value <= UInt.Lit(0)) { + out := UInt.Lit(1) + } .elsewhen (cnt.value <= UInt.Lit(1)) { + out := UInt.Lit(2) + } .elsewhen (cnt.value <= UInt.Lit(2)) { + out := UInt.Lit(3) } .otherwise { - out := UInt(0) + out := UInt.Lit(0) } - assert(out === cnt.value + UInt(1)) + assert(out === cnt.value + UInt.Lit(1)) - when(cnt.value === UInt(3)) { + when(cnt.value === UInt.Lit(3)) { stop() } } -- cgit v1.2.3 From 1fa57cc3f76bc3e5de7e6b943abe70becdcb2295 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Wed, 20 Jul 2016 17:08:55 -0700 Subject: More literal/width rangling. --- chiselFrontend/src/main/scala/chisel3/core/Bits.scala | 4 ---- chiselFrontend/src/main/scala/chisel3/core/Reg.scala | 2 +- chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala | 2 +- src/main/scala/chisel3/util/Arbiter.scala | 10 +++++----- src/main/scala/chisel3/util/Bitwise.scala | 2 +- src/main/scala/chisel3/util/CircuitMath.scala | 2 +- src/main/scala/chisel3/util/Decoupled.scala | 2 +- src/main/scala/chisel3/util/OneHot.scala | 2 +- src/test/scala/chiselTests/BitwiseOps.scala | 8 ++++---- src/test/scala/chiselTests/BundleWire.scala | 4 ++-- src/test/scala/chiselTests/ComplexAssign.scala | 6 +++--- src/test/scala/chiselTests/DeqIOSpec.scala | 2 +- src/test/scala/chiselTests/GCD.scala | 4 ++-- src/test/scala/chiselTests/MultiAssign.scala | 2 +- src/test/scala/chiselTests/Reg.scala | 6 +++--- src/test/scala/chiselTests/Risc.scala | 12 ++++++------ src/test/scala/chiselTests/Stack.scala | 2 +- src/test/scala/chiselTests/Tbl.scala | 10 +++++----- src/test/scala/chiselTests/UIntOps.scala | 2 +- src/test/scala/chiselTests/Vec.scala | 8 ++++---- src/test/scala/chiselTests/VectorPacketIO.scala | 2 +- src/test/scala/chiselTests/When.scala | 4 ++-- 22 files changed, 47 insertions(+), 51 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala index 3580b5f3..ee0acd86 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala @@ -518,8 +518,6 @@ sealed class UInt private[core] (width: Width, lit: Option[ULit] = None) private[core] sealed trait UIntFactory { /** Create a UInt type with inferred width. */ def apply(): UInt = apply(Width()) - /** Create a UInt type or port with fixed width. */ - def apply(width: Int): UInt = apply(Width(width)) /** Create a UInt port with specified width. */ def apply(width: Width): UInt = new UInt(width) /** Create a UInt with a specified width - compatibility with Chisel2. */ @@ -677,8 +675,6 @@ object SInt { /** Create an SInt type with inferred width. */ def apply(): SInt = apply(Width()) /** Create a SInt type or port with fixed width. */ - def apply(width: Int): SInt = apply(Width(width)) - /** Create an SInt type with specified width. */ def apply(width: Width): SInt = new SInt(width) /** Create a SInt type or port with fixed width. */ def width(width: Int): SInt = apply(Width(width)) diff --git a/chiselFrontend/src/main/scala/chisel3/core/Reg.scala b/chiselFrontend/src/main/scala/chisel3/core/Reg.scala index b46b96ef..e0607520 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Reg.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Reg.scala @@ -11,7 +11,7 @@ object Reg { private[core] def makeType[T <: Data](t: T = null, next: T = null, init: T = null): T = { if (t ne null) { - Binding.checkUnbound(t, s"t ($t) must be unbound Type. Try using newType?") + Binding.checkUnbound(t, s"t ($t) must be unbound Type. Try using cloneType?") t.cloneType } else if (next ne null) { next.cloneTypeWidth(Width()) diff --git a/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala b/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala index c1ec6b90..b06fd7a5 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala @@ -51,7 +51,7 @@ private[chisel3] object SeqUtils { if (in.tail.isEmpty) { in.head._2 } else { - val masked = for ((s, i) <- in) yield Mux(s, i.toBits, Bits(0)) + val masked = for ((s, i) <- in) yield Mux(s, i.toBits, Bits.Lit(0)) val width = in.map(_._2.width).reduce(_ max _) in.head._2.cloneTypeWidth(width).fromBits(masked.reduceLeft(_|_)) } diff --git a/src/main/scala/chisel3/util/Arbiter.scala b/src/main/scala/chisel3/util/Arbiter.scala index 44cc88b6..0ece3a0a 100644 --- a/src/main/scala/chisel3/util/Arbiter.scala +++ b/src/main/scala/chisel3/util/Arbiter.scala @@ -11,7 +11,7 @@ import chisel3._ class ArbiterIO[T <: Data](gen: T, n: Int) extends Bundle { val in = Flipped(Vec(n, DecoupledIO(gen))) val out = DecoupledIO(gen) - val chosen = Output(UInt(log2Up(n))) + val chosen = Output(UInt.width(log2Up(n))) } /** Arbiter Control determining which producer has access */ @@ -56,7 +56,7 @@ abstract class LockingArbiterLike[T <: Data](gen: T, n: Int, count: Int, needsLo 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.firing) - lazy val grantMask = (0 until n).map(UInt(_) > lastGrant) + lazy val grantMask = (0 until n).map(UInt.Lit(_) > lastGrant) lazy val validMask = io.in zip grantMask map { case (in, g) => in.valid && g } override def grant: Seq[Bool] = { @@ -64,7 +64,7 @@ class LockingRRArbiter[T <: Data](gen: T, n: Int, count: Int, needsLock: Option[ (0 until n).map(i => ctrl(i) && grantMask(i) || ctrl(i + n)) } - override lazy val choice = Wire(init=UInt(n-1)) + override lazy val choice = Wire(init=UInt.Lit(n-1)) for (i <- n-2 to 0 by -1) when (io.in(i).valid) { choice := UInt.Lit(i) } for (i <- n-1 to 1 by -1) @@ -75,7 +75,7 @@ class LockingArbiter[T <: Data](gen: T, n: Int, count: Int, needsLock: Option[T 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)) + override lazy val choice = Wire(init=UInt.Lit(n-1)) for (i <- n-2 to 0 by -1) when (io.in(i).valid) { choice := UInt.Lit(i) } } @@ -103,7 +103,7 @@ class RRArbiter[T <: Data](gen:T, n: Int) extends LockingRRArbiter[T](gen, n, 1) class Arbiter[T <: Data](gen: T, n: Int) extends Module { val io = IO(new ArbiterIO(gen, n)) - io.chosen := UInt(n-1) + io.chosen := UInt.Lit(n-1) io.out.bits := io.in(n-1).bits for (i <- n-2 to 0 by -1) { when (io.in(i).valid) { diff --git a/src/main/scala/chisel3/util/Bitwise.scala b/src/main/scala/chisel3/util/Bitwise.scala index ab1ff550..b2a9a28c 100644 --- a/src/main/scala/chisel3/util/Bitwise.scala +++ b/src/main/scala/chisel3/util/Bitwise.scala @@ -27,7 +27,7 @@ object Fill { /** Fan out x n times */ def apply(n: Int, x: UInt): UInt = { n match { - case 0 => UInt(width=0) + case 0 => UInt.width(0) case 1 => x case y if n > 1 => val p2 = Array.ofDim[UInt](log2Up(n + 1)) diff --git a/src/main/scala/chisel3/util/CircuitMath.scala b/src/main/scala/chisel3/util/CircuitMath.scala index 5e93b009..8f8bde4a 100644 --- a/src/main/scala/chisel3/util/CircuitMath.scala +++ b/src/main/scala/chisel3/util/CircuitMath.scala @@ -20,7 +20,7 @@ object Log2 { } else if (width == 2) { x(1) } else { - Mux(x(width-1), UInt(width-1), apply(x, width-1)) + Mux(x(width-1), UInt.width(width-1), apply(x, width-1)) } } diff --git a/src/main/scala/chisel3/util/Decoupled.scala b/src/main/scala/chisel3/util/Decoupled.scala index 5958c744..037f9a22 100644 --- a/src/main/scala/chisel3/util/Decoupled.scala +++ b/src/main/scala/chisel3/util/Decoupled.scala @@ -82,7 +82,7 @@ class QueueIO[T <: Data](gen: T, entries: Int) extends Bundle /** I/O to enqueue data, is [[Chisel.DecoupledIO]]*/ val deq = DeqIO(gen) /** The current amount of data in the queue */ - val count = Output(UInt(log2Up(entries + 1))) + val count = Output(UInt.width(log2Up(entries + 1))) } /** A hardware module implementing a Queue diff --git a/src/main/scala/chisel3/util/OneHot.scala b/src/main/scala/chisel3/util/OneHot.scala index 8a5caf44..c1f94ba6 100644 --- a/src/main/scala/chisel3/util/OneHot.scala +++ b/src/main/scala/chisel3/util/OneHot.scala @@ -31,7 +31,7 @@ object OHToUInt { * @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: Seq[Bool]): UInt = PriorityMux(in, (0 until in.size).map(UInt.Lit(_))) def apply(in: Bits): UInt = apply(in.toBools) } diff --git a/src/test/scala/chiselTests/BitwiseOps.scala b/src/test/scala/chiselTests/BitwiseOps.scala index 08999a1b..0aaa3c57 100644 --- a/src/test/scala/chiselTests/BitwiseOps.scala +++ b/src/test/scala/chiselTests/BitwiseOps.scala @@ -11,10 +11,10 @@ class BitwiseOpsTester(w: Int, _a: Int, _b: Int) extends BasicTester { val mask = (1 << w) - 1 val a = UInt(_a, w) val b = UInt(_b, w) - assert(~a === UInt(mask & ~_a)) - assert((a & b) === UInt(_a & _b)) - assert((a | b) === UInt(_a | _b)) - assert((a ^ b) === UInt(_a ^ _b)) + assert(~a === UInt.Lit(mask & ~_a)) + assert((a & b) === UInt.Lit(_a & _b)) + assert((a | b) === UInt.Lit(_a | _b)) + assert((a ^ b) === UInt.Lit(_a ^ _b)) stop() } diff --git a/src/test/scala/chiselTests/BundleWire.scala b/src/test/scala/chiselTests/BundleWire.scala index 2f6322b1..3d3d58f3 100644 --- a/src/test/scala/chiselTests/BundleWire.scala +++ b/src/test/scala/chiselTests/BundleWire.scala @@ -7,8 +7,8 @@ import org.scalatest.prop._ import chisel3.testers.BasicTester class Coord extends Bundle { - val x = UInt(width = 32) - val y = UInt(width = 32) + val x = UInt.width( 32) + val y = UInt.width( 32) } class BundleWire(n: Int) extends Module { diff --git a/src/test/scala/chiselTests/ComplexAssign.scala b/src/test/scala/chiselTests/ComplexAssign.scala index 638ef9b7..c5aaa554 100644 --- a/src/test/scala/chiselTests/ComplexAssign.scala +++ b/src/test/scala/chiselTests/ComplexAssign.scala @@ -17,11 +17,11 @@ class Complex[T <: Data](val re: T, val im: T) extends Bundle { class ComplexAssign(w: Int) extends Module { val io = IO(new Bundle { val e = Input(Bool()) - val in = Input(new Complex(UInt(width = w), UInt(width = w))) - val out = Output(new Complex(UInt(width = w), UInt(width = w))) + val in = Input(new Complex(UInt.width(w), UInt.width(w))) + val out = Output(new Complex(UInt.width(w), UInt.width(w))) }) when (io.e) { - val tmp = Wire(new Complex(UInt(width = w), UInt(width = w))) + val tmp = Wire(new Complex(UInt.width(w), UInt.width(w))) tmp := io.in io.out.re := tmp.re io.out.im := tmp.im diff --git a/src/test/scala/chiselTests/DeqIOSpec.scala b/src/test/scala/chiselTests/DeqIOSpec.scala index 770d2e0e..cd8a5d63 100644 --- a/src/test/scala/chiselTests/DeqIOSpec.scala +++ b/src/test/scala/chiselTests/DeqIOSpec.scala @@ -12,7 +12,7 @@ import chisel3.util._ class UsesDeqIOInfo extends Bundle { val test_width = 32 - val info_data = UInt(width = test_width) + val info_data = UInt.width(test_width) } class UsesDeqIO extends Module { diff --git a/src/test/scala/chiselTests/GCD.scala b/src/test/scala/chiselTests/GCD.scala index d0d945b7..5e4c897a 100644 --- a/src/test/scala/chiselTests/GCD.scala +++ b/src/test/scala/chiselTests/GCD.scala @@ -15,8 +15,8 @@ class GCD extends Module { val z = Output(UInt.width(32)) val v = Output(Bool()) }) - val x = Reg(UInt(width = 32)) - val y = Reg(UInt(width = 32)) + val x = Reg(UInt.width( 32)) + val y = Reg(UInt.width( 32)) when (x > y) { x := x -% y } .otherwise { y := y -% x } when (io.e) { x := io.a; y := io.b } diff --git a/src/test/scala/chiselTests/MultiAssign.scala b/src/test/scala/chiselTests/MultiAssign.scala index 2399267e..fa4c4898 100644 --- a/src/test/scala/chiselTests/MultiAssign.scala +++ b/src/test/scala/chiselTests/MultiAssign.scala @@ -11,7 +11,7 @@ import chisel3.util._ class LastAssignTester() extends BasicTester { val cnt = Counter(2) - val test = Wire(UInt(width=4)) + val test = Wire(UInt.width(4)) assert(test === 7.U) // allow read references before assign references test := 13.U diff --git a/src/test/scala/chiselTests/Reg.scala b/src/test/scala/chiselTests/Reg.scala index 5d4bd18d..8b9016b1 100644 --- a/src/test/scala/chiselTests/Reg.scala +++ b/src/test/scala/chiselTests/Reg.scala @@ -16,7 +16,7 @@ class RegSpec extends ChiselFlatSpec { "A Reg" should "be of the same type and width as outType, if specified" in { class RegOutTypeWidthTester extends BasicTester { - val reg = Reg(t=UInt(width=2), next=Wire(UInt(width=3)), init=UInt.Lit(20)) + val reg = Reg(t=UInt.width(2), next=Wire(UInt.width(3)), init=UInt.Lit(20)) reg.getWidth should be (2) } elaborate{ new RegOutTypeWidthTester } @@ -24,11 +24,11 @@ class RegSpec extends ChiselFlatSpec { "A Reg" should "be of unknown width if outType is not specified and width is not forced" in { class RegUnknownWidthTester extends BasicTester { - val reg1 = Reg(next=Wire(UInt(width=3)), init=20.U) + val reg1 = Reg(next=Wire(UInt.width(3)), init=20.U) DataMirror.widthOf(reg1).known should be (false) val reg2 = Reg(init=20.U) DataMirror.widthOf(reg2).known should be (false) - val reg3 = Reg(next=Wire(UInt(width=3)), init=5.U) + val reg3 = Reg(next=Wire(UInt.width(3)), init=5.U) DataMirror.widthOf(reg3).known should be (false) } elaborate { new RegUnknownWidthTester } diff --git a/src/test/scala/chiselTests/Risc.scala b/src/test/scala/chiselTests/Risc.scala index 156e5df2..665bb8e6 100644 --- a/src/test/scala/chiselTests/Risc.scala +++ b/src/test/scala/chiselTests/Risc.scala @@ -9,17 +9,17 @@ class Risc extends Module { val io = IO(new Bundle { val isWr = Input(Bool()) val wrAddr = Input(UInt.width(8)) - val wrData = Input(Bits(32)) + val wrData = Input(Bits.width(32)) val boot = Input(Bool()) val valid = Output(Bool()) - val out = Output(Bits(32)) + val out = Output(Bits.width(32)) }) val memSize = 256 - val file = Mem(memSize, Bits(width = 32)) - val code = Mem(memSize, Bits(width = 32)) + val file = Mem(memSize, Bits.width(32)) + val code = Mem(memSize, Bits.width(32)) val pc = Reg(init=UInt(0, 8)) - val add_op :: imm_op :: Nil = Enum(Bits(width = 8), 2) + val add_op :: imm_op :: Nil = Enum(Bits.width(8), 2) val inst = code(pc) val op = inst(31,24) @@ -29,7 +29,7 @@ class Risc extends Module { val ra = Mux(rai === 0.asUInt(), 0.asUInt(), file(rai)) val rb = Mux(rbi === 0.asUInt(), 0.asUInt(), file(rbi)) - val rc = Wire(Bits(width = 32)) + val rc = Wire(Bits.width(32)) io.valid := Bool(false) io.out := 0.asUInt() diff --git a/src/test/scala/chiselTests/Stack.scala b/src/test/scala/chiselTests/Stack.scala index 440228c9..0c84e62a 100644 --- a/src/test/scala/chiselTests/Stack.scala +++ b/src/test/scala/chiselTests/Stack.scala @@ -16,7 +16,7 @@ class ChiselStack(val depth: Int) extends Module { val dataOut = Output(UInt.width(32)) }) - val stack_mem = Mem(depth, UInt(width = 32)) + val stack_mem = Mem(depth, UInt.width(32)) val sp = Reg(init = UInt(0, width = log2Up(depth + 1))) val out = Reg(init = UInt(0, width = 32)) diff --git a/src/test/scala/chiselTests/Tbl.scala b/src/test/scala/chiselTests/Tbl.scala index 75c4278f..40730264 100644 --- a/src/test/scala/chiselTests/Tbl.scala +++ b/src/test/scala/chiselTests/Tbl.scala @@ -11,13 +11,13 @@ import chisel3.util._ class Tbl(w: Int, n: Int) extends Module { val io = IO(new Bundle { - val wi = Input(UInt(log2Up(n))) - val ri = Input(UInt(log2Up(n))) + val wi = Input(UInt.width(log2Up(n))) + val ri = Input(UInt.width(log2Up(n))) val we = Input(Bool()) val d = Input(UInt.width(w)) val o = Output(UInt.width(w)) }) - val m = Mem(n, UInt(width = w)) + val m = Mem(n, UInt.width(w)) io.o := m(io.ri) when (io.we) { m(io.wi) := io.d @@ -30,8 +30,8 @@ class Tbl(w: Int, n: Int) extends Module { class TblTester(w: Int, n: Int, idxs: List[Int], values: List[Int]) extends BasicTester { val (cnt, wrap) = Counter(Bool(true), idxs.size) val dut = Module(new Tbl(w, n)) - val vvalues = Vec(values.map(UInt(_))) - val vidxs = Vec(idxs.map(UInt(_))) + val vvalues = Vec(values.map(UInt.Lit(_))) + val vidxs = Vec(idxs.map(UInt.Lit(_))) val prev_idx = vidxs(cnt - UInt.Lit(1)) val prev_value = vvalues(cnt - UInt.Lit(1)) dut.io.wi := vidxs(cnt) diff --git a/src/test/scala/chiselTests/UIntOps.scala b/src/test/scala/chiselTests/UIntOps.scala index 812f822d..69633461 100644 --- a/src/test/scala/chiselTests/UIntOps.scala +++ b/src/test/scala/chiselTests/UIntOps.scala @@ -86,7 +86,7 @@ class GoodBoolConversion extends Module { class BadBoolConversion extends Module { val io = IO(new Bundle { - val u = Input(UInt(width = 5)) + val u = Input(UInt.width( 5)) val b = Output(Bool()) }) io.b := io.u.toBool diff --git a/src/test/scala/chiselTests/Vec.scala b/src/test/scala/chiselTests/Vec.scala index cdb1ba8d..22b518a2 100644 --- a/src/test/scala/chiselTests/Vec.scala +++ b/src/test/scala/chiselTests/Vec.scala @@ -18,9 +18,9 @@ class ValueTester(w: Int, values: List[Int]) extends BasicTester { } class TabulateTester(n: Int) extends BasicTester { - val v = Vec(Range(0, n).map(i => UInt(i * 2))) - val x = Vec(Array.tabulate(n){ i => UInt(i * 2) }) - val u = Vec.tabulate(n)(i => UInt(i*2)) + val v = Vec(Range(0, n).map(i => UInt.Lit(i * 2))) + val x = Vec(Array.tabulate(n){ i => UInt.Lit(i * 2) }) + val u = Vec.tabulate(n)(i => UInt.Lit(i*2)) assert(v.toBits === x.toBits) assert(v.toBits === u.toBits) @@ -31,7 +31,7 @@ class TabulateTester(n: Int) extends BasicTester { class ShiftRegisterTester(n: Int) extends BasicTester { val (cnt, wrap) = Counter(Bool(true), n*2) - val shifter = Reg(Vec(n, UInt(width = log2Up(n)))) + val shifter = Reg(Vec(n, UInt.width(log2Up(n)))) (shifter, shifter drop 1).zipped.foreach(_ := _) shifter(n-1) := cnt when (cnt >= UInt.Lit(n)) { diff --git a/src/test/scala/chiselTests/VectorPacketIO.scala b/src/test/scala/chiselTests/VectorPacketIO.scala index 081990ad..6e1d267d 100644 --- a/src/test/scala/chiselTests/VectorPacketIO.scala +++ b/src/test/scala/chiselTests/VectorPacketIO.scala @@ -19,7 +19,7 @@ import chisel3.util._ * IMPORTANT: The canonical way to initialize a decoupled inteface is still being debated. */ class Packet extends Bundle { - val header = UInt(width = 1) + val header = UInt.width(1) } /** diff --git a/src/test/scala/chiselTests/When.scala b/src/test/scala/chiselTests/When.scala index 58aa43e7..2f5c49e4 100644 --- a/src/test/scala/chiselTests/When.scala +++ b/src/test/scala/chiselTests/When.scala @@ -12,7 +12,7 @@ class WhenTester() extends BasicTester { val cnt = Counter(4) when(Bool(true)) { cnt.inc() } - val out = Wire(UInt(width=3)) + val out = Wire(UInt.width(3)) when(cnt.value === UInt.Lit(0)) { out := UInt.Lit(1) } .elsewhen (cnt.value === UInt.Lit(1)) { @@ -34,7 +34,7 @@ class OverlappedWhenTester() extends BasicTester { val cnt = Counter(4) when(Bool(true)) { cnt.inc() } - val out = Wire(UInt(width=3)) + val out = Wire(UInt.width(3)) when(cnt.value <= UInt.Lit(0)) { out := UInt.Lit(1) } .elsewhen (cnt.value <= UInt.Lit(1)) { -- cgit v1.2.3 From d269818bdd4f2b71abebfaba9d7f8c9b4d488688 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Thu, 21 Jul 2016 09:24:55 -0700 Subject: Ensure test_wire is sinkable. --- src/test/scala/chiselTests/TesterDriverSpec.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/scala/chiselTests/TesterDriverSpec.scala b/src/test/scala/chiselTests/TesterDriverSpec.scala index 4c1e41c8..b0f3a981 100644 --- a/src/test/scala/chiselTests/TesterDriverSpec.scala +++ b/src/test/scala/chiselTests/TesterDriverSpec.scala @@ -20,7 +20,7 @@ class FinishTester extends BasicTester { stop() } - val test_wire = UInt(1, width = test_wire_width) + val test_wire = Wire(init=UInt(1, test_wire_width)) // though we just set test_wire to 1, the assert below will pass because // the finish will change its value -- cgit v1.2.3 From 7c9043859994b32bb07d2fce4ae61a7a3362a1b3 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Thu, 21 Jul 2016 17:12:06 -0700 Subject: Introduce chiselCloneType to distinguish from cloneType. Still fails one test - DirectionSpec in Direction.scala --- .../src/main/scala/chisel3/core/Aggregate.scala | 18 ++++++++-------- .../src/main/scala/chisel3/core/Bits.scala | 6 +----- .../src/main/scala/chisel3/core/Data.scala | 24 ++++++++++------------ .../src/main/scala/chisel3/core/Mem.scala | 6 +++--- .../src/main/scala/chisel3/core/Reg.scala | 4 ++-- src/main/scala/chisel3/util/Decoupled.scala | 8 +++----- src/main/scala/chisel3/util/Reg.scala | 4 ++-- src/main/scala/chisel3/util/Valid.scala | 8 ++------ src/test/scala/chiselTests/ComplexAssign.scala | 2 +- src/test/scala/chiselTests/Module.scala | 2 +- 10 files changed, 34 insertions(+), 48 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala index a80dfec8..7707d906 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala @@ -24,10 +24,10 @@ object Vec { * * @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) + def apply[T <: Data](n: Int, gen: T): Vec[T] = new Vec(gen, 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) + def apply[T <: Data](gen: T, n: Int): Vec[T] = new Vec(gen, n) /** Creates a new [[Vec]] composed of elements of the input Seq of [[Data]] * nodes. @@ -104,12 +104,12 @@ object Vec { * @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) +sealed class Vec[T <: Data] private (gen: T, val length: Int) extends Aggregate 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) + private val self: Seq[T] = Vector.fill(length)(gen.chiselCloneType) /** * sample_element 'tracks' all changes to the elements of self. @@ -118,7 +118,7 @@ sealed class Vec[T <: Data] private (gen: => T, val length: Int) * * Needed specifically for the case when the Vec is length 0. */ - private[core] val sample_element: T = gen + private[core] val sample_element: T = gen.chiselCloneType // allElements current includes sample_element // This is somewhat weird although I think the best course of action here is @@ -157,7 +157,7 @@ sealed class Vec[T <: Data] private (gen: => T, val length: Int) */ def apply(idx: UInt): T = { Binding.checkSynthesizable(idx ,s"'idx' ($idx)") - val port = sample_element.cloneType + val port = sample_element.chiselCloneType port.setRef(this, idx) //TODO(twigg): This is a bit too magical // Bind each element of port to being whatever the base type is @@ -180,9 +180,7 @@ sealed class Vec[T <: Data] private (gen: => T, val length: Int) def write(idx: UInt, data: T): Unit = apply(idx).:=(data)(DeprecatedSourceInfo) override def cloneType: this.type = { - val clone = Vec(length, gen).asInstanceOf[this.type] - clone.unBind() - clone + Vec(length, gen).asInstanceOf[this.type] } private[chisel3] def toType: String = s"${sample_element.toType}[$length]" @@ -390,5 +388,5 @@ class Bundle extends Aggregate { } private[core] object Bundle { - val keywords = List("flip", "asInput", "asOutput", "cloneType", "toBits") + val keywords = List("flip", "asInput", "asOutput", "cloneType", "toBits", "chiselCloneType") } diff --git a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala index ee0acd86..07c113fd 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala @@ -51,11 +51,7 @@ sealed abstract class Bits(width: Width, override val litArg: Option[LitArg]) private[chisel3] def flatten: IndexedSeq[Bits] = IndexedSeq(this) - def cloneType: this.type = { - val clone = cloneTypeWidth(width) - clone.unBind() - clone - } + def cloneType: this.type = cloneTypeWidth(width) final def tail(n: Int): UInt = macro SourceInfoTransform.nArg final def head(n: Int): UInt = macro SourceInfoTransform.nArg diff --git a/chiselFrontend/src/main/scala/chisel3/core/Data.scala b/chiselFrontend/src/main/scala/chisel3/core/Data.scala index 79119114..fee5c01c 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Data.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Data.scala @@ -120,6 +120,15 @@ abstract class Data extends HasId { private[chisel3] def toType: String def cloneType: this.type + def chiselCloneType: this.type = { + // Call the user-supplied cloneType method + val clone = this.cloneType + //TODO(twigg): Do recursively for better error messages + for((clone_elem, source_elem) <- clone.allElements zip this.allElements) { + clone_elem.binding = UnboundBinding(source_elem.binding.direction) + } + clone + } final def := (that: Data)(implicit sourceInfo: SourceInfo): Unit = this connect that final def <> (that: Data)(implicit sourceInfo: SourceInfo): Unit = this bulkConnect that def litArg(): Option[LitArg] = None @@ -154,7 +163,7 @@ abstract class Data extends HasId { def do_fromBits(that: Bits)(implicit sourceInfo: SourceInfo): this.type = { var i = 0 - val wire = Wire(this.cloneType) + val wire = Wire(this.chiselCloneType) val bits = if (that.width.known && that.width.get >= wire.width.get) { that @@ -174,13 +183,6 @@ abstract class Data extends HasId { */ @deprecated("Use asBits, which makes the reinterpret cast more explicit and actually returns Bits", "chisel3") def toBits(): UInt = SeqUtils.do_asUInt(this.flatten)(DeprecatedSourceInfo) - - protected def unBind(): Unit = { - //TODO(twigg): Do recursively for better error messages - for(elem <- this.allElements) { - elem.binding = UnboundBinding(elem.binding.direction) - } - } } object Wire { @@ -217,11 +219,7 @@ object Clock { // TODO: Document this. sealed class Clock extends Element(Width(1)) { - def cloneType: this.type = { - val clone = Clock().asInstanceOf[this.type] - clone.unBind() - clone - } + def cloneType: this.type = Clock().asInstanceOf[this.type] private[chisel3] override def flatten: IndexedSeq[Bits] = IndexedSeq() private[chisel3] def cloneTypeWidth(width: Width): this.type = cloneType private[chisel3] def toType = "Clock" diff --git a/chiselFrontend/src/main/scala/chisel3/core/Mem.scala b/chiselFrontend/src/main/scala/chisel3/core/Mem.scala index a4e6bee3..fd0897a2 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Mem.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Mem.scala @@ -20,7 +20,7 @@ object Mem { */ 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 mt = t.chiselCloneType Binding.bind(mt, NoDirectionBinder, "Error: fresh t") // TODO(twigg): Remove need for this Binding @@ -86,7 +86,7 @@ sealed abstract class MemBase[T <: Data](t: T, val length: Int) extends HasId wi val port = pushCommand( DefMemPort(sourceInfo, - t.cloneType, Node(this), dir, idx.ref, Node(idx._parent.get.clock)) + t.chiselCloneType, Node(this), dir, idx.ref, Node(idx._parent.get.clock)) ).id // Bind each element of port to being a MemoryPort Binding.bind(port, MemoryPortBinder(Builder.forcedModule), "Error: Fresh t") @@ -117,7 +117,7 @@ object SeqMem { 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 mt = t.chiselCloneType Binding.bind(mt, NoDirectionBinder, "Error: fresh t") // TODO(twigg): Remove need for this Binding diff --git a/chiselFrontend/src/main/scala/chisel3/core/Reg.scala b/chiselFrontend/src/main/scala/chisel3/core/Reg.scala index e0607520..c1693531 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Reg.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Reg.scala @@ -12,13 +12,13 @@ object Reg { init: T = null): T = { if (t ne null) { Binding.checkUnbound(t, s"t ($t) must be unbound Type. Try using cloneType?") - t.cloneType + t.chiselCloneType } 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 Some(lit) if lit.forcedWidth => init.chiselCloneType case _ => init.cloneTypeWidth(Width()) } } else { diff --git a/src/main/scala/chisel3/util/Decoupled.scala b/src/main/scala/chisel3/util/Decoupled.scala index 037f9a22..76bf4842 100644 --- a/src/main/scala/chisel3/util/Decoupled.scala +++ b/src/main/scala/chisel3/util/Decoupled.scala @@ -12,7 +12,7 @@ class DecoupledIO[+T <: Data](gen: T) extends Bundle { val ready = Input(Bool()) val valid = Output(Bool()) - val bits = Output(gen.cloneType) + val bits = Output(gen.chiselCloneType) override def cloneType: this.type = DecoupledIO(gen).asInstanceOf[this.type] } @@ -59,9 +59,7 @@ object DecoupledIO { } } // override def cloneType: this.type = { -// val clone = DeqIO(gen).asInstanceOf[this.type] -// clone.unBind() -// clone +// DeqIO(gen).asInstanceOf[this.type] // } } @@ -171,7 +169,7 @@ extends Module(override_reset=override_reset) { 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)) + val q = Module(new Queue(enq.bits.chiselCloneType, 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 diff --git a/src/main/scala/chisel3/util/Reg.scala b/src/main/scala/chisel3/util/Reg.scala index 81de4754..f77a9667 100644 --- a/src/main/scala/chisel3/util/Reg.scala +++ b/src/main/scala/chisel3/util/Reg.scala @@ -26,12 +26,12 @@ object RegEnable { def apply[T <: Data](updateData: T, enable: Bool): T = { val r = Reg(updateData) - when (enable) { r := updateData } + when (enable) { r := updateData.chiselCloneType } r } def apply[T <: Data](updateData: T, resetData: T, enable: Bool): T = { val r = RegInit(resetData) - when (enable) { r := updateData } + when (enable) { r := updateData.chiselCloneType } r } } diff --git a/src/main/scala/chisel3/util/Valid.scala b/src/main/scala/chisel3/util/Valid.scala index 5641f0f2..743038f3 100644 --- a/src/main/scala/chisel3/util/Valid.scala +++ b/src/main/scala/chisel3/util/Valid.scala @@ -11,13 +11,9 @@ import chisel3._ class Valid[+T <: Data](gen: T) extends Bundle { val valid = Output(Bool()) - val bits = Output(gen.cloneType) + val bits = Output(gen.chiselCloneType) def fire(dummy: Int = 0): Bool = valid - override def cloneType: this.type = { - val clone = Valid(gen).asInstanceOf[this.type] - clone.unBind() - clone - } + override def cloneType: this.type = Valid(gen).asInstanceOf[this.type] } /** Adds a valid protocol to any interface */ diff --git a/src/test/scala/chiselTests/ComplexAssign.scala b/src/test/scala/chiselTests/ComplexAssign.scala index c5aaa554..fce2c602 100644 --- a/src/test/scala/chiselTests/ComplexAssign.scala +++ b/src/test/scala/chiselTests/ComplexAssign.scala @@ -11,7 +11,7 @@ import chisel3.util._ class Complex[T <: Data](val re: T, val im: T) extends Bundle { override def cloneType: this.type = - new Complex(re.cloneType, im.cloneType).asInstanceOf[this.type] + new Complex(re.chiselCloneType, im.chiselCloneType).asInstanceOf[this.type] } class ComplexAssign(w: Int) extends Module { diff --git a/src/test/scala/chiselTests/Module.scala b/src/test/scala/chiselTests/Module.scala index 59451a2b..26953f5f 100644 --- a/src/test/scala/chiselTests/Module.scala +++ b/src/test/scala/chiselTests/Module.scala @@ -41,7 +41,7 @@ class ModuleVecTester(c: ModuleVec) extends Tester(c) { class ModuleWire extends Module { val io = IO(new SimpleIO) - val inc = Wire(Module(new PlusOne).io.cloneType) + val inc = Wire(Module(new PlusOne).io.chiselCloneType) inc.in := io.in io.out := inc.out } -- cgit v1.2.3 From 922d43c085585b9eb0276ff2e8e680ca93ec1c2e Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Mon, 25 Jul 2016 08:48:41 -0700 Subject: catch Bad connection exception --- src/test/scala/chiselTests/Direction.scala | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/test/scala/chiselTests/Direction.scala b/src/test/scala/chiselTests/Direction.scala index e22e120b..bb01f0eb 100644 --- a/src/test/scala/chiselTests/Direction.scala +++ b/src/test/scala/chiselTests/Direction.scala @@ -31,7 +31,15 @@ class DirectionSpec extends ChiselPropSpec { } property("Inputs should not be assignable") { - elaborate(new BadDirection) + var excepts: Boolean = false + try elaborate(new BadDirection) + catch { + case e: Exception => { + excepts = true + } + // Should except so this is okay + // Ideally, would throw and catch more precise exception + } + assert(excepts, "Bad connection should have thrown exception!") } - } -- cgit v1.2.3 From 2d4cb434f214c31b5e3e4247775b27f1eb8d7734 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Mon, 25 Jul 2016 09:18:23 -0700 Subject: Add missing compatibility.scala. --- src/main/scala/chisel3/compatibility.scala | 156 +++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 src/main/scala/chisel3/compatibility.scala diff --git a/src/main/scala/chisel3/compatibility.scala b/src/main/scala/chisel3/compatibility.scala new file mode 100644 index 00000000..9360acbc --- /dev/null +++ b/src/main/scala/chisel3/compatibility.scala @@ -0,0 +1,156 @@ +// 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 chisel3 (lowercase c). + +package object Chisel { + type Direction = chisel3.core.Direction + val INPUT = chisel3.core.Direction.Input + val OUTPUT = chisel3.core.Direction.Output + object Flipped { + def apply[T<:Data](target: T): T = chisel3.core.Flipped[T](target) + } + type ChiselException = chisel3.internal.ChiselException + + 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 + val stop = chisel3.core.stop + + 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.core.debug + + object testers { + type BasicTester = chisel3.testers.BasicTester + val TesterDriver = chisel3.testers.TesterDriver + } + + + 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 DecoupledIO = chisel3.util.DecoupledIO + object EnqIO { + def apply[T<:Data](gen: T): DecoupledIO[T] = Flipped(DecoupledIO(gen)) + } + object DeqIO { + def apply[T<:Data](gen: T): DecoupledIO[T] = DecoupledIO(gen) + } + 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.Valid[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) +} -- cgit v1.2.3 From 50518f43cbd9c783633714a26ecdb0f2f18a1142 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Mon, 25 Jul 2016 09:19:14 -0700 Subject: Use more idiomatic ScalaTest exception expecting code. --- src/main/scala/chisel3/package.scala | 1 + src/test/scala/chiselTests/Direction.scala | 13 +++---------- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/src/main/scala/chisel3/package.scala b/src/main/scala/chisel3/package.scala index e43434c0..d47ed890 100644 --- a/src/main/scala/chisel3/package.scala +++ b/src/main/scala/chisel3/package.scala @@ -113,4 +113,5 @@ package object chisel3 { val INPUT = chisel3.core.Direction.Input val OUTPUT = chisel3.core.Direction.Output + type ChiselException = chisel3.internal.ChiselException } diff --git a/src/test/scala/chiselTests/Direction.scala b/src/test/scala/chiselTests/Direction.scala index bb01f0eb..2fe31475 100644 --- a/src/test/scala/chiselTests/Direction.scala +++ b/src/test/scala/chiselTests/Direction.scala @@ -22,7 +22,7 @@ class BadDirection extends DirectionHaver { io.in := UInt.Lit(0) } -class DirectionSpec extends ChiselPropSpec { +class DirectionSpec extends ChiselPropSpec with ShouldMatchers { //TODO: In Chisel3 these are actually FIRRTL errors. Remove from tests? @@ -31,15 +31,8 @@ class DirectionSpec extends ChiselPropSpec { } property("Inputs should not be assignable") { - var excepts: Boolean = false - try elaborate(new BadDirection) - catch { - case e: Exception => { - excepts = true - } - // Should except so this is okay - // Ideally, would throw and catch more precise exception + a[ChiselException] should be thrownBy { + elaborate(new BadDirection) } - assert(excepts, "Bad connection should have thrown exception!") } } -- cgit v1.2.3 From 7aa05590382b0528799ad5e9f1318ce42e409793 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Mon, 25 Jul 2016 14:06:51 -0700 Subject: Minimize differences with master. Remove .Lit(x) usage. Undo "private" scope change. Change "firing" back to "fire". Add package level NODIR definition. --- .../src/main/scala/chisel3/core/Aggregate.scala | 2 +- .../src/main/scala/chisel3/core/Bits.scala | 18 ++++++----- .../src/main/scala/chisel3/core/Mem.scala | 6 ++-- .../src/main/scala/chisel3/core/SeqUtils.scala | 4 +-- .../src/main/scala/chisel3/core/When.scala | 4 +-- src/main/scala/chisel3/compatibility.scala | 1 + src/main/scala/chisel3/package.scala | 3 +- src/main/scala/chisel3/util/Arbiter.scala | 24 +++++++-------- src/main/scala/chisel3/util/CircuitMath.scala | 4 +-- src/main/scala/chisel3/util/Counter.scala | 10 +++--- src/main/scala/chisel3/util/Decoupled.scala | 10 +++--- .../scala/chisel3/util/ImplicitConversions.scala | 2 +- src/main/scala/chisel3/util/OneHot.scala | 6 ++-- src/test/scala/chiselTests/Assert.scala | 4 +-- src/test/scala/chiselTests/BitwiseOps.scala | 8 ++--- src/test/scala/chiselTests/BlackBox.scala | 30 +++++++++--------- src/test/scala/chiselTests/BundleWire.scala | 8 ++--- src/test/scala/chiselTests/ComplexAssign.scala | 12 ++++---- src/test/scala/chiselTests/Counter.scala | 8 ++--- src/test/scala/chiselTests/Decoder.scala | 2 +- src/test/scala/chiselTests/Direction.scala | 4 +-- src/test/scala/chiselTests/MemorySearch.scala | 6 ++-- src/test/scala/chiselTests/Module.scala | 4 +-- src/test/scala/chiselTests/MulLookup.scala | 6 ++-- src/test/scala/chiselTests/Printf.scala | 6 ++-- src/test/scala/chiselTests/Reg.scala | 2 +- src/test/scala/chiselTests/Risc.scala | 2 +- src/test/scala/chiselTests/SIntOps.scala | 6 ++-- src/test/scala/chiselTests/Stack.scala | 12 ++++---- src/test/scala/chiselTests/Tbl.scala | 10 +++--- src/test/scala/chiselTests/TesterDriverSpec.scala | 4 +-- src/test/scala/chiselTests/UIntOps.scala | 4 +-- src/test/scala/chiselTests/Vec.scala | 12 ++++---- src/test/scala/chiselTests/When.scala | 36 +++++++++++----------- 34 files changed, 142 insertions(+), 138 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala index 7707d906..459a3b67 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala @@ -239,7 +239,7 @@ trait VecLike[T <: Data] extends collection.IndexedSeq[T] with HasId { /** 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.Lit(i)) + 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. */ diff --git a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala index 20ac0e4a..6ec455ca 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala @@ -404,8 +404,8 @@ sealed class UInt private[core] (width: Width, lit: Option[ULit] = None) final def unary_- (): UInt = macro SourceInfoTransform.noArg final def unary_-% (): UInt = macro SourceInfoTransform.noArg - def do_unary_- (implicit sourceInfo: SourceInfo) : UInt = UInt.Lit(0) - this - def do_unary_-% (implicit sourceInfo: SourceInfo): UInt = UInt.Lit(0) -% this + 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 @@ -453,8 +453,8 @@ sealed class UInt private[core] (width: Width, lit: Option[ULit] = None) final def andR(): Bool = macro SourceInfoTransform.noArg final def xorR(): Bool = macro SourceInfoTransform.noArg - def do_orR(implicit sourceInfo: SourceInfo): Bool = this != UInt.Lit(0) - def do_andR(implicit sourceInfo: SourceInfo): Bool = ~this === UInt.Lit(0) + 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) @@ -523,6 +523,8 @@ private[core] sealed trait UIntFactory { def width(width: Width): UInt = new UInt(width) /** Create a UInt with a specified width - compatibility with Chisel2. */ def apply(dummy: Option[Direction] = None, width: Int): UInt = apply(Width(width)) + /** Create a UInt literal with inferred width.- compatibility with Chisel2. */ + def apply(value: BigInt): UInt = apply(value, Width()) /** Create a UInt literal with fixed width. */ def apply(value: BigInt, width: Int): UInt = Lit(value, Width(width)) /** Create a UInt literal with inferred width. */ @@ -581,8 +583,8 @@ sealed class SInt private (width: Width, lit: Option[SLit] = None) final def unary_- (): SInt = macro SourceInfoTransform.noArg final def unary_-% (): SInt = macro SourceInfoTransform.noArg - def unary_- (implicit sourceInfo: SourceInfo): SInt = SInt.Lit(0) - this - def unary_-% (implicit sourceInfo: SourceInfo): SInt = SInt.Lit(0) -% this + 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 = @@ -649,7 +651,7 @@ sealed class SInt private (width: Width, lit: Option[SLit] = None) final def abs(): UInt = macro SourceInfoTransform.noArg - def do_abs(implicit sourceInfo: SourceInfo): UInt = Mux(this < SInt.Lit(0), (-this).asUInt, this.asUInt) + 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) @@ -769,7 +771,7 @@ object Mux { * @param alt the value chosen when `cond` is false * @example * {{{ - * val muxOut = Mux(data_in === UInt.Lit(3), UInt(3, 4), UInt(0, 4)) + * 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] diff --git a/chiselFrontend/src/main/scala/chisel3/core/Mem.scala b/chiselFrontend/src/main/scala/chisel3/core/Mem.scala index fd0897a2..931a0489 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Mem.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Mem.scala @@ -36,7 +36,7 @@ sealed abstract class MemBase[T <: Data](t: T, val length: Int) extends HasId wi /** 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.Lit(idx)) + 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. @@ -103,7 +103,7 @@ sealed abstract class MemBase[T <: Data](t: T, val length: Int) extends HasId wi * @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] private (t: T, length: Int) extends MemBase(t, length) +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") @@ -137,7 +137,7 @@ object SeqMem { * @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] private (t: T, n: Int) extends MemBase[T](t, n) { +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()) diff --git a/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala b/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala index f4eec422..0872ec41 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala @@ -24,7 +24,7 @@ private[chisel3] object SeqUtils { def count(in: Seq[Bool]): UInt = macro SourceInfoTransform.inArg def do_count(in: Seq[Bool])(implicit sourceInfo: SourceInfo): UInt = in.size match { - case 0 => UInt.Lit(0) + case 0 => UInt(0) case 1 => in.head case n => count(in take n/2) +& count(in drop n/2) } @@ -47,7 +47,7 @@ private[chisel3] object SeqUtils { if (in.tail.isEmpty) { in.head._2 } else { - val masked = for ((s, i) <- in) yield Mux(s, i.toBits, Bits.Lit(0)) + 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 index 7049eb82..196e7903 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/When.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/When.scala @@ -18,9 +18,9 @@ object when { // scalastyle:ignore object.name * * @example * {{{ - * when ( myData === UInt.Lit(3) ) { + * when ( myData === UInt(3) ) { * // Some logic to run when myData equals 3. - * } .elsewhen ( myData === UInt.Lit(1) ) { + * } .elsewhen ( myData === UInt(1) ) { * // Some logic to run when myData equals 1. * } .otherwise { * // Some logic to run when myData is neither 3 nor 1. diff --git a/src/main/scala/chisel3/compatibility.scala b/src/main/scala/chisel3/compatibility.scala index b7020b5e..041553e0 100644 --- a/src/main/scala/chisel3/compatibility.scala +++ b/src/main/scala/chisel3/compatibility.scala @@ -7,6 +7,7 @@ package object Chisel { type Direction = chisel3.core.Direction val INPUT = chisel3.core.Direction.Input val OUTPUT = chisel3.core.Direction.Output + val NODIR = chisel3.core.Direction.Unspecified object Flipped { def apply[T<:Data](target: T): T = chisel3.core.Flipped[T](target) } diff --git a/src/main/scala/chisel3/package.scala b/src/main/scala/chisel3/package.scala index 9a79b109..774455c4 100644 --- a/src/main/scala/chisel3/package.scala +++ b/src/main/scala/chisel3/package.scala @@ -95,7 +95,7 @@ package object chisel3 { def asSInt(width: Int) = SInt(x, width) } implicit class fromStringToLiteral(val x: String) extends AnyVal { - def U: UInt = UInt.Lit(x) + def U: UInt = UInt(x) } implicit class fromBooleanToLiteral(val x: Boolean) extends AnyVal { def B: Bool = Bool(x) @@ -113,5 +113,6 @@ package object chisel3 { val INPUT = chisel3.core.Direction.Input val OUTPUT = chisel3.core.Direction.Output + val NODIR = chisel3.core.Direction.Unspecified type ChiselException = chisel3.internal.ChiselException } diff --git a/src/main/scala/chisel3/util/Arbiter.scala b/src/main/scala/chisel3/util/Arbiter.scala index 0ece3a0a..5875b3f2 100644 --- a/src/main/scala/chisel3/util/Arbiter.scala +++ b/src/main/scala/chisel3/util/Arbiter.scala @@ -36,17 +36,17 @@ abstract class LockingArbiterLike[T <: Data](gen: T, n: Int, count: Int, needsLo if (count > 1) { val lockCount = Counter(count) val lockIdx = Reg(UInt()) - val locked = lockCount.value =/= UInt.Lit(0) + val locked = lockCount.value =/= UInt(0) val wantsLock = needsLock.map(_(io.out.bits)).getOrElse(Bool(true)) - when (io.out.firing && wantsLock) { + 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.Lit(i), g) && io.out.ready + 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 @@ -55,8 +55,8 @@ abstract class LockingArbiterLike[T <: Data](gen: T, n: Int, count: Int, needsLo 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.firing) - lazy val grantMask = (0 until n).map(UInt.Lit(_) > lastGrant) + 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] = { @@ -64,20 +64,20 @@ class LockingRRArbiter[T <: Data](gen: T, n: Int, count: Int, needsLock: Option[ (0 until n).map(i => ctrl(i) && grantMask(i) || ctrl(i + n)) } - override lazy val choice = Wire(init=UInt.Lit(n-1)) + override lazy val choice = Wire(init=UInt(n-1)) for (i <- n-2 to 0 by -1) - when (io.in(i).valid) { choice := UInt.Lit(i) } + when (io.in(i).valid) { choice := UInt(i) } for (i <- n-1 to 1 by -1) - when (validMask(i)) { choice := UInt.Lit(i) } + 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.Lit(n-1)) + override lazy val choice = Wire(init=UInt(n-1)) for (i <- n-2 to 0 by -1) - when (io.in(i).valid) { choice := UInt.Lit(i) } + when (io.in(i).valid) { choice := UInt(i) } } /** Hardware module that is used to sequence n producers into 1 consumer. @@ -103,11 +103,11 @@ class RRArbiter[T <: Data](gen:T, n: Int) extends LockingRRArbiter[T](gen, n, 1) class Arbiter[T <: Data](gen: T, n: Int) extends Module { val io = IO(new ArbiterIO(gen, n)) - io.chosen := UInt.Lit(n-1) + 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.Lit(i) + io.chosen := UInt(i) io.out.bits := io.in(i).bits } } diff --git a/src/main/scala/chisel3/util/CircuitMath.scala b/src/main/scala/chisel3/util/CircuitMath.scala index 27bd7bfb..c809e14b 100644 --- a/src/main/scala/chisel3/util/CircuitMath.scala +++ b/src/main/scala/chisel3/util/CircuitMath.scala @@ -16,11 +16,11 @@ object Log2 { /** Compute the Log2 on the least significant n bits of x */ def apply(x: Bits, width: Int): UInt = { if (width < 2) { - UInt.Lit(0) + UInt(0) } else if (width == 2) { x(1) } else if (width <= divideAndConquerThreshold) { - Mux(x(width-1), UInt.Lit(width-1), apply(x, width-1)) + Mux(x(width-1), UInt(width-1), apply(x, width-1)) } else { val mid = 1 << (log2Ceil(width) - 1) val hi = x(width-1, mid) diff --git a/src/main/scala/chisel3/util/Counter.scala b/src/main/scala/chisel3/util/Counter.scala index 05d8fba8..40615769 100644 --- a/src/main/scala/chisel3/util/Counter.scala +++ b/src/main/scala/chisel3/util/Counter.scala @@ -10,17 +10,17 @@ import chisel3._ */ class Counter(val n: Int) { require(n >= 0) - val value = if (n > 1) Reg(init=UInt(0, log2Up(n))) else UInt.Lit(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.Lit(n-1) - value := value + UInt.Lit(1) + val wrap = value === UInt(n-1) + value := value + UInt(1) if (!isPow2(n)) { - when (wrap) { value := UInt.Lit(0) } + when (wrap) { value := UInt(0) } } wrap } else { @@ -33,7 +33,7 @@ class Counter(val n: Int) { * Example Usage: * {{{ val countOn = Bool(true) // increment counter every clock cycle * val myCounter = Counter(countOn, n) - * when ( myCounter.value === UInt.Lit(3) ) { ... } }}}*/ + * when ( myCounter.value === UInt(3) ) { ... } }}}*/ object Counter { def apply(n: Int): Counter = new Counter(n) diff --git a/src/main/scala/chisel3/util/Decoupled.scala b/src/main/scala/chisel3/util/Decoupled.scala index 76bf4842..68c3ae88 100644 --- a/src/main/scala/chisel3/util/Decoupled.scala +++ b/src/main/scala/chisel3/util/Decoupled.scala @@ -23,7 +23,7 @@ object DecoupledIO { def apply[T <: Data](gen: T): DecoupledIO[T] = new DecoupledIO(gen) implicit class AddMethodsToDecoupled[T<:Data](val target: DecoupledIO[T]) extends AnyVal { - def firing: Bool = target.ready && target.valid + def fire(): Bool = target.ready && target.valid /** 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. @@ -114,8 +114,8 @@ extends Module(override_reset=override_reset) { 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.firing) - val do_deq = Wire(init=io.deq.firing) + 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 @@ -151,9 +151,9 @@ extends Module(override_reset=override_reset) { } else { io.count := Mux(ptr_match, Mux(maybe_full, - UInt.Lit(entries), UInt.Lit(0)), + UInt(entries), UInt(0)), Mux(deq_ptr.value > enq_ptr.value, - UInt.Lit(entries) + ptr_diff, ptr_diff)) + UInt(entries) + ptr_diff, ptr_diff)) } } diff --git a/src/main/scala/chisel3/util/ImplicitConversions.scala b/src/main/scala/chisel3/util/ImplicitConversions.scala index 3a9089c5..4d816a19 100644 --- a/src/main/scala/chisel3/util/ImplicitConversions.scala +++ b/src/main/scala/chisel3/util/ImplicitConversions.scala @@ -5,6 +5,6 @@ package chisel3.util import chisel3._ object ImplicitConversions { - implicit def intToUInt(x: Int): UInt = UInt.Lit(x) + implicit def intToUInt(x: Int): UInt = UInt(x) implicit def booleanToBool(x: Boolean): Bool = Bool(x) } diff --git a/src/main/scala/chisel3/util/OneHot.scala b/src/main/scala/chisel3/util/OneHot.scala index 49661115..abede61e 100644 --- a/src/main/scala/chisel3/util/OneHot.scala +++ b/src/main/scala/chisel3/util/OneHot.scala @@ -31,7 +31,7 @@ object OHToUInt { * @example {{{ data_out := PriorityEncoder(data_in) }}} */ object PriorityEncoder { - def apply(in: Seq[Bool]): UInt = PriorityMux(in, (0 until in.size).map(UInt.Lit(_))) + def apply(in: Seq[Bool]): UInt = PriorityMux(in, (0 until in.size).map(UInt(_))) def apply(in: Bits): UInt = apply(in.toBools) } @@ -41,9 +41,9 @@ object UIntToOH { def apply(in: UInt, width: Int = -1): UInt = if (width == -1) { - UInt.Lit(1) << in + UInt(1) << in } else { - (UInt.Lit(1) << in(log2Up(width)-1,0))(width-1,0) + (UInt(1) << in(log2Up(width)-1,0))(width-1,0) } } diff --git a/src/test/scala/chiselTests/Assert.scala b/src/test/scala/chiselTests/Assert.scala index bf3c8092..efc2e1e7 100644 --- a/src/test/scala/chiselTests/Assert.scala +++ b/src/test/scala/chiselTests/Assert.scala @@ -27,8 +27,8 @@ class SucceedingAssertTester() extends BasicTester { class PipelinedResetModule extends Module { val io = IO(new Bundle { }) - val a = Reg(init = UInt.Lit(0xbeef)) - val b = Reg(init = UInt.Lit(0xbeef)) + val a = Reg(init = UInt(0xbeef)) + val b = Reg(init = UInt(0xbeef)) assert(a === b) } diff --git a/src/test/scala/chiselTests/BitwiseOps.scala b/src/test/scala/chiselTests/BitwiseOps.scala index 0aaa3c57..08999a1b 100644 --- a/src/test/scala/chiselTests/BitwiseOps.scala +++ b/src/test/scala/chiselTests/BitwiseOps.scala @@ -11,10 +11,10 @@ class BitwiseOpsTester(w: Int, _a: Int, _b: Int) extends BasicTester { val mask = (1 << w) - 1 val a = UInt(_a, w) val b = UInt(_b, w) - assert(~a === UInt.Lit(mask & ~_a)) - assert((a & b) === UInt.Lit(_a & _b)) - assert((a | b) === UInt.Lit(_a | _b)) - assert((a ^ b) === UInt.Lit(_a ^ _b)) + assert(~a === UInt(mask & ~_a)) + assert((a & b) === UInt(_a & _b)) + assert((a | b) === UInt(_a | _b)) + assert((a ^ b) === UInt(_a ^ _b)) stop() } diff --git a/src/test/scala/chiselTests/BlackBox.scala b/src/test/scala/chiselTests/BlackBox.scala index 9b43f0ef..c1154883 100644 --- a/src/test/scala/chiselTests/BlackBox.scala +++ b/src/test/scala/chiselTests/BlackBox.scala @@ -35,11 +35,11 @@ class BlackBoxTester extends BasicTester { val blackBoxPos = Module(new BlackBoxInverter) val blackBoxNeg = Module(new BlackBoxInverter) - blackBoxPos.io.in := UInt.Lit(1) - blackBoxNeg.io.in := UInt.Lit(0) + blackBoxPos.io.in := UInt(1) + blackBoxNeg.io.in := UInt(0) - assert(blackBoxNeg.io.out === UInt.Lit(1)) - assert(blackBoxPos.io.out === UInt.Lit(0)) + assert(blackBoxNeg.io.out === UInt(1)) + assert(blackBoxPos.io.out === UInt(0)) stop() } @@ -54,15 +54,15 @@ class MultiBlackBoxTester extends BasicTester { val blackBoxPassPos = Module(new BlackBoxPassthrough) val blackBoxPassNeg = Module(new BlackBoxPassthrough) - blackBoxInvPos.io.in := UInt.Lit(1) - blackBoxInvNeg.io.in := UInt.Lit(0) - blackBoxPassPos.io.in := UInt.Lit(1) - blackBoxPassNeg.io.in := UInt.Lit(0) + blackBoxInvPos.io.in := UInt(1) + blackBoxInvNeg.io.in := UInt(0) + blackBoxPassPos.io.in := UInt(1) + blackBoxPassNeg.io.in := UInt(0) - assert(blackBoxInvNeg.io.out === UInt.Lit(1)) - assert(blackBoxInvPos.io.out === UInt.Lit(0)) - assert(blackBoxPassNeg.io.out === UInt.Lit(0)) - assert(blackBoxPassPos.io.out === UInt.Lit(1)) + assert(blackBoxInvNeg.io.out === UInt(1)) + assert(blackBoxInvPos.io.out === UInt(0)) + assert(blackBoxPassNeg.io.out === UInt(0)) + assert(blackBoxPassPos.io.out === UInt(1)) stop() } @@ -77,7 +77,7 @@ class BlackBoxWithClockTester extends BasicTester { blackBox.io.in := impetus model := impetus - when(cycles > UInt.Lit(0)) { + when(cycles > UInt(0)) { assert(blackBox.io.out === model) } when(end) { stop() } @@ -98,8 +98,8 @@ class BlackBoxWithParamsTester extends BasicTester { val (cycles, end) = Counter(Bool(true), 4) - assert(blackBoxOne.io.out === UInt.Lit(1)) - assert(blackBoxFour.io.out === UInt.Lit(4)) + assert(blackBoxOne.io.out === UInt(1)) + assert(blackBoxFour.io.out === UInt(4)) when(end) { stop() } } diff --git a/src/test/scala/chiselTests/BundleWire.scala b/src/test/scala/chiselTests/BundleWire.scala index 3d3d58f3..0071041c 100644 --- a/src/test/scala/chiselTests/BundleWire.scala +++ b/src/test/scala/chiselTests/BundleWire.scala @@ -25,11 +25,11 @@ class BundleWire(n: Int) extends Module { class BundleWireTester(n: Int, x: Int, y: Int) extends BasicTester { val dut = Module(new BundleWire(n)) - dut.io.in.x := UInt.Lit(x) - dut.io.in.y := UInt.Lit(y) + dut.io.in.x := UInt(x) + dut.io.in.y := UInt(y) for (elt <- dut.io.outs) { - assert(elt.x === UInt.Lit(x)) - assert(elt.y === UInt.Lit(y)) + assert(elt.x === UInt(x)) + assert(elt.y === UInt(y)) } stop() } diff --git a/src/test/scala/chiselTests/ComplexAssign.scala b/src/test/scala/chiselTests/ComplexAssign.scala index fce2c602..0a1f31cc 100644 --- a/src/test/scala/chiselTests/ComplexAssign.scala +++ b/src/test/scala/chiselTests/ComplexAssign.scala @@ -26,19 +26,19 @@ class ComplexAssign(w: Int) extends Module { io.out.re := tmp.re io.out.im := tmp.im } .otherwise { - io.out.re := UInt.Lit(0) - io.out.im := UInt.Lit(0) + io.out.re := UInt(0) + io.out.im := UInt(0) } } class ComplexAssignTester(enList: List[Boolean], re: Int, im: Int) extends BasicTester { val (cnt, wrap) = Counter(Bool(true), enList.size) val dut = Module(new ComplexAssign(32)) - dut.io.in.re := UInt.Lit(re) - dut.io.in.im := UInt.Lit(im) + dut.io.in.re := UInt(re) + dut.io.in.im := UInt(im) dut.io.e := Vec(enList.map(Bool(_)))(cnt) - val re_correct = dut.io.out.re === Mux(dut.io.e, dut.io.in.re, UInt.Lit(0)) - val im_correct = dut.io.out.im === Mux(dut.io.e, dut.io.in.im, UInt.Lit(0)) + val re_correct = dut.io.out.re === Mux(dut.io.e, dut.io.in.re, UInt(0)) + val im_correct = dut.io.out.im === Mux(dut.io.e, dut.io.in.im, UInt(0)) assert(re_correct && im_correct) when(wrap) { stop() diff --git a/src/test/scala/chiselTests/Counter.scala b/src/test/scala/chiselTests/Counter.scala index af2fa550..69d8a44a 100644 --- a/src/test/scala/chiselTests/Counter.scala +++ b/src/test/scala/chiselTests/Counter.scala @@ -12,20 +12,20 @@ import chisel3.util._ class CountTester(max: Int) extends BasicTester { val cnt = Counter(max) when(Bool(true)) { cnt.inc() } - when(cnt.value === UInt.Lit(max-1)) { + when(cnt.value === UInt(max-1)) { stop() } } class EnableTester(seed: Int) extends BasicTester { - val ens = Reg(init = UInt.Lit(seed)) + val ens = Reg(init = UInt(seed)) ens := ens >> 1 val (cntEnVal, _) = Counter(ens(0), 32) val (_, done) = Counter(Bool(true), 33) when(done) { - assert(cntEnVal === UInt.Lit(popCount(seed))) + assert(cntEnVal === UInt(popCount(seed))) stop() } } @@ -33,7 +33,7 @@ class EnableTester(seed: Int) extends BasicTester { class WrapTester(max: Int) extends BasicTester { val (cnt, wrap) = Counter(Bool(true), max) when(wrap) { - assert(cnt === UInt.Lit(max - 1)) + assert(cnt === UInt(max - 1)) stop() } } diff --git a/src/test/scala/chiselTests/Decoder.scala b/src/test/scala/chiselTests/Decoder.scala index ee892fc5..b50a80c0 100644 --- a/src/test/scala/chiselTests/Decoder.scala +++ b/src/test/scala/chiselTests/Decoder.scala @@ -24,7 +24,7 @@ class DecoderTester(pairs: List[(String, String)]) extends BasicTester { val dut = Module(new Decoder(bitpats)) dut.io.inst := Vec(insts.map(UInt(_)))(cnt) when(!dut.io.matched) { - assert(cnt === UInt.Lit(0)) + assert(cnt === UInt(0)) stop() } when(wrap) { diff --git a/src/test/scala/chiselTests/Direction.scala b/src/test/scala/chiselTests/Direction.scala index 2fe31475..83484a64 100644 --- a/src/test/scala/chiselTests/Direction.scala +++ b/src/test/scala/chiselTests/Direction.scala @@ -15,11 +15,11 @@ class DirectionHaver extends Module { } class GoodDirection extends DirectionHaver { - io.out := UInt.Lit(0) + io.out := UInt(0) } class BadDirection extends DirectionHaver { - io.in := UInt.Lit(0) + io.in := UInt(0) } class DirectionSpec extends ChiselPropSpec with ShouldMatchers { diff --git a/src/test/scala/chiselTests/MemorySearch.scala b/src/test/scala/chiselTests/MemorySearch.scala index e4063532..1d09f3c5 100644 --- a/src/test/scala/chiselTests/MemorySearch.scala +++ b/src/test/scala/chiselTests/MemorySearch.scala @@ -17,11 +17,11 @@ class MemorySearch extends Module { val elts = Vec(vals.map(UInt(_,4))) // val elts = Mem(UInt(width = 32), 8) TODO ???? val elt = elts(index) - val end = !io.en && ((elt === io.target) || (index === UInt.Lit(7))) + val end = !io.en && ((elt === io.target) || (index === UInt(7))) when (io.en) { - index := UInt.Lit(0) + index := UInt(0) } .elsewhen (!end) { - index := index +% UInt.Lit(1) + index := index +% UInt(1) } io.done := end io.address := index diff --git a/src/test/scala/chiselTests/Module.scala b/src/test/scala/chiselTests/Module.scala index 26953f5f..7a4050db 100644 --- a/src/test/scala/chiselTests/Module.scala +++ b/src/test/scala/chiselTests/Module.scala @@ -16,8 +16,8 @@ class PlusOne extends Module { class ModuleVec(val n: Int) extends Module { val io = IO(new Bundle { - val ins = Input(Vec(n, UInt.Lit(32))) - val outs = Output(Vec(n, UInt.Lit(32))) + val ins = Input(Vec(n, UInt(32))) + val outs = Output(Vec(n, UInt(32))) }) val pluses = Vec.fill(n){ Module(new PlusOne).io } for (i <- 0 until n) { diff --git a/src/test/scala/chiselTests/MulLookup.scala b/src/test/scala/chiselTests/MulLookup.scala index 16a29104..26ee4e03 100644 --- a/src/test/scala/chiselTests/MulLookup.scala +++ b/src/test/scala/chiselTests/MulLookup.scala @@ -24,9 +24,9 @@ class MulLookup(val w: Int) extends Module { class MulLookupTester(w: Int, x: Int, y: Int) extends BasicTester { val dut = Module(new MulLookup(w)) - dut.io.x := UInt.Lit(x) - dut.io.y := UInt.Lit(y) - assert(dut.io.z === UInt.Lit(x * y)) + dut.io.x := UInt(x) + dut.io.y := UInt(y) + assert(dut.io.z === UInt(x * y)) stop() } diff --git a/src/test/scala/chiselTests/Printf.scala b/src/test/scala/chiselTests/Printf.scala index 92b6fee1..c872fde4 100644 --- a/src/test/scala/chiselTests/Printf.scala +++ b/src/test/scala/chiselTests/Printf.scala @@ -7,7 +7,7 @@ import chisel3._ import chisel3.testers.BasicTester class SinglePrintfTester() extends BasicTester { - val x = UInt.Lit(254) + val x = UInt(254) printf("x=%x", x) stop() } @@ -18,8 +18,8 @@ class ASCIIPrintfTester() extends BasicTester { } class MultiPrintfTester() extends BasicTester { - val x = UInt.Lit(254) - val y = UInt.Lit(255) + val x = UInt(254) + val y = UInt(255) printf("x=%x y=%x", x, y) stop() } diff --git a/src/test/scala/chiselTests/Reg.scala b/src/test/scala/chiselTests/Reg.scala index 8b9016b1..b66d7cb4 100644 --- a/src/test/scala/chiselTests/Reg.scala +++ b/src/test/scala/chiselTests/Reg.scala @@ -16,7 +16,7 @@ class RegSpec extends ChiselFlatSpec { "A Reg" should "be of the same type and width as outType, if specified" in { class RegOutTypeWidthTester extends BasicTester { - val reg = Reg(t=UInt.width(2), next=Wire(UInt.width(3)), init=UInt.Lit(20)) + val reg = Reg(t=UInt.width(2), next=Wire(UInt.width(3)), init=UInt(20)) reg.getWidth should be (2) } elaborate{ new RegOutTypeWidthTester } diff --git a/src/test/scala/chiselTests/Risc.scala b/src/test/scala/chiselTests/Risc.scala index 665bb8e6..6d5a0a76 100644 --- a/src/test/scala/chiselTests/Risc.scala +++ b/src/test/scala/chiselTests/Risc.scala @@ -38,7 +38,7 @@ class Risc extends Module { when (io.isWr) { code(io.wrAddr) := io.wrData } .elsewhen (io.boot) { - pc := UInt.Lit(0) + pc := UInt(0) } .otherwise { switch(op) { is(add_op) { rc := ra +% rb } diff --git a/src/test/scala/chiselTests/SIntOps.scala b/src/test/scala/chiselTests/SIntOps.scala index d827c096..392c4803 100644 --- a/src/test/scala/chiselTests/SIntOps.scala +++ b/src/test/scala/chiselTests/SIntOps.scala @@ -32,9 +32,9 @@ class SIntOps extends Module { io.subout := a -% b // TODO: //io.timesout := (a * b)(15, 0) - //io.divout := a / Mux(b === SInt.Lit(0), SInt.Lit(1), b) + //io.divout := a / Mux(b === SInt(0), SInt(1), b) //io.divout := (a / b)(15, 0) - //io.modout := SInt.Lit(0) + //io.modout := SInt(0) //io.lshiftout := (a << 12)(15, 0) // (a << ub(3, 0))(15, 0).toSInt io.rshiftout := (a >> 8) // (a >> ub).toSInt io.lessout := a < b @@ -44,7 +44,7 @@ class SIntOps extends Module { io.lesseqout := a <= b io.greateqout := a >= b // io.negout := -a(15, 0).toSInt - io.negout := (SInt.Lit(0) -% a) + io.negout := (SInt(0) -% a) } /* diff --git a/src/test/scala/chiselTests/Stack.scala b/src/test/scala/chiselTests/Stack.scala index 0c84e62a..a72af928 100644 --- a/src/test/scala/chiselTests/Stack.scala +++ b/src/test/scala/chiselTests/Stack.scala @@ -21,14 +21,14 @@ class ChiselStack(val depth: Int) extends Module { val out = Reg(init = UInt(0, width = 32)) when (io.en) { - when(io.push && (sp < UInt.Lit(depth))) { + when(io.push && (sp < UInt(depth))) { stack_mem(sp) := io.dataIn - sp := sp +% UInt.Lit(1) - } .elsewhen(io.pop && (sp > UInt.Lit(0))) { - sp := sp -% UInt.Lit(1) + sp := sp +% UInt(1) + } .elsewhen(io.pop && (sp > UInt(0))) { + sp := sp -% UInt(1) } - when (sp > UInt.Lit(0)) { - out := stack_mem(sp -% UInt.Lit(1)) + when (sp > UInt(0)) { + out := stack_mem(sp -% UInt(1)) } } io.dataOut := out diff --git a/src/test/scala/chiselTests/Tbl.scala b/src/test/scala/chiselTests/Tbl.scala index 40730264..66a06435 100644 --- a/src/test/scala/chiselTests/Tbl.scala +++ b/src/test/scala/chiselTests/Tbl.scala @@ -30,15 +30,15 @@ class Tbl(w: Int, n: Int) extends Module { class TblTester(w: Int, n: Int, idxs: List[Int], values: List[Int]) extends BasicTester { val (cnt, wrap) = Counter(Bool(true), idxs.size) val dut = Module(new Tbl(w, n)) - val vvalues = Vec(values.map(UInt.Lit(_))) - val vidxs = Vec(idxs.map(UInt.Lit(_))) - val prev_idx = vidxs(cnt - UInt.Lit(1)) - val prev_value = vvalues(cnt - UInt.Lit(1)) + val vvalues = Vec(values.map(UInt(_))) + val vidxs = Vec(idxs.map(UInt(_))) + val prev_idx = vidxs(cnt - UInt(1)) + val prev_value = vvalues(cnt - UInt(1)) dut.io.wi := vidxs(cnt) dut.io.ri := prev_idx dut.io.we := Bool(true) //TODO enSequence dut.io.d := vvalues(cnt) - when (cnt > UInt.Lit(0)) { + when (cnt > UInt(0)) { when (prev_idx === vidxs(cnt)) { assert(dut.io.o === vvalues(cnt)) } .otherwise { diff --git a/src/test/scala/chiselTests/TesterDriverSpec.scala b/src/test/scala/chiselTests/TesterDriverSpec.scala index b0f3a981..23eed15f 100644 --- a/src/test/scala/chiselTests/TesterDriverSpec.scala +++ b/src/test/scala/chiselTests/TesterDriverSpec.scala @@ -24,13 +24,13 @@ class FinishTester extends BasicTester { // though we just set test_wire to 1, the assert below will pass because // the finish will change its value - assert(test_wire === UInt.Lit(test_wire_override_value)) + assert(test_wire === UInt(test_wire_override_value)) /** In finish we use last connect semantics to alter the test_wire in the circuit * with a new value */ override def finish(): Unit = { - test_wire := UInt.Lit(test_wire_override_value) + test_wire := UInt(test_wire_override_value) } } diff --git a/src/test/scala/chiselTests/UIntOps.scala b/src/test/scala/chiselTests/UIntOps.scala index 69633461..ad5aecd8 100644 --- a/src/test/scala/chiselTests/UIntOps.scala +++ b/src/test/scala/chiselTests/UIntOps.scala @@ -31,10 +31,10 @@ class UIntOps extends Module { io.addout := a +% b io.subout := a -% b io.timesout := (a * b)(15, 0) - io.divout := a / Mux(b === UInt.Lit(0), UInt.Lit(1), b) + io.divout := a / Mux(b === UInt(0), UInt(1), b) // io.modout := a % b // TODO: - io.modout := UInt.Lit(0) + io.modout := UInt(0) io.lshiftout := (a << b(3, 0))(15, 0) io.rshiftout := a >> b io.lessout := a < b diff --git a/src/test/scala/chiselTests/Vec.scala b/src/test/scala/chiselTests/Vec.scala index 22b518a2..e8bd66bd 100644 --- a/src/test/scala/chiselTests/Vec.scala +++ b/src/test/scala/chiselTests/Vec.scala @@ -12,15 +12,15 @@ 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? for ((a,b) <- v.zip(values)) { - assert(a === UInt.Lit(b)) + assert(a === UInt(b)) } stop() } class TabulateTester(n: Int) extends BasicTester { - val v = Vec(Range(0, n).map(i => UInt.Lit(i * 2))) - val x = Vec(Array.tabulate(n){ i => UInt.Lit(i * 2) }) - val u = Vec.tabulate(n)(i => UInt.Lit(i*2)) + val v = Vec(Range(0, n).map(i => UInt(i * 2))) + val x = Vec(Array.tabulate(n){ i => UInt(i * 2) }) + val u = Vec.tabulate(n)(i => UInt(i*2)) assert(v.toBits === x.toBits) assert(v.toBits === u.toBits) @@ -34,8 +34,8 @@ class ShiftRegisterTester(n: Int) extends BasicTester { val shifter = Reg(Vec(n, UInt.width(log2Up(n)))) (shifter, shifter drop 1).zipped.foreach(_ := _) shifter(n-1) := cnt - when (cnt >= UInt.Lit(n)) { - val expected = cnt - UInt.Lit(n) + when (cnt >= UInt(n)) { + val expected = cnt - UInt(n) assert(shifter(0) === expected) } when (wrap) { diff --git a/src/test/scala/chiselTests/When.scala b/src/test/scala/chiselTests/When.scala index 2f5c49e4..07ab3444 100644 --- a/src/test/scala/chiselTests/When.scala +++ b/src/test/scala/chiselTests/When.scala @@ -13,19 +13,19 @@ class WhenTester() extends BasicTester { when(Bool(true)) { cnt.inc() } val out = Wire(UInt.width(3)) - when(cnt.value === UInt.Lit(0)) { - out := UInt.Lit(1) - } .elsewhen (cnt.value === UInt.Lit(1)) { - out := UInt.Lit(2) - } .elsewhen (cnt.value === UInt.Lit(2)) { - out := UInt.Lit(3) + when(cnt.value === UInt(0)) { + out := UInt(1) + } .elsewhen (cnt.value === UInt(1)) { + out := UInt(2) + } .elsewhen (cnt.value === UInt(2)) { + out := UInt(3) } .otherwise { - out := UInt.Lit(0) + out := UInt(0) } - assert(out === cnt.value + UInt.Lit(1)) + assert(out === cnt.value + UInt(1)) - when(cnt.value === UInt.Lit(3)) { + when(cnt.value === UInt(3)) { stop() } } @@ -35,19 +35,19 @@ class OverlappedWhenTester() extends BasicTester { when(Bool(true)) { cnt.inc() } val out = Wire(UInt.width(3)) - when(cnt.value <= UInt.Lit(0)) { - out := UInt.Lit(1) - } .elsewhen (cnt.value <= UInt.Lit(1)) { - out := UInt.Lit(2) - } .elsewhen (cnt.value <= UInt.Lit(2)) { - out := UInt.Lit(3) + when(cnt.value <= UInt(0)) { + out := UInt(1) + } .elsewhen (cnt.value <= UInt(1)) { + out := UInt(2) + } .elsewhen (cnt.value <= UInt(2)) { + out := UInt(3) } .otherwise { - out := UInt.Lit(0) + out := UInt(0) } - assert(out === cnt.value + UInt.Lit(1)) + assert(out === cnt.value + UInt(1)) - when(cnt.value === UInt.Lit(3)) { + when(cnt.value === UInt(3)) { stop() } } -- cgit v1.2.3 From e09a09e3f4e5d6d8650b1db4add96c0a5b09e8ca Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Mon, 25 Jul 2016 16:36:06 -0700 Subject: Enable current (chisel2-style) compatibility mode. --- .../src/main/scala/chisel3/core/Binding.scala | 25 +++++++++++- .../src/main/scala/chisel3/core/Bits.scala | 18 +++++++-- .../src/main/scala/chisel3/core/Data.scala | 1 + src/test/scala/chiselTests/IOCompatibility.scala | 45 ++++++++++++++++++++++ 4 files changed, 83 insertions(+), 6 deletions(-) create mode 100644 src/test/scala/chiselTests/IOCompatibility.scala diff --git a/chiselFrontend/src/main/scala/chisel3/core/Binding.scala b/chiselFrontend/src/main/scala/chisel3/core/Binding.scala index d8d9ebd2..75a80e4f 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Binding.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Binding.scala @@ -112,17 +112,38 @@ object Binding { } // Excepts if any root element is unbound and thus not on the hardware graph - def checkSynthesizable(target: Data, error_prelude: String): Unit = + def checkSynthesizable(target: Data, error_prelude: String): Unit = { + // This is called is we support autoIOWrap + def elementOfIO(element: Data): Boolean = { + element._parent match { + case None => false + case Some(x: Module) => { + // io.flatten eliminates Clock elements, so we need to use io.allElements + val ports = x.io.allElements + val isIOElement = ports.contains(element) || element == x.clock || element == x.reset + isIOElement + } + } + } try walkToBinding( target, element => element.binding match { case SynthesizableBinding() => {} // OK - case binding => throw NotSynthesizableException + case binding => + // The following kludge is an attempt to provide backward compatibility + // It should be done at at higher level. + if (!(autoIOWrap && elementOfIO(element))) + throw NotSynthesizableException + else + Binding.bind(element, PortBinder(element._parent.get), "Error: IO") } ) catch { case BindingException(message) => throw BindingException(s"$error_prelude$message") } + } + // This should be configure by options in Driver. + private[chisel3] var autoIOWrap = true } // Location refers to 'where' in the Module hierarchy this lives diff --git a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala index 6ec455ca..ecae7340 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala @@ -521,10 +521,6 @@ private[core] sealed trait UIntFactory { def width(width: Int): UInt = apply(Width(width)) /** Create a UInt port with specified width. */ def width(width: Width): UInt = new UInt(width) - /** Create a UInt with a specified width - compatibility with Chisel2. */ - def apply(dummy: Option[Direction] = None, width: Int): UInt = apply(Width(width)) - /** Create a UInt literal with inferred width.- compatibility with Chisel2. */ - def apply(value: BigInt): UInt = apply(value, Width()) /** Create a UInt literal with fixed width. */ def apply(value: BigInt, width: Int): UInt = Lit(value, Width(width)) /** Create a UInt literal with inferred width. */ @@ -546,6 +542,20 @@ private[core] sealed trait UIntFactory { result } + /** Create a UInt with a specified width - compatibility with Chisel2. */ + def apply(dummy: Option[Direction] = None, width: Int): UInt = apply(Width(width)) + /** Create a UInt literal with inferred width.- compatibility with Chisel2. */ + def apply(value: BigInt): UInt = apply(value, Width()) + /** Create a UInt with a specified direction and width - compatibility with Chisel2. */ + def apply(direction: Direction, width: Int): UInt = { + val result = apply(Width(width)) + direction match { + case Direction.Input => Input(result) + case Direction.Output => Output(result) + case Direction.Unspecified => result + } + } + private def parse(n: String) = { val (base, num) = n.splitAt(1) val radix = base match { diff --git a/chiselFrontend/src/main/scala/chisel3/core/Data.scala b/chiselFrontend/src/main/scala/chisel3/core/Data.scala index 9e362fa6..73470383 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Data.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Data.scala @@ -16,6 +16,7 @@ sealed abstract class Direction(name: String) { object Direction { object Input extends Direction("input") { override def flip: Direction = Output } object Output extends Direction("output") { override def flip: Direction = Input } + object Unspecified extends Direction("unspecified") { override def flip: Direction = Unspecified } } @deprecated("debug doesn't do anything in Chisel3 as no pruning happens in the frontend", "chisel3") diff --git a/src/test/scala/chiselTests/IOCompatibility.scala b/src/test/scala/chiselTests/IOCompatibility.scala new file mode 100644 index 00000000..b904d77e --- /dev/null +++ b/src/test/scala/chiselTests/IOCompatibility.scala @@ -0,0 +1,45 @@ +// See LICENSE for license details. + +package chiselTests + +import chisel3._ + +class IOCSimpleIO extends Bundle { + val in = UInt(INPUT, 32) + val out = UInt(OUTPUT, 32) +} + +class IOCPlusOne extends Module { + val io = new IOCSimpleIO + io.out := io.in + UInt(1) +} + +class IOCModuleVec(val n: Int) extends Module { + val io = new Bundle { + val ins = Vec(n, UInt(INPUT, 32)) + val outs = Vec(n, UInt(OUTPUT, 32)) + } + val pluses = Vec.fill(n){ Module(new IOCPlusOne).io } + for (i <- 0 until n) { + pluses(i).in := io.ins(i) + io.outs(i) := pluses(i).out + } +} + +class IOCModuleWire extends Module { + val io = new IOCSimpleIO + val inc = Wire(Module(new IOCPlusOne).io.chiselCloneType) + inc.in := io.in + io.out := inc.out +} + +class IOCompatibilitySpec extends ChiselPropSpec { + + property("IOCModuleVec should elaborate") { + elaborate { new IOCModuleVec(2) } + } + + property("IOCModuleWire should elaborate") { + elaborate { new IOCModuleWire } + } +} -- cgit v1.2.3 From 11f119d0aba5ca578f2178cf83ba5096cc26cb22 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Tue, 26 Jul 2016 08:24:45 -0700 Subject: Add ValidIO definition for old code. --- src/main/scala/chisel3/package.scala | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/scala/chisel3/package.scala b/src/main/scala/chisel3/package.scala index 774455c4..926ca00d 100644 --- a/src/main/scala/chisel3/package.scala +++ b/src/main/scala/chisel3/package.scala @@ -111,8 +111,10 @@ package object chisel3 { def do_=/= (that: BitPat)(implicit sourceInfo: SourceInfo): Bool = that =/= x } + // Compatibility with existing code. val INPUT = chisel3.core.Direction.Input val OUTPUT = chisel3.core.Direction.Output val NODIR = chisel3.core.Direction.Unspecified type ChiselException = chisel3.internal.ChiselException + type ValidIO[+T <: Data] = chisel3.util.Valid[T] } -- cgit v1.2.3 From bdbc554c0ccf490dd75d57c57b171452ac3de14b Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Wed, 27 Jul 2016 08:59:11 -0700 Subject: Correct EnqIO/DeqIO Flipped-ness. --- src/main/scala/chisel3/util/Decoupled.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/chisel3/util/Decoupled.scala b/src/main/scala/chisel3/util/Decoupled.scala index 68c3ae88..3ee363a2 100644 --- a/src/main/scala/chisel3/util/Decoupled.scala +++ b/src/main/scala/chisel3/util/Decoupled.scala @@ -64,10 +64,10 @@ object DecoupledIO { } object EnqIO { - def apply[T<:Data](gen: T): DecoupledIO[T] = Flipped(DecoupledIO(gen)) + def apply[T<:Data](gen: T): DecoupledIO[T] = DecoupledIO(gen) } object DeqIO { - def apply[T<:Data](gen: T): DecoupledIO[T] = DecoupledIO(gen) + def apply[T<:Data](gen: T): DecoupledIO[T] = Flipped(DecoupledIO(gen)) } /** An I/O Bundle for Queues -- cgit v1.2.3 From ddeff65c1c50f0a7c3604cdc254538fbf1263d4f Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Wed, 27 Jul 2016 09:13:15 -0700 Subject: Correct EnqIO/DeqIO Flipped-ness. --- src/main/scala/chisel3/compatibility.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/chisel3/compatibility.scala b/src/main/scala/chisel3/compatibility.scala index 041553e0..3b613a5e 100644 --- a/src/main/scala/chisel3/compatibility.scala +++ b/src/main/scala/chisel3/compatibility.scala @@ -108,10 +108,10 @@ package object Chisel { type DecoupledIO[+T <: Data] = chisel3.util.DecoupledIO[T] val DecoupledIO = chisel3.util.DecoupledIO object EnqIO { - def apply[T<:Data](gen: T): DecoupledIO[T] = Flipped(DecoupledIO(gen)) + def apply[T<:Data](gen: T): DecoupledIO[T] = DecoupledIO(gen) } object DeqIO { - def apply[T<:Data](gen: T): DecoupledIO[T] = DecoupledIO(gen) + def apply[T<:Data](gen: T): DecoupledIO[T] = Flipped(DecoupledIO(gen)) } type QueueIO[T <: Data] = chisel3.util.QueueIO[T] type Queue[T <: Data] = chisel3.util.Queue[T] -- cgit v1.2.3 From e065416d59871d790cca9d75dc9a40fcc7b52015 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Wed, 27 Jul 2016 09:13:45 -0700 Subject: Additional compatibility code. --- .../src/main/scala/chisel3/core/Bits.scala | 21 ++++++++++++++- .../src/main/scala/chisel3/core/Module.scala | 2 ++ src/main/scala/chisel3/package.scala | 30 ++++++++++++++++++++++ src/test/scala/chiselTests/DeqIOSpec.scala | 4 +-- src/test/scala/chiselTests/VectorPacketIO.scala | 4 +-- 5 files changed, 56 insertions(+), 5 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala index ecae7340..6df85c6a 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala @@ -33,10 +33,11 @@ abstract class Element(private[core] val width: Width) extends Data { private[core] def binding = _binding /** Return the binding for some bits. */ - def dir: Direction = binding.direction.get + def dir: Direction = binding.direction.getOrElse(Direction.Unspecified) private[chisel3] final def allElements: Seq[Element] = Seq(this) def widthKnown: Boolean = width.known + def name: String = getRef.name } /** A data type for values represented by a single bitvector. Provides basic @@ -709,6 +710,15 @@ object SInt { result.binding = LitBinding() result } + /** Create a SInt with a specified direction and width - compatibility with Chisel2. */ + def apply(direction: Direction, width: Int): SInt = { + val result = apply(Width(width)) + direction match { + case Direction.Input => Input(result) + case Direction.Output => Output(result) + case Direction.Unspecified => result + } + } } // REVIEW TODO: Why does this extend UInt and not Bits? Does defining airth @@ -770,6 +780,15 @@ object Bool { result.binding = LitBinding() result } + /** Create a UInt with a specified direction and width - compatibility with Chisel2. */ + def apply(direction: Direction): Bool = { + val result = apply() + direction match { + case Direction.Input => Input(result) + case Direction.Output => Output(result) + case Direction.Unspecified => result + } + } } object Mux { diff --git a/chiselFrontend/src/main/scala/chisel3/core/Module.scala b/chiselFrontend/src/main/scala/chisel3/core/Module.scala index a593f539..ba0720a4 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Module.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Module.scala @@ -178,4 +178,6 @@ extends HasId { _ids.foreach(_._onModuleClose) this } + // For debuggers/testers + lazy val getPorts = computePorts } diff --git a/src/main/scala/chisel3/package.scala b/src/main/scala/chisel3/package.scala index 926ca00d..5fcf5e67 100644 --- a/src/main/scala/chisel3/package.scala +++ b/src/main/scala/chisel3/package.scala @@ -7,6 +7,9 @@ package object chisel3 { import internal.sourceinfo.{SourceInfo, SourceInfoTransform} import util.BitPat + import chisel3.core.{Binding, Bits, Element, FlippedBinder} + import chisel3.util._ + import chisel3.internal.firrtl.Port type Direction = chisel3.core.Direction object Input { @@ -117,4 +120,31 @@ package object chisel3 { val NODIR = chisel3.core.Direction.Unspecified type ChiselException = chisel3.internal.ChiselException type ValidIO[+T <: Data] = chisel3.util.Valid[T] + val Decoupled = chisel3.util.DecoupledIO + + class EnqIO[+T <: Data](gen: T) extends DecoupledIO(gen) { + def init(): Unit = { + this.noenq() + } + override def cloneType: this.type = EnqIO(gen).asInstanceOf[this.type] + } + class DeqIO[+T <: Data](gen: T) extends DecoupledIO(gen) { + Binding.bind(this, FlippedBinder, "Error: Cannot flip ") + def init(): Unit = { + this.nodeq() + } + override def cloneType: this.type = DeqIO(gen).asInstanceOf[this.type] + } + object EnqIO { + def apply[T<:Data](gen: T): EnqIO[T] = new EnqIO(gen) + } + object DeqIO { + def apply[T<:Data](gen: T): DeqIO[T] = new DeqIO(gen) + } + + // Debugger/Tester access to internal Chisel data structures and methods. + def getDataElements(a: Aggregate): Seq[Element] = { + a.allElements + } + def getModulePorts(m: Module): Seq[Port] = m.getPorts } diff --git a/src/test/scala/chiselTests/DeqIOSpec.scala b/src/test/scala/chiselTests/DeqIOSpec.scala index cd8a5d63..d41c50e5 100644 --- a/src/test/scala/chiselTests/DeqIOSpec.scala +++ b/src/test/scala/chiselTests/DeqIOSpec.scala @@ -17,8 +17,8 @@ class UsesDeqIOInfo extends Bundle { class UsesDeqIO extends Module { val io = IO(new Bundle { - val in = DeqIO(new UsesDeqIOInfo) - val out = EnqIO(new UsesDeqIOInfo) + val in = chisel3.util.DeqIO(new UsesDeqIOInfo) + val out = chisel3.util.EnqIO(new UsesDeqIOInfo) }) } diff --git a/src/test/scala/chiselTests/VectorPacketIO.scala b/src/test/scala/chiselTests/VectorPacketIO.scala index 6e1d267d..86c0d66f 100644 --- a/src/test/scala/chiselTests/VectorPacketIO.scala +++ b/src/test/scala/chiselTests/VectorPacketIO.scala @@ -28,8 +28,8 @@ class Packet extends Bundle { * The problem does not occur if the Vec is taken out */ class VectorPacketIO(n: Int) extends Bundle { - val ins = Vec(n, DeqIO(new Packet())) - val outs = Vec(n, EnqIO(new Packet())) + val ins = Vec(n, chisel3.util.DeqIO(new Packet())) + val outs = Vec(n, chisel3.util.EnqIO(new Packet())) } /** -- cgit v1.2.3 From 87d69afd1c8f28d91c78e7a539f6bf7a908e2a1f Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Wed, 27 Jul 2016 09:35:02 -0700 Subject: Correct EnqIO/DeqIO Flipped-ness. --- src/main/scala/chisel3/util/Decoupled.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/chisel3/util/Decoupled.scala b/src/main/scala/chisel3/util/Decoupled.scala index 3ee363a2..0d000f49 100644 --- a/src/main/scala/chisel3/util/Decoupled.scala +++ b/src/main/scala/chisel3/util/Decoupled.scala @@ -76,9 +76,9 @@ object DeqIO { class QueueIO[T <: Data](gen: T, entries: Int) extends Bundle { /** I/O to enqueue data, is [[Chisel.DecoupledIO]] flipped */ - val enq = EnqIO(gen) + val enq = DeqIO(gen) /** I/O to enqueue data, is [[Chisel.DecoupledIO]]*/ - val deq = DeqIO(gen) + val deq = EnqIO(gen) /** The current amount of data in the queue */ val count = Output(UInt.width(log2Up(entries + 1))) } -- cgit v1.2.3 From 089987c3e0b2bc390935a4d9d44db38a18c47901 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Wed, 27 Jul 2016 10:29:13 -0700 Subject: Correct EnqIO/DeqIO Flipped-ness. --- src/test/scala/chiselTests/VectorPacketIO.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/scala/chiselTests/VectorPacketIO.scala b/src/test/scala/chiselTests/VectorPacketIO.scala index 86c0d66f..b8e3a154 100644 --- a/src/test/scala/chiselTests/VectorPacketIO.scala +++ b/src/test/scala/chiselTests/VectorPacketIO.scala @@ -41,8 +41,8 @@ class BrokenVectorPacketModule extends Module { val io = IO(new VectorPacketIO(n)) /* the following method of initializing the circuit may change in the future */ - io.ins.foreach(_.noenq()) - io.outs.foreach(_.nodeq()) + io.ins.foreach(_.nodeq()) + io.outs.foreach(_.noenq()) } class VectorPacketIOUnitTester extends BasicTester { -- cgit v1.2.3 From 138329479914ac37b49a5a44841dc1de2929dca5 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Wed, 27 Jul 2016 10:36:55 -0700 Subject: More compatibility fixes --- src/main/scala/chisel3/compatibility.scala | 13 +++++++++++++ src/main/scala/chisel3/package.scala | 3 ++- src/test/scala/chiselTests/Direction.scala | 2 +- src/test/scala/chiselTests/IOCompatibility.scala | 2 +- 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/main/scala/chisel3/compatibility.scala b/src/main/scala/chisel3/compatibility.scala index 3b613a5e..a7968bd5 100644 --- a/src/main/scala/chisel3/compatibility.scala +++ b/src/main/scala/chisel3/compatibility.scala @@ -107,6 +107,19 @@ package object Chisel { type DecoupledIO[+T <: Data] = chisel3.util.DecoupledIO[T] val DecoupledIO = chisel3.util.DecoupledIO + class EnqIO[+T <: Data](gen: T) extends DecoupledIO(gen) { + def init(): Unit = { + this.noenq() + } + override def cloneType: this.type = EnqIO(gen).asInstanceOf[this.type] + } + class DeqIO[+T <: Data](gen: T) extends DecoupledIO(gen) { + chisel3.core.Binding.bind(this, chisel3.core.FlippedBinder, "Error: Cannot flip ") + def init(): Unit = { + this.nodeq() + } + override def cloneType: this.type = DeqIO(gen).asInstanceOf[this.type] + } object EnqIO { def apply[T<:Data](gen: T): DecoupledIO[T] = DecoupledIO(gen) } diff --git a/src/main/scala/chisel3/package.scala b/src/main/scala/chisel3/package.scala index 5fcf5e67..a0264df4 100644 --- a/src/main/scala/chisel3/package.scala +++ b/src/main/scala/chisel3/package.scala @@ -7,7 +7,7 @@ package object chisel3 { import internal.sourceinfo.{SourceInfo, SourceInfoTransform} import util.BitPat - import chisel3.core.{Binding, Bits, Element, FlippedBinder} + import chisel3.core.{Binding, FlippedBinder} import chisel3.util._ import chisel3.internal.firrtl.Port @@ -120,6 +120,7 @@ package object chisel3 { val NODIR = chisel3.core.Direction.Unspecified type ChiselException = chisel3.internal.ChiselException type ValidIO[+T <: Data] = chisel3.util.Valid[T] + val ValidIO = chisel3.util.Valid val Decoupled = chisel3.util.DecoupledIO class EnqIO[+T <: Data](gen: T) extends DecoupledIO(gen) { diff --git a/src/test/scala/chiselTests/Direction.scala b/src/test/scala/chiselTests/Direction.scala index 83484a64..949b92ed 100644 --- a/src/test/scala/chiselTests/Direction.scala +++ b/src/test/scala/chiselTests/Direction.scala @@ -31,7 +31,7 @@ class DirectionSpec extends ChiselPropSpec with ShouldMatchers { } property("Inputs should not be assignable") { - a[ChiselException] should be thrownBy { + a[Exception] should be thrownBy { elaborate(new BadDirection) } } diff --git a/src/test/scala/chiselTests/IOCompatibility.scala b/src/test/scala/chiselTests/IOCompatibility.scala index b904d77e..edbd3d09 100644 --- a/src/test/scala/chiselTests/IOCompatibility.scala +++ b/src/test/scala/chiselTests/IOCompatibility.scala @@ -2,7 +2,7 @@ package chiselTests -import chisel3._ +import Chisel._ class IOCSimpleIO extends Bundle { val in = UInt(INPUT, 32) -- cgit v1.2.3 From ac5bc19b5b4a3cc631900acf9dc04386a5c5cddc Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Thu, 28 Jul 2016 17:00:12 -0700 Subject: Add missing factory constructors. --- chiselFrontend/src/main/scala/chisel3/core/Bits.scala | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala index 6df85c6a..9ef46402 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala @@ -526,6 +526,8 @@ private[core] sealed trait UIntFactory { def apply(value: BigInt, width: Int): UInt = Lit(value, Width(width)) /** Create a UInt literal with inferred width. */ def apply(n: String): UInt = Lit(n) + /** Create a UInt literal with fixed width. */ + def apply(n: String, width: Int): UInt = Lit(parse(n), width) /** Create a UInt literal with specified width. */ def apply(value: BigInt, width: Width): UInt = Lit(value, width) def Lit(value: BigInt, width: Int): UInt = Lit(value, Width(width)) @@ -544,13 +546,13 @@ private[core] sealed trait UIntFactory { } /** Create a UInt with a specified width - compatibility with Chisel2. */ - def apply(dummy: Option[Direction] = None, width: Int): UInt = apply(Width(width)) + def apply(dir: Option[Direction] = None, width: Int): UInt = apply(Width(width)) /** Create a UInt literal with inferred width.- compatibility with Chisel2. */ def apply(value: BigInt): UInt = apply(value, Width()) /** Create a UInt with a specified direction and width - compatibility with Chisel2. */ - def apply(direction: Direction, width: Int): UInt = { + def apply(dir: Direction, width: Int): UInt = { val result = apply(Width(width)) - direction match { + dir match { case Direction.Input => Input(result) case Direction.Output => Output(result) case Direction.Unspecified => result @@ -710,10 +712,12 @@ object SInt { result.binding = LitBinding() result } + /** Create a SInt with a specified width - compatibility with Chisel2. */ + def apply(dir: Option[Direction] = None, width: Int): SInt = apply(Width(width)) /** Create a SInt with a specified direction and width - compatibility with Chisel2. */ - def apply(direction: Direction, width: Int): SInt = { + def apply(dir: Direction, width: Int): SInt = { val result = apply(Width(width)) - direction match { + dir match { case Direction.Input => Input(result) case Direction.Output => Output(result) case Direction.Unspecified => result @@ -781,9 +785,9 @@ object Bool { result } /** Create a UInt with a specified direction and width - compatibility with Chisel2. */ - def apply(direction: Direction): Bool = { + def apply(dir: Direction): Bool = { val result = apply() - direction match { + dir match { case Direction.Input => Input(result) case Direction.Output => Output(result) case Direction.Unspecified => result -- cgit v1.2.3 From 81d60a4076eab24553f67ae6b85031d2075a5fac Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Thu, 28 Jul 2016 17:20:33 -0700 Subject: Add missing Decoupled object pointer. --- src/main/scala/chisel3/compatibility.scala | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/scala/chisel3/compatibility.scala b/src/main/scala/chisel3/compatibility.scala index a7968bd5..939e005a 100644 --- a/src/main/scala/chisel3/compatibility.scala +++ b/src/main/scala/chisel3/compatibility.scala @@ -107,6 +107,7 @@ package object Chisel { type DecoupledIO[+T <: Data] = chisel3.util.DecoupledIO[T] val DecoupledIO = chisel3.util.DecoupledIO + val Decoupled = chisel3.util.DecoupledIO class EnqIO[+T <: Data](gen: T) extends DecoupledIO(gen) { def init(): Unit = { this.noenq() -- cgit v1.2.3 From 8b66107bffac270be16196d5a852cf3e6808fb0a Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Sun, 31 Jul 2016 17:05:21 -0700 Subject: Fix two deprecation warnings --- chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala | 2 +- src/main/scala/chisel3/util/OneHot.scala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala b/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala index 0872ec41..63bcc87f 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala @@ -47,7 +47,7 @@ private[chisel3] object SeqUtils { if (in.tail.isEmpty) { in.head._2 } else { - val masked = for ((s, i) <- in) yield Mux(s, i.toBits, Bits(0)) + val masked = for ((s, i) <- in) yield Mux(s, i.asUInt, UInt(0)) val width = in.map(_._2.width).reduce(_ max _) in.head._2.cloneTypeWidth(width).fromBits(masked.reduceLeft(_|_)) } diff --git a/src/main/scala/chisel3/util/OneHot.scala b/src/main/scala/chisel3/util/OneHot.scala index abede61e..7e04a8d7 100644 --- a/src/main/scala/chisel3/util/OneHot.scala +++ b/src/main/scala/chisel3/util/OneHot.scala @@ -11,7 +11,7 @@ import chisel3._ * This is the inverse of [[Chisel.UIntToOH UIntToOH]]*/ object OHToUInt { 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: Vec[Bool]): UInt = apply(in.asUInt, in.size) def apply(in: Bits): UInt = apply(in, in.getWidth) def apply(in: Bits, width: Int): UInt = { -- cgit v1.2.3 From 8b0fa7826a547f9123277119aabc58f7c75e2ca3 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Sun, 31 Jul 2016 17:26:11 -0700 Subject: Expose asUInt from Data Deprecating toBits removes the capability to cast an arbitrary type to UInt. While it's still possible to do so using asBits.asUInt, this creates boilerplate. (asBits is almost never useful itself.) --- chiselFrontend/src/main/scala/chisel3/core/Bits.scala | 9 --------- chiselFrontend/src/main/scala/chisel3/core/Data.scala | 12 ++++++++++++ 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala index 94d808a4..9cca5d9d 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala @@ -210,15 +210,6 @@ sealed abstract class Bits(dirArg: Direction, width: Width, override val litArg: 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 diff --git a/chiselFrontend/src/main/scala/chisel3/core/Data.scala b/chiselFrontend/src/main/scala/chisel3/core/Data.scala index d5704369..d31e50ff 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Data.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Data.scala @@ -114,6 +114,18 @@ abstract class Data(dirArg: Direction) extends HasId { */ @deprecated("Use asBits, which makes the reinterpret cast more explicit and actually returns Bits", "chisel3") def toBits(): UInt = SeqUtils.do_asUInt(this.flatten)(DeprecatedSourceInfo) + + /** Reinterpret cast to 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 + * @note Aggregates are recursively packed with the first element appearing + * in the least-significant bits of the result. + */ + final def asUInt(): UInt = macro SourceInfoTransform.noArg + + def do_asUInt(implicit sourceInfo: SourceInfo): UInt = + SeqUtils.do_asUInt(this.flatten)(sourceInfo) } object Wire { -- cgit v1.2.3 From ce42ef15128a626e723249ae7b129fb5a370fa9c Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Sun, 31 Jul 2016 18:01:01 -0700 Subject: Remove deprecated FileSystemUtilities This has been deprecated for a long time now (and really shouldn't have existed to begin with). --- src/main/scala/chisel3/compatibility.scala | 1 - .../scala/chisel3/compatibility/FileSystemUtilities.scala | 12 ------------ 2 files changed, 13 deletions(-) delete mode 100644 src/main/scala/chisel3/compatibility/FileSystemUtilities.scala diff --git a/src/main/scala/chisel3/compatibility.scala b/src/main/scala/chisel3/compatibility.scala index c0e933e0..56c92d24 100644 --- a/src/main/scala/chisel3/compatibility.scala +++ b/src/main/scala/chisel3/compatibility.scala @@ -57,7 +57,6 @@ package object Chisel { 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 diff --git a/src/main/scala/chisel3/compatibility/FileSystemUtilities.scala b/src/main/scala/chisel3/compatibility/FileSystemUtilities.scala deleted file mode 100644 index cd47c731..00000000 --- a/src/main/scala/chisel3/compatibility/FileSystemUtilities.scala +++ /dev/null @@ -1,12 +0,0 @@ -// See LICENSE for license details. - -package chisel3.compatibility - -import chisel3._ - -@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) - } -} -- cgit v1.2.3 From c661d9c8def3a14e9e8a42d96005ead78e11e34d Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Wed, 3 Aug 2016 13:57:03 -0700 Subject: Merge "package" code into "compatibility". --- src/main/scala/chisel3/compatibility.scala | 50 ++++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 10 deletions(-) diff --git a/src/main/scala/chisel3/compatibility.scala b/src/main/scala/chisel3/compatibility.scala index 939e005a..d4ad7b9f 100644 --- a/src/main/scala/chisel3/compatibility.scala +++ b/src/main/scala/chisel3/compatibility.scala @@ -57,6 +57,46 @@ package object Chisel { val when = chisel3.core.when type WhenContext = chisel3.core.WhenContext + import chisel3.internal.firrtl.Width + /** + * These implicit classes allow one to convert scala.Int|scala.BigInt to + * Chisel.UInt|Chisel.SInt by calling .asUInt|.asSInt on them, respectively. + * The versions .asUInt(width)|.asSInt(width) are also available to explicitly + * mark a width for the new literal. + * + * Also provides .asBool to scala.Boolean and .asUInt to String + * + * Note that, for stylistic reasons, one should avoid extracting immediately + * after this call using apply, ie. 0.asUInt(1)(0) due to potential for + * confusion (the 1 is a bit length and the 0 is a bit extraction position). + * Prefer storing the result and then extracting from it. + */ + implicit class fromIntToLiteral(val x: Int) extends AnyVal { + def U: UInt = UInt(BigInt(x), Width()) + def S: SInt = SInt(BigInt(x), Width()) + + def asUInt() = UInt(x, Width()) + def asSInt() = SInt(x, Width()) + def asUInt(width: Int) = UInt(x, width) + def asSInt(width: Int) = SInt(x, width) + } + + implicit class fromBigIntToLiteral(val x: BigInt) extends AnyVal { + def U: UInt = UInt(x, Width()) + def S: SInt = SInt(x, Width()) + + def asUInt() = UInt(x, Width()) + def asSInt() = SInt(x, Width()) + def asUInt(width: Int) = UInt(x, width) + def asSInt(width: Int) = SInt(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) + } + type BackendCompilationUtilities = chisel3.BackendCompilationUtilities val Driver = chisel3.Driver @@ -158,14 +198,4 @@ package object Chisel { 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) } -- cgit v1.2.3 From 8e24085e112d595cfaf2dc7d54bce974498521d5 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Thu, 4 Aug 2016 13:40:35 -0700 Subject: Deal with directions on Clocks. --- chiselFrontend/src/main/scala/chisel3/core/Data.scala | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/chiselFrontend/src/main/scala/chisel3/core/Data.scala b/chiselFrontend/src/main/scala/chisel3/core/Data.scala index 8c874070..9115d1ba 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Data.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Data.scala @@ -227,6 +227,14 @@ object Wire { object Clock { def apply(): Clock = new Clock + def apply(dir: Direction): Clock = { + val result = apply() + dir match { + case Direction.Input => Input(result) + case Direction.Output => Output(result) + case Direction.Unspecified => result + } + } } // TODO: Document this. -- cgit v1.2.3 From ef74500b8ae2d3804a43aa5a1fecc59cfbea13f5 Mon Sep 17 00:00:00 2001 From: Colin Schmidt Date: Tue, 9 Aug 2016 10:51:04 -0700 Subject: counter(inc,n) example should reflect actual use (#252) --- src/main/scala/chisel3/util/Counter.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/chisel3/util/Counter.scala b/src/main/scala/chisel3/util/Counter.scala index 40615769..1c95190b 100644 --- a/src/main/scala/chisel3/util/Counter.scala +++ b/src/main/scala/chisel3/util/Counter.scala @@ -32,8 +32,8 @@ class Counter(val n: Int) { /** Counter Object * Example Usage: * {{{ val countOn = Bool(true) // increment counter every clock cycle - * val myCounter = Counter(countOn, n) - * when ( myCounter.value === UInt(3) ) { ... } }}}*/ + * val (myCounterValue, myCounterWrap) = Counter(countOn, n) + * when ( myCounterValue === UInt(3) ) { ... } }}}*/ object Counter { def apply(n: Int): Counter = new Counter(n) -- cgit v1.2.3 From c907eabfb65cd6442e35588b095ca031e2bdad7a Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Sun, 7 Aug 2016 17:09:42 -0700 Subject: Legalize identifier names before printing It's not entirely clear what the FIRRTL implementation supports, so I'm using the ANSI C requirements for the time being. --- .../src/main/scala/chisel3/internal/Builder.scala | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala b/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala index 0e0a88cc..cecbd91e 100644 --- a/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala +++ b/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala @@ -21,16 +21,25 @@ private[chisel3] class Namespace(parent: Option[Namespace], keywords: Set[String if (this contains tryName) rename(n) else tryName } + private def sanitize(s: String): String = { + // TODO what character set does FIRRTL truly support? using ANSI C for now + def legalStart(c: Char) = (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' + def legal(c: Char) = legalStart(c) || (c >= '0' && c <= '9') + val res = s filter legal + if (res.isEmpty || !legalStart(res.head)) s"_$res" else res + } + 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)) + val sanitized = sanitize(elem) + if (this contains sanitized) { + name(rename(sanitized)) } else { - names(elem) = 1 - elem + names(sanitized) = 1 + sanitized } } -- cgit v1.2.3 From 2a074c828ddd8e6c20fa21d618664d50120f3d7a Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Sun, 7 Aug 2016 17:11:24 -0700 Subject: Support Module name overrides with "override def desiredName" The API allowed this before, but not safely, as users could create name conflicts. This exposes the pre-deduplication/sanitization naming API, and closes the other one. --- .../src/main/scala/chisel3/core/Module.scala | 7 +++-- .../scala/chisel3/internal/firrtl/Emitter.scala | 30 ++++++++++++---------- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/Module.scala b/chiselFrontend/src/main/scala/chisel3/core/Module.scala index ca91c5f8..5af744c4 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Module.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Module.scala @@ -57,8 +57,11 @@ extends HasId { private[core] val _ids = ArrayBuffer[HasId]() dynamicContext.currentModule = Some(this) - /** Name of the instance. */ - val name = Builder.globalNamespace.name(getClass.getName.split('.').last) + /** Desired name of this module. */ + def desiredName = this.getClass.getName.split('.').last + + /** Legalized name of this module. */ + final val name = Builder.globalNamespace.name(desiredName) /** IO for this Module. At the Scala level (pre-FIRRTL transformations), * connections in and out of a Module may only go through `io` elements. diff --git a/src/main/scala/chisel3/internal/firrtl/Emitter.scala b/src/main/scala/chisel3/internal/firrtl/Emitter.scala index 08646cf9..31856541 100644 --- a/src/main/scala/chisel3/internal/firrtl/Emitter.scala +++ b/src/main/scala/chisel3/internal/firrtl/Emitter.scala @@ -46,18 +46,21 @@ private class Emitter(circuit: Circuit) { } // Map of Module FIRRTL definition to FIRRTL name, if it has been emitted already. - private val defnMap = collection.mutable.HashMap[String, String]() + private val defnMap = collection.mutable.HashMap[(String, String), Component]() // Map of Component name to FIRRTL id. private val moduleMap = collection.mutable.HashMap[String, String]() - /** Generates the FIRRTL module definition with a specified name. + /** Generates the FIRRTL module declaration. */ - private def moduleDefn(m: Component, name: String): String = { + private def moduleDecl(m: Component): String = m.id match { + case _: BlackBox => newline + s"extmodule ${m.name} : " + case _: Module => newline + s"module ${m.name} : " + } + + /** Generates the FIRRTL module definition. + */ + private def moduleDefn(m: Component): 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) @@ -82,21 +85,20 @@ private class Emitter(circuit: Circuit) { */ private def emit(m: Component): String = { // Generate the body. - val moduleName = m.id.getClass.getName.split('.').last - val defn = moduleDefn(m, moduleName) + val defn = moduleDefn(m) - defnMap get defn match { - case Some(deduplicatedName) => - moduleMap(m.name) = deduplicatedName + defnMap get (m.id.desiredName, defn) match { + case Some(duplicate) => + moduleMap(m.name) = duplicate.name "" case None => require(!(moduleMap contains m.name), "emitting module with same name but different contents") moduleMap(m.name) = m.name - defnMap(defn) = m.name + defnMap((m.id.desiredName, defn)) = m - moduleDefn(m, m.name) + moduleDecl(m) + defn } } -- cgit v1.2.3 From 8c8349e3eab69235f48826b59af8f67fe0b3e80c Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Fri, 12 Aug 2016 09:39:39 -0700 Subject: Add support for per-Module compilation options. Nothing uses these now, but when we integrate Stephen's PR200, we'll need a way to selectively enable some strict connection checks on a file by file basis. We plan to do this using package imports which will define suitable compilation options. --- .../src/main/scala/chisel3/internal/Builder.scala | 11 ++++++++--- .../src/main/scala/chisel3/internal/CompileOptions.scala | 16 ++++++++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 chiselFrontend/src/main/scala/chisel3/internal/CompileOptions.scala diff --git a/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala b/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala index cecbd91e..68dd269c 100644 --- a/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala +++ b/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala @@ -97,12 +97,16 @@ private[chisel3] trait HasId { private[chisel3] def getRef: Arg = _ref.get } -private[chisel3] class DynamicContext { +private[chisel3] class DynamicContext(optionMap: Option[Map[String, String]] = None) { val idGen = new IdGen val globalNamespace = new Namespace(None, Set()) val components = ArrayBuffer[Component]() var currentModule: Option[Module] = None val errors = new ErrorLog + val compileOptions = new CompileOptions(optionMap match { + case Some(map: Map[String, String]) => map + case None => Map[String, String]() + }) } private[chisel3] object Builder { @@ -115,6 +119,7 @@ private[chisel3] object Builder { def globalNamespace: Namespace = dynamicContext.globalNamespace def components: ArrayBuffer[Component] = dynamicContext.components + def compileOptions = dynamicContext.compileOptions def pushCommand[T <: Command](c: T): T = { dynamicContext.currentModule.foreach(_._commands += c) c @@ -124,8 +129,8 @@ private[chisel3] object Builder { 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)) { + def build[T <: Module](f: => T, optionMap: Option[Map[String, String]] = None): Circuit = { + dynamicContextVar.withValue(Some(new DynamicContext(optionMap))) { errors.info("Elaborating design...") val mod = f mod.forceName(mod.name, globalNamespace) diff --git a/chiselFrontend/src/main/scala/chisel3/internal/CompileOptions.scala b/chiselFrontend/src/main/scala/chisel3/internal/CompileOptions.scala new file mode 100644 index 00000000..12789855 --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel3/internal/CompileOptions.scala @@ -0,0 +1,16 @@ +// See LICENSE for license details. + +package chisel3.internal + +/** Initialize compilation options from a string map. + * + * @param optionsMap the map from "option" to "value" + */ +class CompileOptions(optionsMap: Map[String, String]) { + // The default for settings related to "strictness". + val strictDefault: String = optionsMap.getOrElse("strict", "false") + // Should Bundle connections require a strict match of fields. + // If true and the same fields aren't present in both source and sink, a MissingFieldException, + // MissingLeftFieldException, or MissingRightFieldException will be thrown. + val connectFieldsMustMatch: Boolean = optionsMap.getOrElse("connectFieldsMustMatch", strictDefault).toBoolean +} -- cgit v1.2.3 From 4ab2aa0e9209000fb0ba1299ac18db2e033f708f Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Fri, 12 Aug 2016 14:17:52 -0700 Subject: Use compileOptions to determine if Missing...FieldExceptions are thrown. --- .../src/main/scala/chisel3/core/BiConnect.scala | 16 ++++++++++++---- .../src/main/scala/chisel3/core/MonoConnect.scala | 10 +++++++--- .../src/main/scala/chisel3/internal/Builder.scala | 2 +- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala b/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala index cb76159a..71de50f6 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala @@ -1,9 +1,9 @@ package chisel3.core -import chisel3.internal.Builder.pushCommand +import chisel3.internal.Builder.{compileOptions, pushCommand} import chisel3.internal.firrtl.Connect import scala.language.experimental.macros -import chisel3.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, UnlocatableSourceInfo, WireTransform, SourceInfoTransform} +import chisel3.internal.sourceinfo._ /** * BiConnect.connect executes a bidirectional connection element-wise. @@ -69,14 +69,22 @@ object BiConnect { case (left_b: Bundle, right_b: Bundle) => { // Verify right has no extra fields that left doesn't have for((field, right_sub) <- right_b.elements) { - if(!left_b.elements.isDefinedAt(field)) throw MissingLeftFieldException(field) + if(!left_b.elements.isDefinedAt(field)) { + if (compileOptions.connectFieldsMustMatch) { + throw MissingLeftFieldException(field) + } + } } // For each field in left, descend with right for((field, left_sub) <- left_b.elements) { try { right_b.elements.get(field) match { case Some(right_sub) => connect(sourceInfo, left_sub, right_sub, context_mod) - case None => throw MissingRightFieldException(field) + case None => { + if (compileOptions.connectFieldsMustMatch) { + throw MissingRightFieldException(field) + } + } } } catch { case BiConnectException(message) => throw BiConnectException(s".$field$message") diff --git a/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala b/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala index 64c71cb2..bf8e7e28 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala @@ -1,9 +1,9 @@ package chisel3.core -import chisel3.internal.Builder.pushCommand +import chisel3.internal.Builder.{compileOptions, pushCommand} import chisel3.internal.firrtl.Connect import scala.language.experimental.macros -import chisel3.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, UnlocatableSourceInfo, WireTransform, SourceInfoTransform} +import chisel3.internal.sourceinfo.{DeprecatedSourceInfo, SourceInfo, SourceInfoTransform, UnlocatableSourceInfo, WireTransform} /** * MonoConnect.connect executes a mono-directional connection element-wise. @@ -78,7 +78,11 @@ object MonoConnect { try { source_b.elements.get(field) match { case Some(source_sub) => connect(sourceInfo, sink_sub, source_sub, context_mod) - case None => throw MissingFieldException(field) + case None => { + if (compileOptions.connectFieldsMustMatch) { + throw MissingFieldException(field) + } + } } } catch { case MonoConnectException(message) => throw MonoConnectException(s".$field$message") diff --git a/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala b/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala index dddc261e..9f2b1631 100644 --- a/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala +++ b/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala @@ -118,6 +118,7 @@ private[chisel3] object Builder { def idGen: IdGen = dynamicContext.idGen def globalNamespace: Namespace = dynamicContext.globalNamespace def components: ArrayBuffer[Component] = dynamicContext.components + def compileOptions = dynamicContext.compileOptions def currentModule: Option[Module] = dynamicContext.currentModule def currentModule_=(target: Option[Module]): Unit = { @@ -133,7 +134,6 @@ private[chisel3] object Builder { // TODO(twigg): Ideally, binding checks and new bindings would all occur here // However, rest of frontend can't support this yet. - def compileOptions = dynamicContext.compileOptions def pushCommand[T <: Command](c: T): T = { forcedModule._commands += c c -- cgit v1.2.3 From ddb7278760029be9d960ba8bf2b06ac8a8aac767 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Mon, 15 Aug 2016 22:48:14 -0700 Subject: Make "def width" a private API; expose isWidthKnown instead (#257) * Make "def width" a private API; expose isWidthKnown instead Resolves #256. Since width was used to determine whether getWidth would succeed, I added def isWidthKnown: Boolean but another option would be to expose something like def widthOption: Option[Int] ...thoughts? * Document getWidth/isWidthKnown * Add widthOption for more idiomatic Scala manipulation of widths --- chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala | 5 +++-- chiselFrontend/src/main/scala/chisel3/core/Bits.scala | 2 +- chiselFrontend/src/main/scala/chisel3/core/Data.scala | 8 +++++++- src/main/scala/chisel3/util/BitPat.scala | 2 +- src/main/scala/chisel3/util/Bitwise.scala | 2 +- src/test/scala/chiselTests/Reg.scala | 10 +++++----- 6 files changed, 18 insertions(+), 11 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala index f2774a8d..15643ac8 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala @@ -16,7 +16,7 @@ import chisel3.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, VecTransfo */ 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(_ + _) + private[core] def width: Width = flatten.map(_.width).reduce(_ + _) } object Vec { @@ -373,5 +373,6 @@ class Bundle extends Aggregate(NO_DIR) { } private[core] object Bundle { - val keywords = List("flip", "asInput", "asOutput", "cloneType", "toBits") + val keywords = List("flip", "asInput", "asOutput", "cloneType", "toBits", + "widthOption") } diff --git a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala index 9cca5d9d..015b9dfb 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala @@ -14,7 +14,7 @@ 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. */ -abstract class Element(dirArg: Direction, val width: Width) extends Data(dirArg) +abstract class Element(dirArg: Direction, private[core] val width: Width) extends Data(dirArg) /** A data type for values represented by a single bitvector. Provides basic * bitwise operations. diff --git a/chiselFrontend/src/main/scala/chisel3/core/Data.scala b/chiselFrontend/src/main/scala/chisel3/core/Data.scala index d31e50ff..8826af51 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Data.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Data.scala @@ -56,6 +56,7 @@ abstract class Data(dirArg: Direction) extends HasId { private[chisel3] def ref: Arg = if (isLit) litArg.get else lref private[core] def cloneTypeWidth(width: Width): this.type private[chisel3] def toType: String + private[core] def width: Width def := (that: Data)(implicit sourceInfo: SourceInfo): Unit = this badConnect that @@ -66,8 +67,13 @@ abstract class Data(dirArg: Direction) extends HasId { def litValue(): BigInt = litArg.get.num def isLit(): Boolean = litArg.isDefined - def width: Width + /** Returns the width, in bits, if currently known. + * @throws java.util.NoSuchElementException if the width is not known. */ final def getWidth: Int = width.get + /** Returns whether the width is currently known. */ + final def isWidthKnown: Boolean = width.known + /** Returns Some(width) if the width is known, else None. */ + final def widthOption: Option[Int] = if (isWidthKnown) Some(getWidth) else None // While this being in the Data API doesn't really make sense (should be in // Aggregate, right?) this is because of an implementation limitation: diff --git a/src/main/scala/chisel3/util/BitPat.scala b/src/main/scala/chisel3/util/BitPat.scala index d476f957..26106080 100644 --- a/src/main/scala/chisel3/util/BitPat.scala +++ b/src/main/scala/chisel3/util/BitPat.scala @@ -68,7 +68,7 @@ object BitPat { */ def apply(x: UInt): BitPat = { require(x.isLit) - val len = if (x.width.known) x.getWidth else 0 + val len = if (x.isWidthKnown) x.getWidth else 0 apply("b" + x.litValue.toString(2).reverse.padTo(len, "0").reverse.mkString) } } diff --git a/src/main/scala/chisel3/util/Bitwise.scala b/src/main/scala/chisel3/util/Bitwise.scala index 3134d043..6451ab14 100644 --- a/src/main/scala/chisel3/util/Bitwise.scala +++ b/src/main/scala/chisel3/util/Bitwise.scala @@ -29,7 +29,7 @@ object Fill { n match { case 0 => UInt(width=0) case 1 => x - case _ if x.width.known && x.getWidth == 1 => + case _ if x.isWidthKnown && 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)) diff --git a/src/test/scala/chiselTests/Reg.scala b/src/test/scala/chiselTests/Reg.scala index fc2cbf9d..a92d5ebf 100644 --- a/src/test/scala/chiselTests/Reg.scala +++ b/src/test/scala/chiselTests/Reg.scala @@ -16,7 +16,7 @@ class RegSpec extends ChiselFlatSpec { "A Reg" should "be of the same type and width as outType, if specified" in { class RegOutTypeWidthTester extends BasicTester { val reg = Reg(t=UInt(width=2), next=UInt(width=3), init=UInt(20)) - reg.width.get should be (2) + reg.getWidth should be (2) } elaborate{ new RegOutTypeWidthTester } } @@ -24,11 +24,11 @@ class RegSpec extends ChiselFlatSpec { "A Reg" should "be of unknown width if outType is not specified and width is not forced" in { class RegUnknownWidthTester extends BasicTester { val reg1 = Reg(next=UInt(width=3), init=UInt(20)) - reg1.width.known should be (false) + reg1.isWidthKnown should be (false) val reg2 = Reg(init=UInt(20)) - reg2.width.known should be (false) + reg2.isWidthKnown should be (false) val reg3 = Reg(next=UInt(width=3), init=UInt(width=5)) - reg3.width.known should be (false) + reg3.isWidthKnown should be (false) } elaborate { new RegUnknownWidthTester } } @@ -36,7 +36,7 @@ class RegSpec extends ChiselFlatSpec { "A Reg" should "be of width of init if outType and next are missing and init is a literal of forced width" in { class RegForcedWidthTester extends BasicTester { val reg2 = Reg(init=UInt(20, width=7)) - reg2.width.get should be (7) + reg2.getWidth should be (7) } elaborate{ new RegForcedWidthTester } } -- cgit v1.2.3 From e1e7c7ea3359df1351ba979287b62458e411e846 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Mon, 8 Aug 2016 16:54:05 -0700 Subject: Provide public SignalID trait to be used to conjure up a signal identifier. --- .../src/main/scala/chisel3/core/Module.scala | 3 +++ .../src/main/scala/chisel3/internal/Builder.scala | 21 ++++++++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/Module.scala b/chiselFrontend/src/main/scala/chisel3/core/Module.scala index 5af744c4..4f25515b 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Module.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Module.scala @@ -63,6 +63,9 @@ extends HasId { /** Legalized name of this module. */ final val name = Builder.globalNamespace.name(desiredName) + /** Signal name (for simulation). */ + override def signalName(component: Component) = name + /** IO for this Module. At the Scala level (pre-FIRRTL transformations), * connections in and out of a Module may only go through `io` elements. */ diff --git a/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala b/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala index cecbd91e..dd4b3264 100644 --- a/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala +++ b/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala @@ -55,11 +55,30 @@ private[chisel3] class IdGen { } } -private[chisel3] trait HasId { +/** Public API to Nodes. + * currently, the node's name, the full path name, and a reference to its parent. + */ +trait SignalID { + def signalName(component: Component): String + def signalPathName(component: Component, separator: String = "_"): String + def signalParent: Module +} + +private[chisel3] trait HasId extends SignalID { private[chisel3] def _onModuleClose {} // scalastyle:ignore method.name private[chisel3] val _parent = Builder.dynamicContext.currentModule _parent.foreach(_.addId(this)) + // Implementation of public methods. + override def signalParent = _parent.get + override def signalName(component: Component) = _ref.get.fullName(component) + override def signalPathName(component: Component, separator: String = "_"): String = { + _parent match { + case Some(p) => p.signalPathName(component, separator) + separator + signalName(component) + case None => signalName(component) + } + } + private[chisel3] val _id = Builder.idGen.next override def hashCode: Int = _id.toInt override def equals(that: Any): Boolean = that match { -- cgit v1.2.3 From 0744b3e5f9c0648878b97d3375cd7d88e2d0ee08 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Wed, 10 Aug 2016 17:07:31 -0700 Subject: Add component to signature. --- chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala | 3 +-- chiselFrontend/src/main/scala/chisel3/internal/Builder.scala | 9 ++++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala index 15643ac8..de64cb3d 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala @@ -374,5 +374,4 @@ class Bundle extends Aggregate(NO_DIR) { private[core] object Bundle { val keywords = List("flip", "asInput", "asOutput", "cloneType", "toBits", - "widthOption") -} + "widthOption", "signalName", "signalPathName", "signalParent", "signalComponent") diff --git a/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala b/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala index dd4b3264..21f32483 100644 --- a/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala +++ b/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala @@ -55,13 +55,15 @@ private[chisel3] class IdGen { } } -/** Public API to Nodes. - * currently, the node's name, the full path name, and a reference to its parent. +/** Public API to access Node/Signal names. + * currently, the node's name, the full path name, and references to its parent Module and component. + * These are only valid once the design has been elaborated, and should not be used during its construction. */ trait SignalID { def signalName(component: Component): String - def signalPathName(component: Component, separator: String = "_"): String + def signalPathName(component: Component, separator: String = "."): String def signalParent: Module + def signalComponent: Option[Component] } private[chisel3] trait HasId extends SignalID { @@ -78,6 +80,7 @@ private[chisel3] trait HasId extends SignalID { case None => signalName(component) } } + override def signalComponent: Option[Component] = None private[chisel3] val _id = Builder.idGen.next override def hashCode: Int = _id.toInt -- cgit v1.2.3 From f41f2533c55e506f7d5bf2ee0198de4d9a3dbea3 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Tue, 16 Aug 2016 11:59:20 -0700 Subject: Reduce rocket-chip elaboration errors. --- .../src/main/scala/chisel3/core/BiConnect.scala | 24 ++++++++++++++-- .../src/main/scala/chisel3/core/Binder.scala | 3 +- .../src/main/scala/chisel3/core/Binding.scala | 33 ++++++++++++++-------- .../src/main/scala/chisel3/core/Module.scala | 14 +++++---- .../src/main/scala/chisel3/core/MonoConnect.scala | 2 ++ .../src/main/scala/chisel3/core/Reg.scala | 4 ++- .../scala/chisel3/internal/CompileOptions.scala | 6 ++++ src/main/scala/chisel3/util/Reg.scala | 7 +++-- 8 files changed, 69 insertions(+), 24 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala b/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala index 71de50f6..b7fd65a5 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala @@ -166,8 +166,28 @@ object BiConnect { case (Some(Output), None) => issueConnectR2L(left, right) case (None, Some(Input)) => issueConnectR2L(left, right) - case (Some(Input), Some(Input)) => throw BothDriversException - case (Some(Output), Some(Output)) => throw NeitherDriverException + case (Some(Input), Some(Input)) => { + if (compileOptions.portDeterminesDirection) + (left.binding, right.binding) match { + case (PortBinding(_, _), PortBinding(_, _)) => throw BothDriversException + case (PortBinding(_, _), _) => issueConnectL2R(left, right) + case (_, PortBinding(_, _)) => issueConnectR2L(left, right) + case _ => throw BothDriversException + } else { + throw BothDriversException + } + } + case (Some(Output), Some(Output)) => { + if (compileOptions.portDeterminesDirection) + (left.binding, right.binding) match { + case (PortBinding(_, _), PortBinding(_, _)) => throw BothDriversException + case (PortBinding(_, _), _) => issueConnectR2L(left, right) + case (_, PortBinding(_, _)) => issueConnectL2R(left, right) + case _ => throw BothDriversException + } else { + throw BothDriversException + } + } case (None, None) => throw UnknownDriverException } } diff --git a/chiselFrontend/src/main/scala/chisel3/core/Binder.scala b/chiselFrontend/src/main/scala/chisel3/core/Binder.scala index c7346dce..08c0519e 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Binder.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Binder.scala @@ -58,7 +58,8 @@ case class RegBinder(enclosure: Module) extends Binder[RegBinding] { def apply(in: UnboundBinding) = RegBinding(enclosure) } +// Notice how WireBinder uses the direction of the UnboundNode case class WireBinder(enclosure: Module) extends Binder[WireBinding] { - def apply(in: UnboundBinding) = WireBinding(enclosure) + def apply(in: UnboundBinding) = WireBinding(enclosure, in.direction) } diff --git a/chiselFrontend/src/main/scala/chisel3/core/Binding.scala b/chiselFrontend/src/main/scala/chisel3/core/Binding.scala index 75a80e4f..555ba4d5 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Binding.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Binding.scala @@ -1,5 +1,7 @@ package chisel3.core +import chisel3.internal.Builder.compileOptions + /** * The purpose of a Binding is to indicate what type of hardware 'entity' a * specific Data's leaf Elements is actually bound to. All Data starts as being @@ -88,6 +90,8 @@ object Binding { case unbound @ UnboundBinding(_) => { element.binding = binder(unbound) } + // If autoIOWrap is enabled and we're rebinding a PortBinding, just ignore the rebinding. + case portBound @ PortBinding(_, _) if (compileOptions.autoIOWrap && binder.isInstanceOf[PortBinder]) => case binding => throw AlreadyBoundException(binding.toString) } ) @@ -113,15 +117,24 @@ object Binding { // Excepts if any root element is unbound and thus not on the hardware graph def checkSynthesizable(target: Data, error_prelude: String): Unit = { - // This is called is we support autoIOWrap - def elementOfIO(element: Data): Boolean = { + // This is called if we support autoIOWrap + def elementOfIO(element: Element): Boolean = { element._parent match { case None => false case Some(x: Module) => { - // io.flatten eliminates Clock elements, so we need to use io.allElements - val ports = x.io.allElements - val isIOElement = ports.contains(element) || element == x.clock || element == x.reset - isIOElement + // Have we defined the IO ports for this module? If not, do so now. + if (!x.ioDefined) { + x.computePorts + element.binding match { + case SynthesizableBinding() => true + case _ => false + } + } else { + // io.flatten eliminates Clock elements, so we need to use io.allElements + val ports = x.io.allElements + val isIOElement = ports.contains(element) || element == x.clock || element == x.reset + isIOElement + } } } } @@ -132,7 +145,7 @@ object Binding { case binding => // The following kludge is an attempt to provide backward compatibility // It should be done at at higher level. - if (!(autoIOWrap && elementOfIO(element))) + if (!(compileOptions.autoIOWrap && elementOfIO(element))) throw NotSynthesizableException else Binding.bind(element, PortBinder(element._parent.get), "Error: IO") @@ -142,8 +155,6 @@ object Binding { case BindingException(message) => throw BindingException(s"$error_prelude$message") } } - // This should be configure by options in Driver. - private[chisel3] var autoIOWrap = true } // Location refers to 'where' in the Module hierarchy this lives @@ -196,5 +207,5 @@ case class PortBinding(enclosure: Module, direction: Option[Direction]) case class RegBinding(enclosure: Module) extends SynthesizableBinding with ConstrainedBinding with UndirectionedBinding -case class WireBinding(enclosure: Module) - extends SynthesizableBinding with ConstrainedBinding with UndirectionedBinding +case class WireBinding(enclosure: Module, direction: Option[Direction]) + extends SynthesizableBinding with ConstrainedBinding diff --git a/chiselFrontend/src/main/scala/chisel3/core/Module.scala b/chiselFrontend/src/main/scala/chisel3/core/Module.scala index bbed4d9f..450f5b58 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Module.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Module.scala @@ -4,13 +4,11 @@ package chisel3.core import scala.collection.mutable.ArrayBuffer import scala.language.experimental.macros - import chisel3.internal._ -import chisel3.internal.Builder.pushCommand -import chisel3.internal.Builder.dynamicContext +import chisel3.internal.Builder._ import chisel3.internal.firrtl._ -import chisel3.internal.firrtl.{Command, Component, DefInstance, DefInvalid, ModuleIO} -import chisel3.internal.sourceinfo.{SourceInfo, InstTransform, UnlocatableSourceInfo} +import chisel3.internal.firrtl.{Command => _, _} +import chisel3.internal.sourceinfo.{InstTransform, SourceInfo, UnlocatableSourceInfo} object Module { /** A wrapper method that all Module instantiations must be wrapped in @@ -65,7 +63,7 @@ extends HasId { iodef } - private[this] var ioDefined: Boolean = false + private[core] var ioDefined: Boolean = false /** * This must wrap the datatype used to set the io field of any Module. @@ -115,6 +113,10 @@ extends HasId { private[core] def computePorts: Seq[firrtl.Port] = for((name, port) <- ports) yield { + // If we're auto-wrapping IO definitions, do so now. + if (compileOptions.autoIOWrap && name == "io" && !ioDefined) { + IO(port) + } // Port definitions need to know input or output at top-level. // By FIRRTL semantics, 'flipped' becomes an Input val direction = if(Data.isFlipped(port)) Direction.Input else Direction.Output diff --git a/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala b/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala index bf8e7e28..e0c95e80 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala @@ -118,6 +118,7 @@ object MonoConnect { // CURRENT MOD CURRENT MOD case (Some(Output), _) => issueConnect(sink, source) case (None, _) => issueConnect(sink, source) + case (_, None) if (compileOptions.internalConnectionToInputOk) => issueConnect(sink, source) case (Some(Input), _) => throw UnwritableSinkException } } @@ -134,6 +135,7 @@ object MonoConnect { case (Some(Output), Some(Output)) => issueConnect(sink, source) case (Some(Output), Some(Input)) => issueConnect(sink, source) case (_, None) => throw UnreadableSourceException + case (Some(Input), Some(Output)) if (compileOptions.tryConnectionsSwapped) => issueConnect(source, sink) case (Some(Input), _) => throw UnwritableSinkException } } diff --git a/chiselFrontend/src/main/scala/chisel3/core/Reg.scala b/chiselFrontend/src/main/scala/chisel3/core/Reg.scala index f5706833..6c357461 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Reg.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Reg.scala @@ -10,7 +10,9 @@ import chisel3.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) { - Binding.checkUnbound(t, s"t ($t) must be unbound Type. Try using cloneType?") + if (Builder.compileOptions.regTypeMustBeUnbound) { + Binding.checkUnbound(t, s"t ($t) must be unbound Type. Try using cloneType?") + } t.chiselCloneType } else if (next ne null) { next.cloneTypeWidth(Width()) diff --git a/chiselFrontend/src/main/scala/chisel3/internal/CompileOptions.scala b/chiselFrontend/src/main/scala/chisel3/internal/CompileOptions.scala index 12789855..b809b8fe 100644 --- a/chiselFrontend/src/main/scala/chisel3/internal/CompileOptions.scala +++ b/chiselFrontend/src/main/scala/chisel3/internal/CompileOptions.scala @@ -9,8 +9,14 @@ package chisel3.internal class CompileOptions(optionsMap: Map[String, String]) { // The default for settings related to "strictness". val strictDefault: String = optionsMap.getOrElse("strict", "false") + val looseDefault: String = (!(strictDefault.toBoolean)).toString // Should Bundle connections require a strict match of fields. // If true and the same fields aren't present in both source and sink, a MissingFieldException, // MissingLeftFieldException, or MissingRightFieldException will be thrown. val connectFieldsMustMatch: Boolean = optionsMap.getOrElse("connectFieldsMustMatch", strictDefault).toBoolean + val regTypeMustBeUnbound: Boolean = optionsMap.getOrElse("regTypeMustBeUnbound", strictDefault).toBoolean + val autoIOWrap: Boolean = optionsMap.getOrElse("autoIOWrap", looseDefault).toBoolean + val portDeterminesDirection: Boolean = optionsMap.getOrElse("portDeterminesDirection", looseDefault).toBoolean + val internalConnectionToInputOk: Boolean = optionsMap.getOrElse("internalConnectionToInputOk", looseDefault).toBoolean + val tryConnectionsSwapped: Boolean = optionsMap.getOrElse("tryConnectionsSwapped", looseDefault).toBoolean } diff --git a/src/main/scala/chisel3/util/Reg.scala b/src/main/scala/chisel3/util/Reg.scala index f77a9667..37c28b14 100644 --- a/src/main/scala/chisel3/util/Reg.scala +++ b/src/main/scala/chisel3/util/Reg.scala @@ -25,13 +25,14 @@ object RegInit { object RegEnable { def apply[T <: Data](updateData: T, enable: Bool): T = { - val r = Reg(updateData) - when (enable) { r := updateData.chiselCloneType } + val clonedUpdateData = updateData.chiselCloneType + val r = Reg(clonedUpdateData) + when (enable) { r := updateData } r } def apply[T <: Data](updateData: T, resetData: T, enable: Bool): T = { val r = RegInit(resetData) - when (enable) { r := updateData.chiselCloneType } + when (enable) { r := updateData } r } } -- cgit v1.2.3 From 7922f8d4998dd902ee18a6e85e4a404a1f29eb3f Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Wed, 17 Aug 2016 13:30:05 -0700 Subject: Rocket-chip updates. Assume LHSItOutput if neither side is driving. Restore Wire()'s removal of direction in binding. --- chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala | 8 +++++++- chiselFrontend/src/main/scala/chisel3/core/Binder.scala | 3 +-- chiselFrontend/src/main/scala/chisel3/core/Binding.scala | 4 ++-- .../src/main/scala/chisel3/internal/CompileOptions.scala | 1 + 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala b/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala index b7fd65a5..c40b85ad 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala @@ -188,7 +188,13 @@ object BiConnect { throw BothDriversException } } - case (None, None) => throw UnknownDriverException + case (None, None) => { + if (compileOptions.assumeLHSIsOutput) { + issueConnectR2L(left, right) + } else { + throw UnknownDriverException + } + } } } diff --git a/chiselFrontend/src/main/scala/chisel3/core/Binder.scala b/chiselFrontend/src/main/scala/chisel3/core/Binder.scala index 08c0519e..c7346dce 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Binder.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Binder.scala @@ -58,8 +58,7 @@ case class RegBinder(enclosure: Module) extends Binder[RegBinding] { def apply(in: UnboundBinding) = RegBinding(enclosure) } -// Notice how WireBinder uses the direction of the UnboundNode case class WireBinder(enclosure: Module) extends Binder[WireBinding] { - def apply(in: UnboundBinding) = WireBinding(enclosure, in.direction) + def apply(in: UnboundBinding) = WireBinding(enclosure) } diff --git a/chiselFrontend/src/main/scala/chisel3/core/Binding.scala b/chiselFrontend/src/main/scala/chisel3/core/Binding.scala index 555ba4d5..da678fed 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Binding.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Binding.scala @@ -207,5 +207,5 @@ case class PortBinding(enclosure: Module, direction: Option[Direction]) case class RegBinding(enclosure: Module) extends SynthesizableBinding with ConstrainedBinding with UndirectionedBinding -case class WireBinding(enclosure: Module, direction: Option[Direction]) - extends SynthesizableBinding with ConstrainedBinding +case class WireBinding(enclosure: Module) + extends SynthesizableBinding with ConstrainedBinding with UndirectionedBinding diff --git a/chiselFrontend/src/main/scala/chisel3/internal/CompileOptions.scala b/chiselFrontend/src/main/scala/chisel3/internal/CompileOptions.scala index b809b8fe..93879950 100644 --- a/chiselFrontend/src/main/scala/chisel3/internal/CompileOptions.scala +++ b/chiselFrontend/src/main/scala/chisel3/internal/CompileOptions.scala @@ -19,4 +19,5 @@ class CompileOptions(optionsMap: Map[String, String]) { val portDeterminesDirection: Boolean = optionsMap.getOrElse("portDeterminesDirection", looseDefault).toBoolean val internalConnectionToInputOk: Boolean = optionsMap.getOrElse("internalConnectionToInputOk", looseDefault).toBoolean val tryConnectionsSwapped: Boolean = optionsMap.getOrElse("tryConnectionsSwapped", looseDefault).toBoolean + val assumeLHSIsOutput: Boolean = optionsMap.getOrElse("assumeLHSIsOutput", looseDefault).toBoolean } -- cgit v1.2.3 From bd6e69c19aef76b6e87f7e328e03d1b93f8a1472 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Thu, 18 Aug 2016 13:42:24 -0700 Subject: Use isFirrtlFlipped() to determine port direction. --- chiselFrontend/src/main/scala/chisel3/core/Module.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/Module.scala b/chiselFrontend/src/main/scala/chisel3/core/Module.scala index 450f5b58..24dabcbe 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Module.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Module.scala @@ -119,7 +119,7 @@ extends HasId { } // Port definitions need to know input or output at top-level. // By FIRRTL semantics, 'flipped' becomes an Input - val direction = if(Data.isFlipped(port)) Direction.Input else Direction.Output + val direction = if(Data.isFirrtlFlipped(port)) Direction.Input else Direction.Output firrtl.Port(port, direction) } -- cgit v1.2.3 From 471a9e2d15d4c968fc6eca9a86c232c6c9c9322d Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Thu, 18 Aug 2016 15:26:39 -0700 Subject: Add assumeNoDirectionIsOutput. --- .../src/main/scala/chisel3/core/MonoConnect.scala | 16 ++++++++++++++-- .../src/main/scala/chisel3/internal/CompileOptions.scala | 1 + 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala b/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala index 4ba921fa..74373e22 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala @@ -133,7 +133,13 @@ object MonoConnect { case (None, Some(Input)) => issueConnect(sink, source) case (Some(Output), Some(Output)) => issueConnect(sink, source) case (Some(Output), Some(Input)) => issueConnect(sink, source) - case (_, None) => throw UnreadableSourceException + case (_, None) => { + if (compileOptions.assumeNoDirectionIsOutput) { + issueConnect(sink, source) + } else { + throw UnreadableSourceException + } + } case (Some(Input), Some(Output)) if (compileOptions.tryConnectionsSwapped) => issueConnect(source, sink) case (Some(Input), _) => throw UnwritableSinkException } @@ -165,7 +171,13 @@ object MonoConnect { case (Some(Input), Some(Input)) => issueConnect(sink, source) case (Some(Input), Some(Output)) => issueConnect(sink, source) case (Some(Output), _) => throw UnwritableSinkException - case (_, None) => throw UnreadableSourceException + case (_, None) => { + if (compileOptions.assumeNoDirectionIsOutput) { + issueConnect(sink, source) + } else { + throw UnreadableSourceException + } + } case (None, _) => throw UnwritableSinkException } } diff --git a/chiselFrontend/src/main/scala/chisel3/internal/CompileOptions.scala b/chiselFrontend/src/main/scala/chisel3/internal/CompileOptions.scala index e040201b..912184fb 100644 --- a/chiselFrontend/src/main/scala/chisel3/internal/CompileOptions.scala +++ b/chiselFrontend/src/main/scala/chisel3/internal/CompileOptions.scala @@ -19,4 +19,5 @@ class CompileOptions(optionsMap: Map[String, String]) { val portDeterminesDirection: Boolean = optionsMap.getOrElse("portDeterminesDirection", looseDefault).toBoolean val tryConnectionsSwapped: Boolean = optionsMap.getOrElse("tryConnectionsSwapped", looseDefault).toBoolean val assumeLHSIsOutput: Boolean = optionsMap.getOrElse("assumeLHSIsOutput", looseDefault).toBoolean + val assumeNoDirectionIsOutput: Boolean = optionsMap.getOrElse("assumeNoDirectionIsOutput", looseDefault).toBoolean } -- cgit v1.2.3 From 119e6c7bb9096bbd163a439de09d4932303d0140 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Fri, 19 Aug 2016 12:02:10 -0700 Subject: Simplify autioIOWrap code in computePorts(). As a side-effect, handle BlackBoxes correctly. --- chiselFrontend/src/main/scala/chisel3/core/Module.scala | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/Module.scala b/chiselFrontend/src/main/scala/chisel3/core/Module.scala index 24dabcbe..19063664 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Module.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Module.scala @@ -111,17 +111,18 @@ extends HasId { ("clk", clock), ("reset", reset), ("io", io) ) - private[core] def computePorts: Seq[firrtl.Port] = - for((name, port) <- ports) yield { - // If we're auto-wrapping IO definitions, do so now. - if (compileOptions.autoIOWrap && name == "io" && !ioDefined) { - IO(port) - } + private[core] def computePorts: Seq[firrtl.Port] = { + // If we're auto-wrapping IO definitions, do so now. + if (compileOptions.autoIOWrap && !ioDefined) { + IO(io) + } + for ((name, port) <- ports) yield { // Port definitions need to know input or output at top-level. // By FIRRTL semantics, 'flipped' becomes an Input val direction = if(Data.isFirrtlFlipped(port)) Direction.Input else Direction.Output firrtl.Port(port, direction) } + } private[core] def setupInParent(implicit sourceInfo: SourceInfo): this.type = { _parent match { -- cgit v1.2.3 From 525e5688f69f474240fe5a21d6210beb04cfef29 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Fri, 19 Aug 2016 14:46:53 -0700 Subject: Restore immutability of direction overrides. Input, Output, and Flipped clone their inputs. --- chiselFrontend/src/main/scala/chisel3/core/Data.scala | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/Data.scala b/chiselFrontend/src/main/scala/chisel3/core/Data.scala index cb6d427d..ce7b58b4 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Data.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Data.scala @@ -31,27 +31,28 @@ object DataMirror { /** * Input, Output, and Flipped are used to define the directions of Module IOs. * -* Note that they do not currently call target to be a newType or cloneType. -* This is nominally for performance reasons to avoid too many extra copies when -* something is flipped multiple times. +* Note that they currently clone their source argument, including its bindings. * * Thus, an error will be thrown if these are used on bound Data */ object Input { - def apply[T<:Data](target: T): T = { + def apply[T<:Data](source: T): T = { + val target = source.chiselCloneType Data.setFirrtlDirection(target, Direction.Input) Binding.bind(target, InputBinder, "Error: Cannot set as input ") } } object Output { - def apply[T<:Data](target: T): T = { + def apply[T<:Data](source: T): T = { + val target = source.chiselCloneType Data.setFirrtlDirection(target, Direction.Output) Binding.bind(target, OutputBinder, "Error: Cannot set as output ") } } object Flipped { - def apply[T<:Data](target: T): T = { - Data.setFirrtlDirection(target, Data.getFirrtlDirection(target).flip) + def apply[T<:Data](source: T): T = { + val target = source.chiselCloneType + Data.setFirrtlDirection(target, Data.getFirrtlDirection(source).flip) Binding.bind(target, FlippedBinder, "Error: Cannot flip ") } } -- cgit v1.2.3 From 2d01fdf6f26f480cb7ed19c1365f181ea717ddc2 Mon Sep 17 00:00:00 2001 From: Donggyu Kim Date: Mon, 15 Aug 2016 18:03:12 -0700 Subject: provides signal name methods for firrtl annotation and chisel testers * signalName: returns the chirrtl name of the signal * pathName: returns the full path name of the signal from the top module * parentPathName: returns the full path of the signal's parent module instance from the top module * parentModName: returns the signal's parent **module(not instance)** name. --- .../src/main/scala/chisel3/core/Aggregate.scala | 3 +- .../src/main/scala/chisel3/core/Module.scala | 22 ++++++++++- .../src/main/scala/chisel3/internal/Builder.scala | 44 +++++++++++++--------- src/main/scala/chisel3/Driver.scala | 2 + .../scala/chisel3/internal/firrtl/Emitter.scala | 16 ++------ 5 files changed, 54 insertions(+), 33 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala index de64cb3d..82c6097f 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala @@ -374,4 +374,5 @@ class Bundle extends Aggregate(NO_DIR) { private[core] object Bundle { val keywords = List("flip", "asInput", "asOutput", "cloneType", "toBits", - "widthOption", "signalName", "signalPathName", "signalParent", "signalComponent") + "widthOption", "signalName", "signalPathName", "signalParent", "signalComponent") +} diff --git a/chiselFrontend/src/main/scala/chisel3/core/Module.scala b/chiselFrontend/src/main/scala/chisel3/core/Module.scala index 4f25515b..eb48a14d 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Module.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Module.scala @@ -31,7 +31,9 @@ object Module { 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) + val component = Component(m, m.name, ports, m._commands) + m._component = Some(component) + Builder.components += component pushCommand(DefInstance(sourceInfo, m, ports)) m.setupInParent(childSourceInfo) } @@ -63,8 +65,24 @@ extends HasId { /** Legalized name of this module. */ final val name = Builder.globalNamespace.name(desiredName) + /** FIRRTL Module name */ + private var _modName: Option[String] = None + private[chisel3] def setModName(name: String) = _modName = Some(name) + def modName = _modName match { + case Some(name) => name + case None => throwException("modName should be called after circuit elaboration") + } + + /** Keep component for signal names */ + private[chisel3] var _component: Option[Component] = None + + /** Signal name (for simulation). */ - override def signalName(component: Component) = name + override def signalName = + if (_parent == None) name else _component match { + case None => getRef.name + case Some(c) => getRef fullName c + } /** IO for this Module. At the Scala level (pre-FIRRTL transformations), * connections in and out of a Module may only go through `io` elements. diff --git a/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala b/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala index 21f32483..bf78c410 100644 --- a/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala +++ b/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala @@ -59,29 +59,18 @@ private[chisel3] class IdGen { * currently, the node's name, the full path name, and references to its parent Module and component. * These are only valid once the design has been elaborated, and should not be used during its construction. */ -trait SignalID { - def signalName(component: Component): String - def signalPathName(component: Component, separator: String = "."): String - def signalParent: Module - def signalComponent: Option[Component] +trait SignalId { + def signalName: String + def pathName: String + def parentPathName: String + def parentModName: String } -private[chisel3] trait HasId extends SignalID { +private[chisel3] trait HasId extends SignalId { private[chisel3] def _onModuleClose {} // scalastyle:ignore method.name private[chisel3] val _parent = Builder.dynamicContext.currentModule _parent.foreach(_.addId(this)) - // Implementation of public methods. - override def signalParent = _parent.get - override def signalName(component: Component) = _ref.get.fullName(component) - override def signalPathName(component: Component, separator: String = "_"): String = { - _parent match { - case Some(p) => p.signalPathName(component, separator) + separator + signalName(component) - case None => signalName(component) - } - } - override def signalComponent: Option[Component] = None - private[chisel3] val _id = Builder.idGen.next override def hashCode: Int = _id.toInt override def equals(that: Any): Boolean = that match { @@ -117,6 +106,27 @@ private[chisel3] trait HasId extends SignalID { 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 + + // Implementation of public methods. + def signalName = _parent match { + case Some(p) => p._component match { + case Some(c) => getRef fullName c + case None => throwException("signalName/pathName should be called after circuit elaboration") + } + case None => throwException("this cannot happen") + } + def pathName = _parent match { + case None => signalName + case Some(p) => s"${p.pathName}.$signalName" + } + def parentPathName = _parent match { + case Some(p) => p.pathName + case None => throwException(s"$signalName doesn't have a parent") + } + def parentModName = _parent match { + case Some(p) => p.modName + case None => throwException(s"$signalName doesn't have a parent") + } } private[chisel3] class DynamicContext { diff --git a/src/main/scala/chisel3/Driver.scala b/src/main/scala/chisel3/Driver.scala index 0979314f..5aeeef99 100644 --- a/src/main/scala/chisel3/Driver.scala +++ b/src/main/scala/chisel3/Driver.scala @@ -112,6 +112,8 @@ object Driver extends BackendCompilationUtilities { def emit[T <: Module](gen: () => T): String = Emitter.emit(elaborate(gen)) + def emit[T <: Module](ir: Circuit): String = Emitter.emit(ir) + def dumpFirrtl(ir: Circuit, optName: Option[File]): File = { val f = optName.getOrElse(new File(ir.name + ".fir")) val w = new FileWriter(f) diff --git a/src/main/scala/chisel3/internal/firrtl/Emitter.scala b/src/main/scala/chisel3/internal/firrtl/Emitter.scala index 31856541..79f86ae9 100644 --- a/src/main/scala/chisel3/internal/firrtl/Emitter.scala +++ b/src/main/scala/chisel3/internal/firrtl/Emitter.scala @@ -27,11 +27,7 @@ private class Emitter(circuit: Circuit) { 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 e: DefInstance => s"inst ${e.name} of ${e.id.modName}" case w: WhenBegin => indent() s"when ${w.pred.fullName(ctx)} :" @@ -47,8 +43,6 @@ private class Emitter(circuit: Circuit) { // Map of Module FIRRTL definition to FIRRTL name, if it has been emitted already. private val defnMap = collection.mutable.HashMap[(String, String), Component]() - // Map of Component name to FIRRTL id. - private val moduleMap = collection.mutable.HashMap[String, String]() /** Generates the FIRRTL module declaration. */ @@ -89,15 +83,11 @@ private class Emitter(circuit: Circuit) { defnMap get (m.id.desiredName, defn) match { case Some(duplicate) => - moduleMap(m.name) = duplicate.name + m.id setModName duplicate.name "" case None => - require(!(moduleMap contains m.name), - "emitting module with same name but different contents") - - moduleMap(m.name) = m.name defnMap((m.id.desiredName, defn)) = m - + m.id setModName m.id.name moduleDecl(m) + defn } } -- cgit v1.2.3 From bc4f64020b8115d04af00e92bf9a7c68d9b35443 Mon Sep 17 00:00:00 2001 From: chick Date: Wed, 17 Aug 2016 16:12:33 -0700 Subject: Add annotating example to test new signal name api --- src/test/scala/chiselTests/AnnotatingExample.scala | 115 +++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 src/test/scala/chiselTests/AnnotatingExample.scala diff --git a/src/test/scala/chiselTests/AnnotatingExample.scala b/src/test/scala/chiselTests/AnnotatingExample.scala new file mode 100644 index 00000000..dc0d0421 --- /dev/null +++ b/src/test/scala/chiselTests/AnnotatingExample.scala @@ -0,0 +1,115 @@ +// See LICENSE for license details. + +package chiselTests + +import chisel3._ +import chisel3.core.Module +import chisel3.internal.Builder +import chisel3.internal.firrtl.{Emitter, Circuit} +import chisel3.testers.BasicTester +import org.scalatest._ +import org.scalatest.prop._ + +import scala.util.DynamicVariable + +class SomeSubMod extends Module { + val io = new Bundle { + val in = UInt(INPUT, 16) + val out = SInt(OUTPUT, 32) + } + MyBuilder.myDynamicContext.annotationMap(AnnotationKey(io.in, AllRefs)) = "sub mod io.in" + MyBuilder.myDynamicContext.annotationMap(AnnotationKey(io.out, JustThisRef)) = "sub mod io.out" +} + +class AnnotatingExample extends Module { + val io = new Bundle { + val a = UInt(INPUT, 32) + val b = UInt(INPUT, 32) + val e = Bool(INPUT) + val z = UInt(OUTPUT, 32) + val v = Bool(OUTPUT) + val bun = new Bundle { + val nested_1 = UInt(INPUT, 12) + val nested_2 = Bool(OUTPUT) + } + } + val x = Reg(UInt(width = 32)) + val y = Reg(UInt(width = 32)) + + val subModule1 = Module(new SomeSubMod) + val subModule2 = Module(new SomeSubMod) + + + val annotate = MyBuilder.myDynamicContext.annotationMap + + annotate(AnnotationKey(x, JustThisRef)) = "I am register X" + annotate(AnnotationKey(io.a, JustThisRef)) = "I am io.a" + annotate(AnnotationKey(io.bun.nested_1, JustThisRef)) = "I am io.bun.nested_1" + annotate(AnnotationKey(io.bun.nested_2, JustThisRef)) = "I am io.bun.nested_2" + + when (x > y) { x := x -% y } + .otherwise { y := y -% x } + when (io.e) { x := io.a; y := io.b } + io.z := x + io.v := y === UInt(0) +} + +class AnnotatingExampleTester(a: Int, b: Int, z: Int) extends BasicTester { + val dut = Module(new AnnotatingExample) + val first = Reg(init=Bool(true)) + dut.io.a := UInt(a) + dut.io.b := UInt(b) + dut.io.e := first + when(first) { first := Bool(false) } + when(!first && dut.io.v) { + assert(dut.io.z === UInt(z)) + stop() + } +} + +class AnnotatingExampleSpec extends ChiselPropSpec { + + property("show node info") { + MyDriver.doStuff { () => new AnnotatingExampleTester(1, 2, 3) } + } + +} + +trait AnnotationScope +case object Default extends AnnotationScope +case object AllRefs extends AnnotationScope +case object JustThisRef extends AnnotationScope + +case class AnnotationKey(val component: Data, scope: AnnotationScope) + +class MyDynamicContext { + val annotationMap = new scala.collection.mutable.HashMap[AnnotationKey, String] +} + +object MyBuilder { + private val myDynamicContextVar = new DynamicVariable[Option[MyDynamicContext]](None) + + def myDynamicContext: MyDynamicContext = + myDynamicContextVar.value getOrElse (new MyDynamicContext) + + def build[T <: Module](f: => T): Unit = { + myDynamicContextVar.withValue(Some(new MyDynamicContext)) { + Driver.emit(() => f) + val list = myDynamicContextVar.value.get.annotationMap.map { case (k,v) => + k match { + case (AnnotationKey(signal, JustThisRef)) => + f"Just this ref ${signal.pathName + signal.signalName}%60s -> $v%30s component $signal" + case (AnnotationKey(signal, AllRefs)) => + f"All refs ${signal.signalName}%60s -> $v%30s component $signal" + case _ => + s"Unknown annotation key $k" + } + }.toList.sorted + println(list.mkString("\n")) + } + } +} + +object MyDriver extends BackendCompilationUtilities { + def doStuff[T <: Module](gen: () => T): Unit = MyBuilder.build(Module(gen())) +} \ No newline at end of file -- cgit v1.2.3 From 3f771ee67b9f8fa0d92ce00af1ea062c5a2605b2 Mon Sep 17 00:00:00 2001 From: chick Date: Thu, 18 Aug 2016 13:03:16 -0700 Subject: Add AnnotationSpec file which provides an example of a way to implement generation of annotations in a chisel circuit that could be used by custom firrtl passes This spec also shows and tests in a limited way the new API of .signalName, .pathName, parentModName which allows access to the various path information of a chisel component (something that subclasses SignalId, most prominently SubClasses of Data and Module --- src/test/scala/chiselTests/AnnotatingExample.scala | 102 +++++++++++++++------ 1 file changed, 72 insertions(+), 30 deletions(-) diff --git a/src/test/scala/chiselTests/AnnotatingExample.scala b/src/test/scala/chiselTests/AnnotatingExample.scala index dc0d0421..073355fc 100644 --- a/src/test/scala/chiselTests/AnnotatingExample.scala +++ b/src/test/scala/chiselTests/AnnotatingExample.scala @@ -4,20 +4,31 @@ package chiselTests import chisel3._ import chisel3.core.Module -import chisel3.internal.Builder -import chisel3.internal.firrtl.{Emitter, Circuit} +import chisel3.internal.SignalId import chisel3.testers.BasicTester import org.scalatest._ -import org.scalatest.prop._ import scala.util.DynamicVariable -class SomeSubMod extends Module { +//scalastyle:off magic.number + +/** + * This Spec file illustrates use of Donggyu's component name API, it currently only + * uses three methods .signalName, .parentModName and .pathName + * + * This is also an illustration of how to implement an annotation system in chisel3 + * A local (my) Driver and Builder are created to provide thread-local access to + * an annotation map, and then a post elaboration annotation processor can resolve + * the keys and could serialize the annotations to a file for use by firrtl passes + */ + +class SomeSubMod(param1: Int, param2: Int) extends Module { val io = new Bundle { val in = UInt(INPUT, 16) val out = SInt(OUTPUT, 32) } - MyBuilder.myDynamicContext.annotationMap(AnnotationKey(io.in, AllRefs)) = "sub mod io.in" + MyBuilder.myDynamicContext.annotationMap(AnnotationKey(this, JustThisRef)) = s"SomeSubMod($param1, $param2)" + MyBuilder.myDynamicContext.annotationMap(AnnotationKey(io.in, AllRefs)) = "sub mod io.in" MyBuilder.myDynamicContext.annotationMap(AnnotationKey(io.out, JustThisRef)) = "sub mod io.out" } @@ -36,15 +47,17 @@ class AnnotatingExample extends Module { val x = Reg(UInt(width = 32)) val y = Reg(UInt(width = 32)) - val subModule1 = Module(new SomeSubMod) - val subModule2 = Module(new SomeSubMod) + val subModule1 = Module(new SomeSubMod(1, 2)) + val subModule2 = Module(new SomeSubMod(3, 4)) val annotate = MyBuilder.myDynamicContext.annotationMap + annotate(AnnotationKey(subModule2, AllRefs)) = s"SomeSubMod was used" + annotate(AnnotationKey(x, JustThisRef)) = "I am register X" annotate(AnnotationKey(io.a, JustThisRef)) = "I am io.a" - annotate(AnnotationKey(io.bun.nested_1, JustThisRef)) = "I am io.bun.nested_1" + annotate(AnnotationKey(io.bun.nested_1, AllRefs)) = "I am io.bun.nested_1" annotate(AnnotationKey(io.bun.nested_2, JustThisRef)) = "I am io.bun.nested_2" when (x > y) { x := x -% y } @@ -67,49 +80,78 @@ class AnnotatingExampleTester(a: Int, b: Int, z: Int) extends BasicTester { } } -class AnnotatingExampleSpec extends ChiselPropSpec { +class AnnotatingExampleSpec extends FlatSpec with Matchers { + behavior of "Annotating components of a circuit" - property("show node info") { - MyDriver.doStuff { () => new AnnotatingExampleTester(1, 2, 3) } + val annotationMap = MyDriver.doStuff { () => new AnnotatingExampleTester(1, 2, 3) } + it should "contain the following relative keys" in { + annotationMap.contains("SomeSubMod.io.in") should be(true) + annotationMap("SomeSubMod.io.in") should be("sub mod io.in") + } + it should "contain the following absolute keys" in { + annotationMap.contains("AnnotatingExampleTester.dut.subModule2.io.out") should be (true) + annotationMap("AnnotatingExampleTester.dut.subModule2.io.out") should be ("sub mod io.out") } - } trait AnnotationScope -case object Default extends AnnotationScope -case object AllRefs extends AnnotationScope +case object AllRefs extends AnnotationScope case object JustThisRef extends AnnotationScope -case class AnnotationKey(val component: Data, scope: AnnotationScope) +object AnnotationKey { + def apply(component: SignalId): AnnotationKey = { + AnnotationKey(component, AllRefs) + } +} +case class AnnotationKey(val component: SignalId, scope: AnnotationScope) { + override def toString: String = { + scope match { + case JustThisRef => + s"${component.pathName}" + case AllRefs => + s"${component.parentModName}.${component.signalName}" + case _ => + s"${component.toString}_unknown_scope" + } + } +} + +class AnnotationMap extends scala.collection.mutable.HashMap[AnnotationKey, String] class MyDynamicContext { - val annotationMap = new scala.collection.mutable.HashMap[AnnotationKey, String] + val annotationMap = new AnnotationMap } object MyBuilder { private val myDynamicContextVar = new DynamicVariable[Option[MyDynamicContext]](None) def myDynamicContext: MyDynamicContext = - myDynamicContextVar.value getOrElse (new MyDynamicContext) + myDynamicContextVar.value getOrElse new MyDynamicContext + + def processAnnotations(annotationMap: AnnotationMap): Map[String, String] = { + val list = annotationMap.map { case (k,v) => + k match { + case (AnnotationKey(signal, JustThisRef)) => + f"Just this ref $k%60s -> $v%40s component $signal" + case (AnnotationKey(signal, AllRefs)) => + f"All refs $k%60s -> $v%40s component $signal" + case _ => + s"Unknown annotation key $k" + } + }.toList.sorted.mkString("\n") + println(s"Sorted list of annotations\n$list") + + annotationMap.map { case (k,v) => k.toString -> v}.toMap + } - def build[T <: Module](f: => T): Unit = { + def build[T <: Module](f: => T): Map[String, String] = { myDynamicContextVar.withValue(Some(new MyDynamicContext)) { Driver.emit(() => f) - val list = myDynamicContextVar.value.get.annotationMap.map { case (k,v) => - k match { - case (AnnotationKey(signal, JustThisRef)) => - f"Just this ref ${signal.pathName + signal.signalName}%60s -> $v%30s component $signal" - case (AnnotationKey(signal, AllRefs)) => - f"All refs ${signal.signalName}%60s -> $v%30s component $signal" - case _ => - s"Unknown annotation key $k" - } - }.toList.sorted - println(list.mkString("\n")) + processAnnotations(myDynamicContextVar.value.get.annotationMap) } } } object MyDriver extends BackendCompilationUtilities { - def doStuff[T <: Module](gen: () => T): Unit = MyBuilder.build(Module(gen())) + def doStuff[T <: Module](gen: () => T): Map[String, String] = MyBuilder.build(Module(gen())) } \ No newline at end of file -- cgit v1.2.3 From a177f40f1ff2482ba268a27e0af02b57713e781a Mon Sep 17 00:00:00 2001 From: chick Date: Fri, 19 Aug 2016 12:28:35 -0700 Subject: AnnotatingExample: Removed extraneous logic Renamed doStuff to buildAnnotatedCircuit Removed println's --- src/test/scala/chiselTests/AnnotatingExample.scala | 54 +++++++++------------- 1 file changed, 21 insertions(+), 33 deletions(-) diff --git a/src/test/scala/chiselTests/AnnotatingExample.scala b/src/test/scala/chiselTests/AnnotatingExample.scala index 073355fc..a252309d 100644 --- a/src/test/scala/chiselTests/AnnotatingExample.scala +++ b/src/test/scala/chiselTests/AnnotatingExample.scala @@ -27,9 +27,11 @@ class SomeSubMod(param1: Int, param2: Int) extends Module { val in = UInt(INPUT, 16) val out = SInt(OUTPUT, 32) } - MyBuilder.myDynamicContext.annotationMap(AnnotationKey(this, JustThisRef)) = s"SomeSubMod($param1, $param2)" - MyBuilder.myDynamicContext.annotationMap(AnnotationKey(io.in, AllRefs)) = "sub mod io.in" - MyBuilder.myDynamicContext.annotationMap(AnnotationKey(io.out, JustThisRef)) = "sub mod io.out" + val annotate = MyBuilder.myDynamicContext.annotationMap + + annotate(AnnotationKey(this, JustThisRef)) = s"SomeSubMod($param1, $param2)" + annotate(AnnotationKey(io.in, AllRefs)) = "sub mod io.in" + annotate(AnnotationKey(io.out, JustThisRef)) = "sub mod io.out" } class AnnotatingExample extends Module { @@ -56,40 +58,35 @@ class AnnotatingExample extends Module { annotate(AnnotationKey(subModule2, AllRefs)) = s"SomeSubMod was used" annotate(AnnotationKey(x, JustThisRef)) = "I am register X" + annotate(AnnotationKey(y, AllRefs)) = "I am register Y" annotate(AnnotationKey(io.a, JustThisRef)) = "I am io.a" annotate(AnnotationKey(io.bun.nested_1, AllRefs)) = "I am io.bun.nested_1" annotate(AnnotationKey(io.bun.nested_2, JustThisRef)) = "I am io.bun.nested_2" - - when (x > y) { x := x -% y } - .otherwise { y := y -% x } - when (io.e) { x := io.a; y := io.b } - io.z := x - io.v := y === UInt(0) } -class AnnotatingExampleTester(a: Int, b: Int, z: Int) extends BasicTester { +class AnnotatingExampleTester extends BasicTester { val dut = Module(new AnnotatingExample) - val first = Reg(init=Bool(true)) - dut.io.a := UInt(a) - dut.io.b := UInt(b) - dut.io.e := first - when(first) { first := Bool(false) } - when(!first && dut.io.v) { - assert(dut.io.z === UInt(z)) - stop() - } + + stop() } class AnnotatingExampleSpec extends FlatSpec with Matchers { behavior of "Annotating components of a circuit" - val annotationMap = MyDriver.doStuff { () => new AnnotatingExampleTester(1, 2, 3) } it should "contain the following relative keys" in { + val annotationMap = MyDriver.buildAnnotatedCircuit { () => new AnnotatingExampleTester } + annotationMap.contains("SomeSubMod.io.in") should be(true) + annotationMap.contains("AnnotatingExample.y") should be(true) + annotationMap("SomeSubMod.io.in") should be("sub mod io.in") } it should "contain the following absolute keys" in { + val annotationMap = MyDriver.buildAnnotatedCircuit { () => new AnnotatingExampleTester } + annotationMap.contains("AnnotatingExampleTester.dut.subModule2.io.out") should be (true) + annotationMap.contains("AnnotatingExampleTester.dut.x") should be (true) + annotationMap("AnnotatingExampleTester.dut.subModule2.io.out") should be ("sub mod io.out") } } @@ -129,18 +126,6 @@ object MyBuilder { myDynamicContextVar.value getOrElse new MyDynamicContext def processAnnotations(annotationMap: AnnotationMap): Map[String, String] = { - val list = annotationMap.map { case (k,v) => - k match { - case (AnnotationKey(signal, JustThisRef)) => - f"Just this ref $k%60s -> $v%40s component $signal" - case (AnnotationKey(signal, AllRefs)) => - f"All refs $k%60s -> $v%40s component $signal" - case _ => - s"Unknown annotation key $k" - } - }.toList.sorted.mkString("\n") - println(s"Sorted list of annotations\n$list") - annotationMap.map { case (k,v) => k.toString -> v}.toMap } @@ -153,5 +138,8 @@ object MyBuilder { } object MyDriver extends BackendCompilationUtilities { - def doStuff[T <: Module](gen: () => T): Map[String, String] = MyBuilder.build(Module(gen())) + /** + * illustrates a chisel3 style driver that, annotations can only processed within this structure + */ + def buildAnnotatedCircuit[T <: Module](gen: () => T): Map[String, String] = MyBuilder.build(Module(gen())) } \ No newline at end of file -- cgit v1.2.3 From 94796f5960b5b82f9d28d2b0e0e7ec7c92e29dfa Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Mon, 22 Aug 2016 15:46:28 -0700 Subject: Fix firrtlDirection for class DeqIO. --- src/main/scala/chisel3/package.scala | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/scala/chisel3/package.scala b/src/main/scala/chisel3/package.scala index fc23f41b..93070f1d 100644 --- a/src/main/scala/chisel3/package.scala +++ b/src/main/scala/chisel3/package.scala @@ -124,6 +124,8 @@ package object chisel3 { override def cloneType: this.type = EnqIO(gen).asInstanceOf[this.type] } class DeqIO[+T <: Data](gen: T) extends DecoupledIO(gen) { + val Data = chisel3.core.Data + Data.setFirrtlDirection(this, Data.getFirrtlDirection(this).flip) Binding.bind(this, FlippedBinder, "Error: Cannot flip ") def init(): Unit = { this.nodeq() -- cgit v1.2.3 From 35c8e40b25f529da883e8ae91644fcc496e087da Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Mon, 22 Aug 2016 16:57:43 -0700 Subject: Purely cosmetic changes to placate the scalastyle checker. --- src/main/scala/chisel3/compatibility.scala | 34 ++++++++++----------- src/main/scala/chisel3/compatibility/debug.scala | 2 ++ src/main/scala/chisel3/package.scala | 38 ++++++++++++------------ src/main/scala/chisel3/util/BitPat.scala | 6 ++-- src/main/scala/chisel3/util/Decoupled.scala | 2 +- src/main/scala/chisel3/util/TransitName.scala | 4 ++- 6 files changed, 45 insertions(+), 41 deletions(-) diff --git a/src/main/scala/chisel3/compatibility.scala b/src/main/scala/chisel3/compatibility.scala index 5624b79c..35c44330 100644 --- a/src/main/scala/chisel3/compatibility.scala +++ b/src/main/scala/chisel3/compatibility.scala @@ -3,7 +3,7 @@ // Allows legacy users to continue using Chisel (capital C) package name while // moving to the more standard package naming convention chisel3 (lowercase c). -package object Chisel { +package object Chisel { // scalastyle:ignore package.object.name type Direction = chisel3.core.Direction val INPUT = chisel3.core.Direction.Input val OUTPUT = chisel3.core.Direction.Output @@ -72,29 +72,29 @@ package object Chisel { * Prefer storing the result and then extracting from it. */ implicit class fromIntToLiteral(val x: Int) extends AnyVal { - def U: UInt = UInt(BigInt(x), Width()) - def S: SInt = SInt(BigInt(x), Width()) + def U: UInt = UInt(BigInt(x), Width()) // scalastyle:ignore method.name + def S: SInt = SInt(BigInt(x), Width()) // scalastyle:ignore method.name - def asUInt() = UInt(x, Width()) - def asSInt() = SInt(x, Width()) - def asUInt(width: Int) = UInt(x, width) - def asSInt(width: Int) = SInt(x, width) + def asUInt(): UInt = UInt(x, Width()) + def asSInt(): SInt = SInt(x, Width()) + def asUInt(width: Int): UInt = UInt(x, width) + def asSInt(width: Int): SInt = SInt(x, width) } - + implicit class fromBigIntToLiteral(val x: BigInt) extends AnyVal { - def U: UInt = UInt(x, Width()) - def S: SInt = SInt(x, Width()) + def U: UInt = UInt(x, Width()) // scalastyle:ignore method.name + def S: SInt = SInt(x, Width()) // scalastyle:ignore method.name - def asUInt() = UInt(x, Width()) - def asSInt() = SInt(x, Width()) - def asUInt(width: Int) = UInt(x, width) - def asSInt(width: Int) = SInt(x, width) + def asUInt(): UInt = UInt(x, Width()) + def asSInt(): SInt = SInt(x, Width()) + def asUInt(width: Int): UInt = UInt(x, width) + def asSInt(width: Int): SInt = SInt(x, width) } implicit class fromStringToLiteral(val x: String) extends AnyVal { - def U: UInt = UInt(x) + def U: UInt = UInt(x) // scalastyle:ignore method.name } implicit class fromBooleanToLiteral(val x: Boolean) extends AnyVal { - def B: Bool = Bool(x) + def B: Bool = Bool(x) // scalastyle:ignore method.name } @@ -105,7 +105,7 @@ package object Chisel { val throwException = chisel3.compatibility.throwException val debug = chisel3.compatibility.debug - object testers { + object testers { // scalastyle:ignore object.name type BasicTester = chisel3.testers.BasicTester val TesterDriver = chisel3.testers.TesterDriver } diff --git a/src/main/scala/chisel3/compatibility/debug.scala b/src/main/scala/chisel3/compatibility/debug.scala index c3966dae..d9f6e4b0 100644 --- a/src/main/scala/chisel3/compatibility/debug.scala +++ b/src/main/scala/chisel3/compatibility/debug.scala @@ -1,3 +1,5 @@ +// See LICENSE for license details. + package chisel3.compatibility import chisel3.core._ diff --git a/src/main/scala/chisel3/package.scala b/src/main/scala/chisel3/package.scala index 93070f1d..7911cb04 100644 --- a/src/main/scala/chisel3/package.scala +++ b/src/main/scala/chisel3/package.scala @@ -1,6 +1,6 @@ // See LICENSE for license details. -package object chisel3 { +package object chisel3 { // scalastyle:ignore package.object.name import scala.language.experimental.macros import internal.firrtl.Width @@ -73,29 +73,29 @@ package object chisel3 { * Prefer storing the result and then extracting from it. */ implicit class fromIntToLiteral(val x: Int) extends AnyVal { - def U: UInt = UInt(BigInt(x), Width()) - def S: SInt = SInt(BigInt(x), Width()) + def U: UInt = UInt(BigInt(x), Width()) // scalastyle:ignore method.name + def S: SInt = SInt(BigInt(x), Width()) // scalastyle:ignore method.name - def asUInt() = UInt(x, Width()) - def asSInt() = SInt(x, Width()) - def asUInt(width: Int) = UInt(x, width) - def asSInt(width: Int) = SInt(x, width) + def asUInt(): UInt = UInt(x, Width()) + def asSInt(): SInt = SInt(x, Width()) + def asUInt(width: Int): UInt = UInt(x, width) + def asSInt(width: Int): SInt = SInt(x, width) } - + implicit class fromBigIntToLiteral(val x: BigInt) extends AnyVal { - def U: UInt = UInt(x, Width()) - def S: SInt = SInt(x, Width()) + def U: UInt = UInt(x, Width()) // scalastyle:ignore method.name + def S: SInt = SInt(x, Width()) // scalastyle:ignore method.name - def asUInt() = UInt(x, Width()) - def asSInt() = SInt(x, Width()) - def asUInt(width: Int) = UInt(x, width) - def asSInt(width: Int) = SInt(x, width) + def asUInt(): UInt = UInt(x, Width()) + def asSInt(): SInt = SInt(x, Width()) + def asUInt(width: Int): UInt = UInt(x, width) + def asSInt(width: Int): SInt = SInt(x, width) } implicit class fromStringToLiteral(val x: String) extends AnyVal { - def U: UInt = UInt(x) + def U: UInt = UInt(x) // scalastyle:ignore method.name } implicit class fromBooleanToLiteral(val x: Boolean) extends AnyVal { - def B: Bool = Bool(x) + def B: Bool = Bool(x) // scalastyle:ignore method.name } implicit class fromUIntToBitPatComparable(val x: UInt) extends AnyVal { @@ -103,9 +103,9 @@ package object chisel3 { 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 + def do_=== (that: BitPat)(implicit sourceInfo: SourceInfo): Bool = that === x // scalastyle:ignore method.name + def do_!= (that: BitPat)(implicit sourceInfo: SourceInfo): Bool = that != x // scalastyle:ignore method.name + def do_=/= (that: BitPat)(implicit sourceInfo: SourceInfo): Bool = that =/= x // scalastyle:ignore method.name } // Compatibility with existing code. diff --git a/src/main/scala/chisel3/util/BitPat.scala b/src/main/scala/chisel3/util/BitPat.scala index e79b882b..5de7a508 100644 --- a/src/main/scala/chisel3/util/BitPat.scala +++ b/src/main/scala/chisel3/util/BitPat.scala @@ -84,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 = value.asUInt === (that & mask.asUInt) - def do_=/= (that: UInt)(implicit sourceInfo: SourceInfo): Bool = !(this === that) - def do_!= (that: UInt)(implicit sourceInfo: SourceInfo): Bool = this =/= that + def do_=== (that: UInt)(implicit sourceInfo: SourceInfo): Bool = value.asUInt === (that & mask.asUInt) // scalastyle:ignore method.name + def do_=/= (that: UInt)(implicit sourceInfo: SourceInfo): Bool = !(this === that) // scalastyle:ignore method.name + def do_!= (that: UInt)(implicit sourceInfo: SourceInfo): Bool = this =/= that // scalastyle:ignore method.name } diff --git a/src/main/scala/chisel3/util/Decoupled.scala b/src/main/scala/chisel3/util/Decoupled.scala index 0d000f49..42f58ea9 100644 --- a/src/main/scala/chisel3/util/Decoupled.scala +++ b/src/main/scala/chisel3/util/Decoupled.scala @@ -103,7 +103,7 @@ class Queue[T <: Data](gen: T, val entries: Int, 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 = IO(new QueueIO(gen, entries)) val ram = Mem(entries, gen) diff --git a/src/main/scala/chisel3/util/TransitName.scala b/src/main/scala/chisel3/util/TransitName.scala index f36f926f..ce6cb60f 100644 --- a/src/main/scala/chisel3/util/TransitName.scala +++ b/src/main/scala/chisel3/util/TransitName.scala @@ -1,3 +1,5 @@ +// See LICENSE for license details. + package chisel3.util import chisel3._ @@ -16,7 +18,7 @@ object TransitName { from } def withSuffix[T<:HasId](suffix: String)(from: T, to: HasId): T = { - from.addPostnameHook((given_name: String) => {to.suggestName(given_name+suffix)}) + from.addPostnameHook((given_name: String) => {to.suggestName(given_name + suffix)}) from } } -- cgit v1.2.3 From 716de18b37c301523f8c6fb4954745aaa2a79bdb Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Tue, 23 Aug 2016 09:42:10 -0700 Subject: Swap name of compileOption "assumeNoDirectionIsOutput" to "assumeNoDirectionIsInput". --- chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala | 4 ++-- chiselFrontend/src/main/scala/chisel3/internal/CompileOptions.scala | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala b/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala index 74373e22..e3ba4801 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala @@ -134,7 +134,7 @@ object MonoConnect { case (Some(Output), Some(Output)) => issueConnect(sink, source) case (Some(Output), Some(Input)) => issueConnect(sink, source) case (_, None) => { - if (compileOptions.assumeNoDirectionIsOutput) { + if (compileOptions.assumeNoDirectionIsInput) { issueConnect(sink, source) } else { throw UnreadableSourceException @@ -172,7 +172,7 @@ object MonoConnect { case (Some(Input), Some(Output)) => issueConnect(sink, source) case (Some(Output), _) => throw UnwritableSinkException case (_, None) => { - if (compileOptions.assumeNoDirectionIsOutput) { + if (compileOptions.assumeNoDirectionIsInput) { issueConnect(sink, source) } else { throw UnreadableSourceException diff --git a/chiselFrontend/src/main/scala/chisel3/internal/CompileOptions.scala b/chiselFrontend/src/main/scala/chisel3/internal/CompileOptions.scala index 912184fb..a0a20020 100644 --- a/chiselFrontend/src/main/scala/chisel3/internal/CompileOptions.scala +++ b/chiselFrontend/src/main/scala/chisel3/internal/CompileOptions.scala @@ -19,5 +19,5 @@ class CompileOptions(optionsMap: Map[String, String]) { val portDeterminesDirection: Boolean = optionsMap.getOrElse("portDeterminesDirection", looseDefault).toBoolean val tryConnectionsSwapped: Boolean = optionsMap.getOrElse("tryConnectionsSwapped", looseDefault).toBoolean val assumeLHSIsOutput: Boolean = optionsMap.getOrElse("assumeLHSIsOutput", looseDefault).toBoolean - val assumeNoDirectionIsOutput: Boolean = optionsMap.getOrElse("assumeNoDirectionIsOutput", looseDefault).toBoolean + val assumeNoDirectionIsInput: Boolean = optionsMap.getOrElse("assumeNoDirectionIsInput", looseDefault).toBoolean } -- cgit v1.2.3 From f5e9a6c6e55ba19a7c1f2353d0207189062db1c9 Mon Sep 17 00:00:00 2001 From: chick Date: Wed, 24 Aug 2016 17:09:41 -0700 Subject: Per Chisel meeting. signalName -> instanceName SignalId -> InstanceId Based on Stephen's comments on PR --- chiselFrontend/src/main/scala/chisel3/core/Module.scala | 2 +- .../src/main/scala/chisel3/internal/Builder.scala | 16 ++++++++-------- src/test/scala/chiselTests/AnnotatingExample.scala | 8 ++++---- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/Module.scala b/chiselFrontend/src/main/scala/chisel3/core/Module.scala index eb48a14d..2426ae78 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Module.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Module.scala @@ -78,7 +78,7 @@ extends HasId { /** Signal name (for simulation). */ - override def signalName = + override def instanceName = if (_parent == None) name else _component match { case None => getRef.name case Some(c) => getRef fullName c diff --git a/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala b/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala index bf78c410..2dec78bb 100644 --- a/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala +++ b/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala @@ -59,14 +59,14 @@ private[chisel3] class IdGen { * currently, the node's name, the full path name, and references to its parent Module and component. * These are only valid once the design has been elaborated, and should not be used during its construction. */ -trait SignalId { - def signalName: String +trait InstanceId { + def instanceName: String def pathName: String def parentPathName: String def parentModName: String } -private[chisel3] trait HasId extends SignalId { +private[chisel3] trait HasId extends InstanceId { private[chisel3] def _onModuleClose {} // scalastyle:ignore method.name private[chisel3] val _parent = Builder.dynamicContext.currentModule _parent.foreach(_.addId(this)) @@ -108,7 +108,7 @@ private[chisel3] trait HasId extends SignalId { private[chisel3] def getRef: Arg = _ref.get // Implementation of public methods. - def signalName = _parent match { + def instanceName = _parent match { case Some(p) => p._component match { case Some(c) => getRef fullName c case None => throwException("signalName/pathName should be called after circuit elaboration") @@ -116,16 +116,16 @@ private[chisel3] trait HasId extends SignalId { case None => throwException("this cannot happen") } def pathName = _parent match { - case None => signalName - case Some(p) => s"${p.pathName}.$signalName" + case None => instanceName + case Some(p) => s"${p.pathName}.$instanceName" } def parentPathName = _parent match { case Some(p) => p.pathName - case None => throwException(s"$signalName doesn't have a parent") + case None => throwException(s"$instanceName doesn't have a parent") } def parentModName = _parent match { case Some(p) => p.modName - case None => throwException(s"$signalName doesn't have a parent") + case None => throwException(s"$instanceName doesn't have a parent") } } diff --git a/src/test/scala/chiselTests/AnnotatingExample.scala b/src/test/scala/chiselTests/AnnotatingExample.scala index a252309d..c84edf86 100644 --- a/src/test/scala/chiselTests/AnnotatingExample.scala +++ b/src/test/scala/chiselTests/AnnotatingExample.scala @@ -4,7 +4,7 @@ package chiselTests import chisel3._ import chisel3.core.Module -import chisel3.internal.SignalId +import chisel3.internal.InstanceId import chisel3.testers.BasicTester import org.scalatest._ @@ -96,17 +96,17 @@ case object AllRefs extends AnnotationScope case object JustThisRef extends AnnotationScope object AnnotationKey { - def apply(component: SignalId): AnnotationKey = { + def apply(component: InstanceId): AnnotationKey = { AnnotationKey(component, AllRefs) } } -case class AnnotationKey(val component: SignalId, scope: AnnotationScope) { +case class AnnotationKey(val component: InstanceId, scope: AnnotationScope) { override def toString: String = { scope match { case JustThisRef => s"${component.pathName}" case AllRefs => - s"${component.parentModName}.${component.signalName}" + s"${component.parentModName}.${component.instanceName}" case _ => s"${component.toString}_unknown_scope" } -- cgit v1.2.3 From f84e6ef2d68404c741ea7e2aa2f3990ebb0984ee Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Thu, 25 Aug 2016 12:16:33 -0700 Subject: Use bulkConnect in Vec,fill if any (flattened) element of the Vec has a direction associated with it. This impetus for this came out of discussion during the chisel meeting of 8/24/16 in response to errors running the chisel tutorial examples Adder test. --- chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala index 03c84827..5e410ebd 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala @@ -49,9 +49,16 @@ object Vec { // DummyImplicit or additional type parameter will break some code. require(!elts.isEmpty) val width = elts.map(_.width).reduce(_ max _) + // If an element has a direction associated with it, use the bulk connect operator. val vec = Wire(new Vec(elts.head.cloneTypeWidth(width), elts.length)) - for ((v, e) <- vec zip elts) - v := e + def doConnect(sink: T, source: T) = if (elts.head.flatten.exists(_.firrtlDirection != Direction.Unspecified)) { + sink bulkConnect source + } else { + sink connect source + } + for ((v, e) <- vec zip elts) { + doConnect(v, e) + } vec } -- cgit v1.2.3 From 5ca2820216a4c4b8c28438967d6e4680412f6580 Mon Sep 17 00:00:00 2001 From: Donggyu Kim Date: Thu, 25 Aug 2016 14:05:31 -0700 Subject: fix a bug in setModName --- src/main/scala/chisel3/internal/firrtl/Emitter.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/chisel3/internal/firrtl/Emitter.scala b/src/main/scala/chisel3/internal/firrtl/Emitter.scala index 79f86ae9..8b94c68f 100644 --- a/src/main/scala/chisel3/internal/firrtl/Emitter.scala +++ b/src/main/scala/chisel3/internal/firrtl/Emitter.scala @@ -87,7 +87,7 @@ private class Emitter(circuit: Circuit) { "" case None => defnMap((m.id.desiredName, defn)) = m - m.id setModName m.id.name + m.id setModName m.name moduleDecl(m) + defn } } -- cgit v1.2.3 From 5fcdd12fe92bd22f9cdfb8f5e39e510684b709bf Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Mon, 29 Aug 2016 09:33:51 -0700 Subject: Rename individual compile options. Stricter values are "true". Current default (not strict) values are "false". --- .../src/main/scala/chisel3/core/BiConnect.scala | 28 ++++++++++++---------- .../src/main/scala/chisel3/core/Binding.scala | 4 ++-- .../src/main/scala/chisel3/core/Module.scala | 2 +- .../src/main/scala/chisel3/core/MonoConnect.scala | 6 ++--- .../src/main/scala/chisel3/core/Reg.scala | 2 +- .../scala/chisel3/internal/CompileOptions.scala | 9 ++++--- 6 files changed, 26 insertions(+), 25 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala b/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala index c40b85ad..857b25aa 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala @@ -167,32 +167,34 @@ object BiConnect { case (None, Some(Input)) => issueConnectR2L(left, right) case (Some(Input), Some(Input)) => { - if (compileOptions.portDeterminesDirection) - (left.binding, right.binding) match { - case (PortBinding(_, _), PortBinding(_, _)) => throw BothDriversException - case (PortBinding(_, _), _) => issueConnectL2R(left, right) - case (_, PortBinding(_, _)) => issueConnectR2L(left, right) - case _ => throw BothDriversException - } else { + if (compileOptions.dontAssumeDirectionality) { throw BothDriversException + } else { + (left.binding, right.binding) match { + case (PortBinding(_, _), PortBinding(_, _)) => throw BothDriversException + case (PortBinding(_, _), _) => issueConnectL2R(left, right) + case (_, PortBinding(_, _)) => issueConnectR2L(left, right) + case _ => throw BothDriversException + } } } case (Some(Output), Some(Output)) => { - if (compileOptions.portDeterminesDirection) + if (compileOptions.dontAssumeDirectionality) { + throw BothDriversException + } else { (left.binding, right.binding) match { case (PortBinding(_, _), PortBinding(_, _)) => throw BothDriversException case (PortBinding(_, _), _) => issueConnectR2L(left, right) case (_, PortBinding(_, _)) => issueConnectL2R(left, right) case _ => throw BothDriversException - } else { - throw BothDriversException + } } } case (None, None) => { - if (compileOptions.assumeLHSIsOutput) { - issueConnectR2L(left, right) - } else { + if (compileOptions.dontAssumeDirectionality) { throw UnknownDriverException + } else { + issueConnectR2L(left, right) } } } diff --git a/chiselFrontend/src/main/scala/chisel3/core/Binding.scala b/chiselFrontend/src/main/scala/chisel3/core/Binding.scala index da678fed..a32d3ade 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Binding.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Binding.scala @@ -91,7 +91,7 @@ object Binding { element.binding = binder(unbound) } // If autoIOWrap is enabled and we're rebinding a PortBinding, just ignore the rebinding. - case portBound @ PortBinding(_, _) if (compileOptions.autoIOWrap && binder.isInstanceOf[PortBinder]) => + case portBound @ PortBinding(_, _) if (!compileOptions.requireIOWrap && binder.isInstanceOf[PortBinder]) => case binding => throw AlreadyBoundException(binding.toString) } ) @@ -145,7 +145,7 @@ object Binding { case binding => // The following kludge is an attempt to provide backward compatibility // It should be done at at higher level. - if (!(compileOptions.autoIOWrap && elementOfIO(element))) + if ((compileOptions.requireIOWrap || !elementOfIO(element))) throw NotSynthesizableException else Binding.bind(element, PortBinder(element._parent.get), "Error: IO") diff --git a/chiselFrontend/src/main/scala/chisel3/core/Module.scala b/chiselFrontend/src/main/scala/chisel3/core/Module.scala index 19063664..b4659a52 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Module.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Module.scala @@ -113,7 +113,7 @@ extends HasId { private[core] def computePorts: Seq[firrtl.Port] = { // If we're auto-wrapping IO definitions, do so now. - if (compileOptions.autoIOWrap && !ioDefined) { + if (!(compileOptions.requireIOWrap || ioDefined)) { IO(io) } for ((name, port) <- ports) yield { diff --git a/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala b/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala index e3ba4801..66729bac 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala @@ -134,13 +134,13 @@ object MonoConnect { case (Some(Output), Some(Output)) => issueConnect(sink, source) case (Some(Output), Some(Input)) => issueConnect(sink, source) case (_, None) => { - if (compileOptions.assumeNoDirectionIsInput) { + if (!compileOptions.dontAssumeDirectionality) { issueConnect(sink, source) } else { throw UnreadableSourceException } } - case (Some(Input), Some(Output)) if (compileOptions.tryConnectionsSwapped) => issueConnect(source, sink) + case (Some(Input), Some(Output)) if (!compileOptions.dontTryConnectionsSwapped) => issueConnect(source, sink) case (Some(Input), _) => throw UnwritableSinkException } } @@ -172,7 +172,7 @@ object MonoConnect { case (Some(Input), Some(Output)) => issueConnect(sink, source) case (Some(Output), _) => throw UnwritableSinkException case (_, None) => { - if (compileOptions.assumeNoDirectionIsInput) { + if (!compileOptions.dontAssumeDirectionality) { issueConnect(sink, source) } else { throw UnreadableSourceException diff --git a/chiselFrontend/src/main/scala/chisel3/core/Reg.scala b/chiselFrontend/src/main/scala/chisel3/core/Reg.scala index 6c357461..b77c9a31 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Reg.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Reg.scala @@ -10,7 +10,7 @@ import chisel3.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) { - if (Builder.compileOptions.regTypeMustBeUnbound) { + if (Builder.compileOptions.declaredTypeMustBeUnbound) { Binding.checkUnbound(t, s"t ($t) must be unbound Type. Try using cloneType?") } t.chiselCloneType diff --git a/chiselFrontend/src/main/scala/chisel3/internal/CompileOptions.scala b/chiselFrontend/src/main/scala/chisel3/internal/CompileOptions.scala index a0a20020..31d441c1 100644 --- a/chiselFrontend/src/main/scala/chisel3/internal/CompileOptions.scala +++ b/chiselFrontend/src/main/scala/chisel3/internal/CompileOptions.scala @@ -15,9 +15,8 @@ class CompileOptions(optionsMap: Map[String, String]) { // MissingLeftFieldException, or MissingRightFieldException will be thrown. val connectFieldsMustMatch: Boolean = optionsMap.getOrElse("connectFieldsMustMatch", strictDefault).toBoolean val regTypeMustBeUnbound: Boolean = optionsMap.getOrElse("regTypeMustBeUnbound", strictDefault).toBoolean - val autoIOWrap: Boolean = optionsMap.getOrElse("autoIOWrap", looseDefault).toBoolean - val portDeterminesDirection: Boolean = optionsMap.getOrElse("portDeterminesDirection", looseDefault).toBoolean - val tryConnectionsSwapped: Boolean = optionsMap.getOrElse("tryConnectionsSwapped", looseDefault).toBoolean - val assumeLHSIsOutput: Boolean = optionsMap.getOrElse("assumeLHSIsOutput", looseDefault).toBoolean - val assumeNoDirectionIsInput: Boolean = optionsMap.getOrElse("assumeNoDirectionIsInput", looseDefault).toBoolean + val declaredTypeMustBeUnbound: Boolean = optionsMap.getOrElse("declaredTypeMustBeUnbound", strictDefault).toBoolean + val requireIOWrap: Boolean = optionsMap.getOrElse("requireIOWrap", strictDefault).toBoolean + val dontTryConnectionsSwapped: Boolean = optionsMap.getOrElse("dontTryConnectionsSwapped", strictDefault).toBoolean + val dontAssumeDirectionality: Boolean = optionsMap.getOrElse("dontAssumeDirectionality", strictDefault).toBoolean } -- cgit v1.2.3 From 6df3a785f8abe706838bc5b4b35c3374b6512f96 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Mon, 29 Aug 2016 12:17:48 -0700 Subject: Pass compileOptions as an implicit Module parameter. --- .../src/main/scala/chisel3/core/BlackBox.scala | 1 + .../src/main/scala/chisel3/core/Module.scala | 3 ++ .../src/main/scala/chisel3/internal/Builder.scala | 14 ++++---- .../scala/chisel3/internal/CompileOptions.scala | 39 ++++++++++++++-------- .../src/main/scala/chisel3/notstrict.scala | 16 +++++++++ chiselFrontend/src/main/scala/chisel3/strict.scala | 16 +++++++++ src/main/scala/chisel3/testers/BasicTester.scala | 3 +- src/main/scala/chisel3/util/Arbiter.scala | 1 + src/main/scala/chisel3/util/Decoupled.scala | 1 + src/main/scala/chisel3/util/Valid.scala | 1 + src/test/scala/chiselTests/Assert.scala | 1 + src/test/scala/chiselTests/BetterNamingTests.scala | 1 + src/test/scala/chiselTests/BundleWire.scala | 1 + src/test/scala/chiselTests/ComplexAssign.scala | 1 + src/test/scala/chiselTests/Decoder.scala | 1 + src/test/scala/chiselTests/DeqIOSpec.scala | 1 + src/test/scala/chiselTests/Direction.scala | 1 + .../scala/chiselTests/EnableShiftRegister.scala | 1 + src/test/scala/chiselTests/GCD.scala | 1 + src/test/scala/chiselTests/IOCompatibility.scala | 1 + src/test/scala/chiselTests/LFSR16.scala | 1 + src/test/scala/chiselTests/MemorySearch.scala | 1 + src/test/scala/chiselTests/Module.scala | 1 + src/test/scala/chiselTests/MulLookup.scala | 1 + src/test/scala/chiselTests/OptionBundle.scala | 1 + src/test/scala/chiselTests/Padding.scala | 1 + .../scala/chiselTests/ParameterizedModule.scala | 1 + src/test/scala/chiselTests/Risc.scala | 1 + src/test/scala/chiselTests/SIntOps.scala | 1 + src/test/scala/chiselTests/Stack.scala | 1 + src/test/scala/chiselTests/Tbl.scala | 1 + src/test/scala/chiselTests/UIntOps.scala | 1 + src/test/scala/chiselTests/VectorPacketIO.scala | 1 + src/test/scala/chiselTests/VendingMachine.scala | 1 + 34 files changed, 97 insertions(+), 22 deletions(-) create mode 100644 chiselFrontend/src/main/scala/chisel3/notstrict.scala create mode 100644 chiselFrontend/src/main/scala/chisel3/strict.scala diff --git a/chiselFrontend/src/main/scala/chisel3/core/BlackBox.scala b/chiselFrontend/src/main/scala/chisel3/core/BlackBox.scala index f2d9558d..a9f89cbc 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/BlackBox.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/BlackBox.scala @@ -5,6 +5,7 @@ package chisel3.core import chisel3.internal.Builder.pushCommand import chisel3.internal.firrtl.{ModuleIO, DefInvalid} import chisel3.internal.sourceinfo.SourceInfo +import chisel3.NotStrict.NotStrictCompileOptions /** 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/Module.scala b/chiselFrontend/src/main/scala/chisel3/core/Module.scala index b4659a52..47003df0 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Module.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Module.scala @@ -9,6 +9,7 @@ import chisel3.internal.Builder._ import chisel3.internal.firrtl._ import chisel3.internal.firrtl.{Command => _, _} import chisel3.internal.sourceinfo.{InstTransform, SourceInfo, UnlocatableSourceInfo} +import chisel3.NotStrict.NotStrictCompileOptions object Module { /** A wrapper method that all Module instantiations must be wrapped in @@ -49,6 +50,7 @@ object Module { */ abstract class Module( override_clock: Option[Clock]=None, override_reset: Option[Bool]=None) + (implicit moduleCompileOptions: ExplicitCompileOptions) extends HasId { // _clock and _reset can be clock and reset in these 2ary constructors // once chisel2 compatibility issues are resolved @@ -186,4 +188,5 @@ extends HasId { } // For debuggers/testers lazy val getPorts = computePorts + val compileOptions = moduleCompileOptions } diff --git a/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala b/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala index 9f2b1631..9b656dea 100644 --- a/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala +++ b/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala @@ -97,16 +97,16 @@ private[chisel3] trait HasId { private[chisel3] def getRef: Arg = _ref.get } -private[chisel3] class DynamicContext(optionMap: Option[Map[String, String]] = None) { +private[chisel3] class DynamicContext(moduleCompileOptions: Option[ExplicitCompileOptions] = None) { val idGen = new IdGen val globalNamespace = new Namespace(None, Set()) val components = ArrayBuffer[Component]() var currentModule: Option[Module] = None val errors = new ErrorLog - val compileOptions = new CompileOptions(optionMap match { - case Some(map: Map[String, String]) => map - case None => Map[String, String]() - }) + val compileOptions = moduleCompileOptions match { + case Some(options: ExplicitCompileOptions) => options + case None => chisel3.NotStrict.NotStrictCompileOptions + } } private[chisel3] object Builder { @@ -147,8 +147,8 @@ private[chisel3] object Builder { def errors: ErrorLog = dynamicContext.errors def error(m: => String): Unit = errors.error(m) - def build[T <: Module](f: => T, optionMap: Option[Map[String, String]] = None): Circuit = { - dynamicContextVar.withValue(Some(new DynamicContext(optionMap))) { + def build[T <: Module](f: => T, moduleCompileOptions: Option[ExplicitCompileOptions] = None): Circuit = { + dynamicContextVar.withValue(Some(new DynamicContext(moduleCompileOptions))) { errors.info("Elaborating design...") val mod = f mod.forceName(mod.name, globalNamespace) diff --git a/chiselFrontend/src/main/scala/chisel3/internal/CompileOptions.scala b/chiselFrontend/src/main/scala/chisel3/internal/CompileOptions.scala index 31d441c1..2890f6dc 100644 --- a/chiselFrontend/src/main/scala/chisel3/internal/CompileOptions.scala +++ b/chiselFrontend/src/main/scala/chisel3/internal/CompileOptions.scala @@ -2,21 +2,32 @@ package chisel3.internal -/** Initialize compilation options from a string map. - * - * @param optionsMap the map from "option" to "value" - */ -class CompileOptions(optionsMap: Map[String, String]) { - // The default for settings related to "strictness". - val strictDefault: String = optionsMap.getOrElse("strict", "false") - val looseDefault: String = (!(strictDefault.toBoolean)).toString +trait CompileOptions { // Should Bundle connections require a strict match of fields. // If true and the same fields aren't present in both source and sink, a MissingFieldException, // MissingLeftFieldException, or MissingRightFieldException will be thrown. - val connectFieldsMustMatch: Boolean = optionsMap.getOrElse("connectFieldsMustMatch", strictDefault).toBoolean - val regTypeMustBeUnbound: Boolean = optionsMap.getOrElse("regTypeMustBeUnbound", strictDefault).toBoolean - val declaredTypeMustBeUnbound: Boolean = optionsMap.getOrElse("declaredTypeMustBeUnbound", strictDefault).toBoolean - val requireIOWrap: Boolean = optionsMap.getOrElse("requireIOWrap", strictDefault).toBoolean - val dontTryConnectionsSwapped: Boolean = optionsMap.getOrElse("dontTryConnectionsSwapped", strictDefault).toBoolean - val dontAssumeDirectionality: Boolean = optionsMap.getOrElse("dontAssumeDirectionality", strictDefault).toBoolean + val connectFieldsMustMatch: Boolean + val declaredTypeMustBeUnbound: Boolean + val requireIOWrap: Boolean + val dontTryConnectionsSwapped: Boolean + val dontAssumeDirectionality: Boolean } + +trait ExplicitCompileOptions extends CompileOptions + +///** Initialize compilation options from a string map. +// * +// * @param optionsMap the map from "option" to "value" +// */ +//class CompileOptions(optionsMap: Map[String, String]) { +// // The default for settings related to "strictness". +// val strictDefault: String = optionsMap.getOrElse("strict", "false") +// // Should Bundle connections require a strict match of fields. +// // If true and the same fields aren't present in both source and sink, a MissingFieldException, +// // MissingLeftFieldException, or MissingRightFieldException will be thrown. +// val connectFieldsMustMatch: Boolean = optionsMap.getOrElse("connectFieldsMustMatch", strictDefault).toBoolean +// val declaredTypeMustBeUnbound: Boolean = optionsMap.getOrElse("declaredTypeMustBeUnbound", strictDefault).toBoolean +// val requireIOWrap: Boolean = optionsMap.getOrElse("requireIOWrap", strictDefault).toBoolean +// val dontTryConnectionsSwapped: Boolean = optionsMap.getOrElse("dontTryConnectionsSwapped", strictDefault).toBoolean +// val dontAssumeDirectionality: Boolean = optionsMap.getOrElse("dontAssumeDirectionality", strictDefault).toBoolean +//} diff --git a/chiselFrontend/src/main/scala/chisel3/notstrict.scala b/chiselFrontend/src/main/scala/chisel3/notstrict.scala new file mode 100644 index 00000000..dc4bf807 --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel3/notstrict.scala @@ -0,0 +1,16 @@ +// See LICENSE for license details. + +package chisel3 + +import chisel3.internal.ExplicitCompileOptions + + +object NotStrict { + implicit object NotStrictCompileOptions extends ExplicitCompileOptions { + val connectFieldsMustMatch = false + val declaredTypeMustBeUnbound = false + val requireIOWrap = false + val dontTryConnectionsSwapped = false + val dontAssumeDirectionality = false + } +} diff --git a/chiselFrontend/src/main/scala/chisel3/strict.scala b/chiselFrontend/src/main/scala/chisel3/strict.scala new file mode 100644 index 00000000..f6db8765 --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel3/strict.scala @@ -0,0 +1,16 @@ +// See LICENSE for license details. + +package chisel3 + +import chisel3.internal.ExplicitCompileOptions + + +object Strict { + implicit object StrictCompileOptions extends ExplicitCompileOptions { + val connectFieldsMustMatch = true + val declaredTypeMustBeUnbound = true + val requireIOWrap = true + val dontTryConnectionsSwapped = true + val dontAssumeDirectionality = true + } +} diff --git a/src/main/scala/chisel3/testers/BasicTester.scala b/src/main/scala/chisel3/testers/BasicTester.scala index 329237c6..0c8df2eb 100644 --- a/src/main/scala/chisel3/testers/BasicTester.scala +++ b/src/main/scala/chisel3/testers/BasicTester.scala @@ -9,8 +9,9 @@ import internal._ import internal.Builder.pushCommand import internal.firrtl._ import internal.sourceinfo.SourceInfo +import chisel3.NotStrict.NotStrictCompileOptions -class BasicTester extends Module { +class BasicTester extends Module() { // The testbench has no IOs, rather it should communicate using printf, assert, and stop. val io = IO(new Bundle()) diff --git a/src/main/scala/chisel3/util/Arbiter.scala b/src/main/scala/chisel3/util/Arbiter.scala index 5875b3f2..57e81708 100644 --- a/src/main/scala/chisel3/util/Arbiter.scala +++ b/src/main/scala/chisel3/util/Arbiter.scala @@ -6,6 +6,7 @@ package chisel3.util import chisel3._ +import chisel3.NotStrict.NotStrictCompileOptions /** 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/Decoupled.scala b/src/main/scala/chisel3/util/Decoupled.scala index 42f58ea9..8064d19b 100644 --- a/src/main/scala/chisel3/util/Decoupled.scala +++ b/src/main/scala/chisel3/util/Decoupled.scala @@ -6,6 +6,7 @@ package chisel3.util import chisel3._ +import chisel3.NotStrict.NotStrictCompileOptions /** 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/Valid.scala b/src/main/scala/chisel3/util/Valid.scala index 743038f3..d465d18d 100644 --- a/src/main/scala/chisel3/util/Valid.scala +++ b/src/main/scala/chisel3/util/Valid.scala @@ -6,6 +6,7 @@ package chisel3.util import chisel3._ +import chisel3.NotStrict.NotStrictCompileOptions /** An Bundle containing data and a signal determining if it is valid */ class Valid[+T <: Data](gen: T) extends Bundle diff --git a/src/test/scala/chiselTests/Assert.scala b/src/test/scala/chiselTests/Assert.scala index efc2e1e7..0afeac7b 100644 --- a/src/test/scala/chiselTests/Assert.scala +++ b/src/test/scala/chiselTests/Assert.scala @@ -6,6 +6,7 @@ import org.scalatest._ import chisel3._ import chisel3.testers.BasicTester import chisel3.util._ +import chisel3.NotStrict.NotStrictCompileOptions class FailingAssertTester() extends BasicTester { assert(Bool(false)) diff --git a/src/test/scala/chiselTests/BetterNamingTests.scala b/src/test/scala/chiselTests/BetterNamingTests.scala index 44fc542a..7d69d604 100644 --- a/src/test/scala/chiselTests/BetterNamingTests.scala +++ b/src/test/scala/chiselTests/BetterNamingTests.scala @@ -4,6 +4,7 @@ import org.scalatest.{FlatSpec, Matchers} import collection.mutable import Chisel._ +import chisel3.NotStrict.NotStrictCompileOptions // Defined outside of the class so we don't get $ in name diff --git a/src/test/scala/chiselTests/BundleWire.scala b/src/test/scala/chiselTests/BundleWire.scala index 0071041c..c72ad78d 100644 --- a/src/test/scala/chiselTests/BundleWire.scala +++ b/src/test/scala/chiselTests/BundleWire.scala @@ -5,6 +5,7 @@ import chisel3._ import org.scalatest._ import org.scalatest.prop._ import chisel3.testers.BasicTester +import chisel3.Strict.StrictCompileOptions class Coord extends Bundle { val x = UInt.width( 32) diff --git a/src/test/scala/chiselTests/ComplexAssign.scala b/src/test/scala/chiselTests/ComplexAssign.scala index 0a1f31cc..efca4947 100644 --- a/src/test/scala/chiselTests/ComplexAssign.scala +++ b/src/test/scala/chiselTests/ComplexAssign.scala @@ -8,6 +8,7 @@ import org.scalatest.prop._ import chisel3._ import chisel3.testers.BasicTester import chisel3.util._ +import chisel3.NotStrict.NotStrictCompileOptions class Complex[T <: Data](val re: T, val im: T) extends Bundle { override def cloneType: this.type = diff --git a/src/test/scala/chiselTests/Decoder.scala b/src/test/scala/chiselTests/Decoder.scala index b50a80c0..758b4f6d 100644 --- a/src/test/scala/chiselTests/Decoder.scala +++ b/src/test/scala/chiselTests/Decoder.scala @@ -9,6 +9,7 @@ import org.scalacheck._ import chisel3._ import chisel3.testers.BasicTester import chisel3.util._ +import chisel3.NotStrict.NotStrictCompileOptions class Decoder(bitpats: List[String]) extends Module { val io = IO(new Bundle { diff --git a/src/test/scala/chiselTests/DeqIOSpec.scala b/src/test/scala/chiselTests/DeqIOSpec.scala index d41c50e5..9ad776da 100644 --- a/src/test/scala/chiselTests/DeqIOSpec.scala +++ b/src/test/scala/chiselTests/DeqIOSpec.scala @@ -5,6 +5,7 @@ package chiselTests import chisel3._ import chisel3.testers.BasicTester import chisel3.util._ +import chisel3.NotStrict.NotStrictCompileOptions /** * Created by chick on 2/8/16. diff --git a/src/test/scala/chiselTests/Direction.scala b/src/test/scala/chiselTests/Direction.scala index 949b92ed..ec1232e2 100644 --- a/src/test/scala/chiselTests/Direction.scala +++ b/src/test/scala/chiselTests/Direction.scala @@ -6,6 +6,7 @@ import chisel3._ import org.scalatest._ import org.scalatest.prop._ import chisel3.testers.BasicTester +import chisel3.NotStrict.NotStrictCompileOptions class DirectionHaver extends Module { val io = IO(new Bundle { diff --git a/src/test/scala/chiselTests/EnableShiftRegister.scala b/src/test/scala/chiselTests/EnableShiftRegister.scala index 5f3e0dd1..ee568be5 100644 --- a/src/test/scala/chiselTests/EnableShiftRegister.scala +++ b/src/test/scala/chiselTests/EnableShiftRegister.scala @@ -3,6 +3,7 @@ package chiselTests import chisel3._ import chisel3.testers.BasicTester +import chisel3.NotStrict.NotStrictCompileOptions class EnableShiftRegister extends Module { val io = IO(new Bundle { diff --git a/src/test/scala/chiselTests/GCD.scala b/src/test/scala/chiselTests/GCD.scala index d683ce34..8c298d14 100644 --- a/src/test/scala/chiselTests/GCD.scala +++ b/src/test/scala/chiselTests/GCD.scala @@ -6,6 +6,7 @@ import chisel3._ import chisel3.testers.BasicTester import org.scalatest._ import org.scalatest.prop._ +import chisel3.NotStrict.NotStrictCompileOptions class GCD extends Module { val io = IO(new Bundle { diff --git a/src/test/scala/chiselTests/IOCompatibility.scala b/src/test/scala/chiselTests/IOCompatibility.scala index edbd3d09..c247973d 100644 --- a/src/test/scala/chiselTests/IOCompatibility.scala +++ b/src/test/scala/chiselTests/IOCompatibility.scala @@ -3,6 +3,7 @@ package chiselTests import Chisel._ +import chisel3.NotStrict.NotStrictCompileOptions class IOCSimpleIO extends Bundle { val in = UInt(INPUT, 32) diff --git a/src/test/scala/chiselTests/LFSR16.scala b/src/test/scala/chiselTests/LFSR16.scala index b13b67e3..b1b2b415 100644 --- a/src/test/scala/chiselTests/LFSR16.scala +++ b/src/test/scala/chiselTests/LFSR16.scala @@ -5,6 +5,7 @@ package chiselTests import chisel3._ import chisel3.testers.BasicTester import chisel3.util._ +import chisel3.NotStrict.NotStrictCompileOptions class LFSR16 extends Module { val io = IO(new Bundle { diff --git a/src/test/scala/chiselTests/MemorySearch.scala b/src/test/scala/chiselTests/MemorySearch.scala index 1d09f3c5..b05a112b 100644 --- a/src/test/scala/chiselTests/MemorySearch.scala +++ b/src/test/scala/chiselTests/MemorySearch.scala @@ -4,6 +4,7 @@ package chiselTests import chisel3._ import chisel3.testers.BasicTester +import chisel3.NotStrict.NotStrictCompileOptions class MemorySearch extends Module { val io = IO(new Bundle { diff --git a/src/test/scala/chiselTests/Module.scala b/src/test/scala/chiselTests/Module.scala index 7a4050db..8d72fc44 100644 --- a/src/test/scala/chiselTests/Module.scala +++ b/src/test/scala/chiselTests/Module.scala @@ -3,6 +3,7 @@ package chiselTests import chisel3._ +import chisel3.NotStrict.NotStrictCompileOptions class SimpleIO extends Bundle { val in = Input(UInt.width(32)) diff --git a/src/test/scala/chiselTests/MulLookup.scala b/src/test/scala/chiselTests/MulLookup.scala index 26ee4e03..63a0a7c7 100644 --- a/src/test/scala/chiselTests/MulLookup.scala +++ b/src/test/scala/chiselTests/MulLookup.scala @@ -6,6 +6,7 @@ import chisel3._ import org.scalatest._ import org.scalatest.prop._ import chisel3.testers.BasicTester +import chisel3.NotStrict.NotStrictCompileOptions class MulLookup(val w: Int) extends Module { val io = IO(new Bundle { diff --git a/src/test/scala/chiselTests/OptionBundle.scala b/src/test/scala/chiselTests/OptionBundle.scala index 8e4c7579..236e1007 100644 --- a/src/test/scala/chiselTests/OptionBundle.scala +++ b/src/test/scala/chiselTests/OptionBundle.scala @@ -5,6 +5,7 @@ package chiselTests import org.scalatest._ import chisel3._ import chisel3.testers.BasicTester +import chisel3.NotStrict.NotStrictCompileOptions 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 42df6802..ca769b49 100644 --- a/src/test/scala/chiselTests/Padding.scala +++ b/src/test/scala/chiselTests/Padding.scala @@ -3,6 +3,7 @@ package chiselTests import chisel3._ +import chisel3.NotStrict.NotStrictCompileOptions class Padder extends Module { val io = IO(new Bundle { diff --git a/src/test/scala/chiselTests/ParameterizedModule.scala b/src/test/scala/chiselTests/ParameterizedModule.scala index 14b21631..2929cccc 100644 --- a/src/test/scala/chiselTests/ParameterizedModule.scala +++ b/src/test/scala/chiselTests/ParameterizedModule.scala @@ -5,6 +5,7 @@ package chiselTests import org.scalatest._ import chisel3._ import chisel3.testers.BasicTester +import chisel3.NotStrict.NotStrictCompileOptions class ParameterizedModule(invert: Boolean) extends Module { val io = IO(new Bundle { diff --git a/src/test/scala/chiselTests/Risc.scala b/src/test/scala/chiselTests/Risc.scala index 6d5a0a76..f255f996 100644 --- a/src/test/scala/chiselTests/Risc.scala +++ b/src/test/scala/chiselTests/Risc.scala @@ -4,6 +4,7 @@ package chiselTests import chisel3._ import chisel3.util._ +import chisel3.NotStrict.NotStrictCompileOptions class Risc extends Module { val io = IO(new Bundle { diff --git a/src/test/scala/chiselTests/SIntOps.scala b/src/test/scala/chiselTests/SIntOps.scala index 392c4803..227a4514 100644 --- a/src/test/scala/chiselTests/SIntOps.scala +++ b/src/test/scala/chiselTests/SIntOps.scala @@ -4,6 +4,7 @@ package chiselTests import chisel3._ import chisel3.testers.BasicTester +import chisel3.NotStrict.NotStrictCompileOptions class SIntOps extends Module { val io = IO(new Bundle { diff --git a/src/test/scala/chiselTests/Stack.scala b/src/test/scala/chiselTests/Stack.scala index a72af928..9ccfc9ee 100644 --- a/src/test/scala/chiselTests/Stack.scala +++ b/src/test/scala/chiselTests/Stack.scala @@ -6,6 +6,7 @@ import scala.collection.mutable.Stack import chisel3._ import chisel3.util._ +import chisel3.NotStrict.NotStrictCompileOptions class ChiselStack(val depth: Int) extends Module { val io = IO(new Bundle { diff --git a/src/test/scala/chiselTests/Tbl.scala b/src/test/scala/chiselTests/Tbl.scala index 66a06435..2aa8b031 100644 --- a/src/test/scala/chiselTests/Tbl.scala +++ b/src/test/scala/chiselTests/Tbl.scala @@ -8,6 +8,7 @@ import org.scalatest.prop._ import chisel3._ import chisel3.testers.BasicTester import chisel3.util._ +import chisel3.NotStrict.NotStrictCompileOptions class Tbl(w: Int, n: Int) extends Module { val io = IO(new Bundle { diff --git a/src/test/scala/chiselTests/UIntOps.scala b/src/test/scala/chiselTests/UIntOps.scala index ad5aecd8..836ad864 100644 --- a/src/test/scala/chiselTests/UIntOps.scala +++ b/src/test/scala/chiselTests/UIntOps.scala @@ -5,6 +5,7 @@ package chiselTests import chisel3._ import org.scalatest._ import chisel3.testers.BasicTester +import chisel3.NotStrict.NotStrictCompileOptions class UIntOps extends Module { val io = IO(new Bundle { diff --git a/src/test/scala/chiselTests/VectorPacketIO.scala b/src/test/scala/chiselTests/VectorPacketIO.scala index b8e3a154..66b599a9 100644 --- a/src/test/scala/chiselTests/VectorPacketIO.scala +++ b/src/test/scala/chiselTests/VectorPacketIO.scala @@ -5,6 +5,7 @@ package chiselTests import chisel3._ import chisel3.testers.BasicTester import chisel3.util._ +import chisel3.NotStrict.NotStrictCompileOptions /** * 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 00b1e7de..89060941 100644 --- a/src/test/scala/chiselTests/VendingMachine.scala +++ b/src/test/scala/chiselTests/VendingMachine.scala @@ -4,6 +4,7 @@ package chiselTests import chisel3._ import chisel3.util._ +import chisel3.NotStrict.NotStrictCompileOptions class VendingMachine extends Module { val io = IO(new Bundle { -- cgit v1.2.3 From 62817134d222747f1eab34626fe7b1bb13b9f6df Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Mon, 29 Aug 2016 13:45:05 -0700 Subject: Rename CompileOptions implicit objects. --- chiselFrontend/src/main/scala/chisel3/core/BlackBox.scala | 2 +- chiselFrontend/src/main/scala/chisel3/core/Module.scala | 2 +- chiselFrontend/src/main/scala/chisel3/internal/Builder.scala | 2 +- chiselFrontend/src/main/scala/chisel3/notstrict.scala | 2 +- chiselFrontend/src/main/scala/chisel3/strict.scala | 2 +- src/main/scala/chisel3/testers/BasicTester.scala | 2 +- src/main/scala/chisel3/util/Arbiter.scala | 2 +- src/main/scala/chisel3/util/Decoupled.scala | 2 +- src/main/scala/chisel3/util/Valid.scala | 2 +- src/test/scala/chiselTests/Assert.scala | 2 +- src/test/scala/chiselTests/BetterNamingTests.scala | 2 +- src/test/scala/chiselTests/BundleWire.scala | 2 +- src/test/scala/chiselTests/ComplexAssign.scala | 2 +- src/test/scala/chiselTests/Decoder.scala | 2 +- src/test/scala/chiselTests/DeqIOSpec.scala | 2 +- src/test/scala/chiselTests/Direction.scala | 2 +- src/test/scala/chiselTests/EnableShiftRegister.scala | 2 +- src/test/scala/chiselTests/GCD.scala | 2 +- src/test/scala/chiselTests/IOCompatibility.scala | 2 +- src/test/scala/chiselTests/LFSR16.scala | 2 +- src/test/scala/chiselTests/MemorySearch.scala | 2 +- src/test/scala/chiselTests/Module.scala | 2 +- src/test/scala/chiselTests/MulLookup.scala | 2 +- src/test/scala/chiselTests/OptionBundle.scala | 2 +- src/test/scala/chiselTests/Padding.scala | 2 +- src/test/scala/chiselTests/ParameterizedModule.scala | 2 +- src/test/scala/chiselTests/Risc.scala | 2 +- src/test/scala/chiselTests/SIntOps.scala | 2 +- src/test/scala/chiselTests/Stack.scala | 2 +- src/test/scala/chiselTests/Tbl.scala | 2 +- src/test/scala/chiselTests/UIntOps.scala | 2 +- src/test/scala/chiselTests/VectorPacketIO.scala | 2 +- src/test/scala/chiselTests/VendingMachine.scala | 2 +- 33 files changed, 33 insertions(+), 33 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/BlackBox.scala b/chiselFrontend/src/main/scala/chisel3/core/BlackBox.scala index a9f89cbc..7b0cf3f7 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/BlackBox.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/BlackBox.scala @@ -5,7 +5,7 @@ package chisel3.core import chisel3.internal.Builder.pushCommand import chisel3.internal.firrtl.{ModuleIO, DefInvalid} import chisel3.internal.sourceinfo.SourceInfo -import chisel3.NotStrict.NotStrictCompileOptions +import chisel3.NotStrict.CompileOptions /** 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/Module.scala b/chiselFrontend/src/main/scala/chisel3/core/Module.scala index 47003df0..2cfc6c6a 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Module.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Module.scala @@ -9,7 +9,7 @@ import chisel3.internal.Builder._ import chisel3.internal.firrtl._ import chisel3.internal.firrtl.{Command => _, _} import chisel3.internal.sourceinfo.{InstTransform, SourceInfo, UnlocatableSourceInfo} -import chisel3.NotStrict.NotStrictCompileOptions +import chisel3.NotStrict.CompileOptions object Module { /** A wrapper method that all Module instantiations must be wrapped in diff --git a/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala b/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala index 9b656dea..3191e384 100644 --- a/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala +++ b/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala @@ -105,7 +105,7 @@ private[chisel3] class DynamicContext(moduleCompileOptions: Option[ExplicitCompi val errors = new ErrorLog val compileOptions = moduleCompileOptions match { case Some(options: ExplicitCompileOptions) => options - case None => chisel3.NotStrict.NotStrictCompileOptions + case None => chisel3.NotStrict.CompileOptions } } diff --git a/chiselFrontend/src/main/scala/chisel3/notstrict.scala b/chiselFrontend/src/main/scala/chisel3/notstrict.scala index dc4bf807..bb390e7c 100644 --- a/chiselFrontend/src/main/scala/chisel3/notstrict.scala +++ b/chiselFrontend/src/main/scala/chisel3/notstrict.scala @@ -6,7 +6,7 @@ import chisel3.internal.ExplicitCompileOptions object NotStrict { - implicit object NotStrictCompileOptions extends ExplicitCompileOptions { + implicit object CompileOptions extends ExplicitCompileOptions { val connectFieldsMustMatch = false val declaredTypeMustBeUnbound = false val requireIOWrap = false diff --git a/chiselFrontend/src/main/scala/chisel3/strict.scala b/chiselFrontend/src/main/scala/chisel3/strict.scala index f6db8765..70240429 100644 --- a/chiselFrontend/src/main/scala/chisel3/strict.scala +++ b/chiselFrontend/src/main/scala/chisel3/strict.scala @@ -6,7 +6,7 @@ import chisel3.internal.ExplicitCompileOptions object Strict { - implicit object StrictCompileOptions extends ExplicitCompileOptions { + implicit object CompileOptions extends ExplicitCompileOptions { val connectFieldsMustMatch = true val declaredTypeMustBeUnbound = true val requireIOWrap = true diff --git a/src/main/scala/chisel3/testers/BasicTester.scala b/src/main/scala/chisel3/testers/BasicTester.scala index 0c8df2eb..edb32853 100644 --- a/src/main/scala/chisel3/testers/BasicTester.scala +++ b/src/main/scala/chisel3/testers/BasicTester.scala @@ -9,7 +9,7 @@ import internal._ import internal.Builder.pushCommand import internal.firrtl._ import internal.sourceinfo.SourceInfo -import chisel3.NotStrict.NotStrictCompileOptions +import chisel3.NotStrict.CompileOptions class BasicTester extends Module() { // The testbench has no IOs, rather it should communicate using printf, assert, and stop. diff --git a/src/main/scala/chisel3/util/Arbiter.scala b/src/main/scala/chisel3/util/Arbiter.scala index 57e81708..5d46b7b9 100644 --- a/src/main/scala/chisel3/util/Arbiter.scala +++ b/src/main/scala/chisel3/util/Arbiter.scala @@ -6,7 +6,7 @@ package chisel3.util import chisel3._ -import chisel3.NotStrict.NotStrictCompileOptions +import chisel3.NotStrict.CompileOptions /** 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/Decoupled.scala b/src/main/scala/chisel3/util/Decoupled.scala index 8064d19b..63831d2f 100644 --- a/src/main/scala/chisel3/util/Decoupled.scala +++ b/src/main/scala/chisel3/util/Decoupled.scala @@ -6,7 +6,7 @@ package chisel3.util import chisel3._ -import chisel3.NotStrict.NotStrictCompileOptions +import chisel3.NotStrict.CompileOptions /** 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/Valid.scala b/src/main/scala/chisel3/util/Valid.scala index d465d18d..ed4c3721 100644 --- a/src/main/scala/chisel3/util/Valid.scala +++ b/src/main/scala/chisel3/util/Valid.scala @@ -6,7 +6,7 @@ package chisel3.util import chisel3._ -import chisel3.NotStrict.NotStrictCompileOptions +import chisel3.NotStrict.CompileOptions /** An Bundle containing data and a signal determining if it is valid */ class Valid[+T <: Data](gen: T) extends Bundle diff --git a/src/test/scala/chiselTests/Assert.scala b/src/test/scala/chiselTests/Assert.scala index 0afeac7b..509dedbd 100644 --- a/src/test/scala/chiselTests/Assert.scala +++ b/src/test/scala/chiselTests/Assert.scala @@ -6,7 +6,7 @@ import org.scalatest._ import chisel3._ import chisel3.testers.BasicTester import chisel3.util._ -import chisel3.NotStrict.NotStrictCompileOptions +import chisel3.NotStrict.CompileOptions class FailingAssertTester() extends BasicTester { assert(Bool(false)) diff --git a/src/test/scala/chiselTests/BetterNamingTests.scala b/src/test/scala/chiselTests/BetterNamingTests.scala index 7d69d604..a480da98 100644 --- a/src/test/scala/chiselTests/BetterNamingTests.scala +++ b/src/test/scala/chiselTests/BetterNamingTests.scala @@ -4,7 +4,7 @@ import org.scalatest.{FlatSpec, Matchers} import collection.mutable import Chisel._ -import chisel3.NotStrict.NotStrictCompileOptions +import chisel3.NotStrict.CompileOptions // Defined outside of the class so we don't get $ in name diff --git a/src/test/scala/chiselTests/BundleWire.scala b/src/test/scala/chiselTests/BundleWire.scala index c72ad78d..15c5d5f8 100644 --- a/src/test/scala/chiselTests/BundleWire.scala +++ b/src/test/scala/chiselTests/BundleWire.scala @@ -5,7 +5,7 @@ import chisel3._ import org.scalatest._ import org.scalatest.prop._ import chisel3.testers.BasicTester -import chisel3.Strict.StrictCompileOptions +import chisel3.Strict.CompileOptions class Coord extends Bundle { val x = UInt.width( 32) diff --git a/src/test/scala/chiselTests/ComplexAssign.scala b/src/test/scala/chiselTests/ComplexAssign.scala index efca4947..48a673cf 100644 --- a/src/test/scala/chiselTests/ComplexAssign.scala +++ b/src/test/scala/chiselTests/ComplexAssign.scala @@ -8,7 +8,7 @@ import org.scalatest.prop._ import chisel3._ import chisel3.testers.BasicTester import chisel3.util._ -import chisel3.NotStrict.NotStrictCompileOptions +import chisel3.NotStrict.CompileOptions class Complex[T <: Data](val re: T, val im: T) extends Bundle { override def cloneType: this.type = diff --git a/src/test/scala/chiselTests/Decoder.scala b/src/test/scala/chiselTests/Decoder.scala index 758b4f6d..35c83a8a 100644 --- a/src/test/scala/chiselTests/Decoder.scala +++ b/src/test/scala/chiselTests/Decoder.scala @@ -9,7 +9,7 @@ import org.scalacheck._ import chisel3._ import chisel3.testers.BasicTester import chisel3.util._ -import chisel3.NotStrict.NotStrictCompileOptions +import chisel3.NotStrict.CompileOptions class Decoder(bitpats: List[String]) extends Module { val io = IO(new Bundle { diff --git a/src/test/scala/chiselTests/DeqIOSpec.scala b/src/test/scala/chiselTests/DeqIOSpec.scala index 9ad776da..31508149 100644 --- a/src/test/scala/chiselTests/DeqIOSpec.scala +++ b/src/test/scala/chiselTests/DeqIOSpec.scala @@ -5,7 +5,7 @@ package chiselTests import chisel3._ import chisel3.testers.BasicTester import chisel3.util._ -import chisel3.NotStrict.NotStrictCompileOptions +import chisel3.NotStrict.CompileOptions /** * Created by chick on 2/8/16. diff --git a/src/test/scala/chiselTests/Direction.scala b/src/test/scala/chiselTests/Direction.scala index ec1232e2..7cfe8268 100644 --- a/src/test/scala/chiselTests/Direction.scala +++ b/src/test/scala/chiselTests/Direction.scala @@ -6,7 +6,7 @@ import chisel3._ import org.scalatest._ import org.scalatest.prop._ import chisel3.testers.BasicTester -import chisel3.NotStrict.NotStrictCompileOptions +import chisel3.NotStrict.CompileOptions class DirectionHaver extends Module { val io = IO(new Bundle { diff --git a/src/test/scala/chiselTests/EnableShiftRegister.scala b/src/test/scala/chiselTests/EnableShiftRegister.scala index ee568be5..15173e0f 100644 --- a/src/test/scala/chiselTests/EnableShiftRegister.scala +++ b/src/test/scala/chiselTests/EnableShiftRegister.scala @@ -3,7 +3,7 @@ package chiselTests import chisel3._ import chisel3.testers.BasicTester -import chisel3.NotStrict.NotStrictCompileOptions +import chisel3.NotStrict.CompileOptions class EnableShiftRegister extends Module { val io = IO(new Bundle { diff --git a/src/test/scala/chiselTests/GCD.scala b/src/test/scala/chiselTests/GCD.scala index 8c298d14..21082fc9 100644 --- a/src/test/scala/chiselTests/GCD.scala +++ b/src/test/scala/chiselTests/GCD.scala @@ -6,7 +6,7 @@ import chisel3._ import chisel3.testers.BasicTester import org.scalatest._ import org.scalatest.prop._ -import chisel3.NotStrict.NotStrictCompileOptions +import chisel3.NotStrict.CompileOptions class GCD extends Module { val io = IO(new Bundle { diff --git a/src/test/scala/chiselTests/IOCompatibility.scala b/src/test/scala/chiselTests/IOCompatibility.scala index c247973d..aa3bd962 100644 --- a/src/test/scala/chiselTests/IOCompatibility.scala +++ b/src/test/scala/chiselTests/IOCompatibility.scala @@ -3,7 +3,7 @@ package chiselTests import Chisel._ -import chisel3.NotStrict.NotStrictCompileOptions +import chisel3.NotStrict.CompileOptions class IOCSimpleIO extends Bundle { val in = UInt(INPUT, 32) diff --git a/src/test/scala/chiselTests/LFSR16.scala b/src/test/scala/chiselTests/LFSR16.scala index b1b2b415..3b2b28f6 100644 --- a/src/test/scala/chiselTests/LFSR16.scala +++ b/src/test/scala/chiselTests/LFSR16.scala @@ -5,7 +5,7 @@ package chiselTests import chisel3._ import chisel3.testers.BasicTester import chisel3.util._ -import chisel3.NotStrict.NotStrictCompileOptions +import chisel3.NotStrict.CompileOptions class LFSR16 extends Module { val io = IO(new Bundle { diff --git a/src/test/scala/chiselTests/MemorySearch.scala b/src/test/scala/chiselTests/MemorySearch.scala index b05a112b..a2a8eb8b 100644 --- a/src/test/scala/chiselTests/MemorySearch.scala +++ b/src/test/scala/chiselTests/MemorySearch.scala @@ -4,7 +4,7 @@ package chiselTests import chisel3._ import chisel3.testers.BasicTester -import chisel3.NotStrict.NotStrictCompileOptions +import chisel3.NotStrict.CompileOptions class MemorySearch extends Module { val io = IO(new Bundle { diff --git a/src/test/scala/chiselTests/Module.scala b/src/test/scala/chiselTests/Module.scala index 8d72fc44..1f0ab084 100644 --- a/src/test/scala/chiselTests/Module.scala +++ b/src/test/scala/chiselTests/Module.scala @@ -3,7 +3,7 @@ package chiselTests import chisel3._ -import chisel3.NotStrict.NotStrictCompileOptions +import chisel3.NotStrict.CompileOptions class SimpleIO extends Bundle { val in = Input(UInt.width(32)) diff --git a/src/test/scala/chiselTests/MulLookup.scala b/src/test/scala/chiselTests/MulLookup.scala index 63a0a7c7..4548ae40 100644 --- a/src/test/scala/chiselTests/MulLookup.scala +++ b/src/test/scala/chiselTests/MulLookup.scala @@ -6,7 +6,7 @@ import chisel3._ import org.scalatest._ import org.scalatest.prop._ import chisel3.testers.BasicTester -import chisel3.NotStrict.NotStrictCompileOptions +import chisel3.NotStrict.CompileOptions class MulLookup(val w: Int) extends Module { val io = IO(new Bundle { diff --git a/src/test/scala/chiselTests/OptionBundle.scala b/src/test/scala/chiselTests/OptionBundle.scala index 236e1007..d2165f62 100644 --- a/src/test/scala/chiselTests/OptionBundle.scala +++ b/src/test/scala/chiselTests/OptionBundle.scala @@ -5,7 +5,7 @@ package chiselTests import org.scalatest._ import chisel3._ import chisel3.testers.BasicTester -import chisel3.NotStrict.NotStrictCompileOptions +import chisel3.NotStrict.CompileOptions 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 ca769b49..c7265c6c 100644 --- a/src/test/scala/chiselTests/Padding.scala +++ b/src/test/scala/chiselTests/Padding.scala @@ -3,7 +3,7 @@ package chiselTests import chisel3._ -import chisel3.NotStrict.NotStrictCompileOptions +import chisel3.NotStrict.CompileOptions class Padder extends Module { val io = IO(new Bundle { diff --git a/src/test/scala/chiselTests/ParameterizedModule.scala b/src/test/scala/chiselTests/ParameterizedModule.scala index 2929cccc..b75d898b 100644 --- a/src/test/scala/chiselTests/ParameterizedModule.scala +++ b/src/test/scala/chiselTests/ParameterizedModule.scala @@ -5,7 +5,7 @@ package chiselTests import org.scalatest._ import chisel3._ import chisel3.testers.BasicTester -import chisel3.NotStrict.NotStrictCompileOptions +import chisel3.NotStrict.CompileOptions class ParameterizedModule(invert: Boolean) extends Module { val io = IO(new Bundle { diff --git a/src/test/scala/chiselTests/Risc.scala b/src/test/scala/chiselTests/Risc.scala index f255f996..e27cbdca 100644 --- a/src/test/scala/chiselTests/Risc.scala +++ b/src/test/scala/chiselTests/Risc.scala @@ -4,7 +4,7 @@ package chiselTests import chisel3._ import chisel3.util._ -import chisel3.NotStrict.NotStrictCompileOptions +import chisel3.NotStrict.CompileOptions class Risc extends Module { val io = IO(new Bundle { diff --git a/src/test/scala/chiselTests/SIntOps.scala b/src/test/scala/chiselTests/SIntOps.scala index 227a4514..d070295c 100644 --- a/src/test/scala/chiselTests/SIntOps.scala +++ b/src/test/scala/chiselTests/SIntOps.scala @@ -4,7 +4,7 @@ package chiselTests import chisel3._ import chisel3.testers.BasicTester -import chisel3.NotStrict.NotStrictCompileOptions +import chisel3.NotStrict.CompileOptions class SIntOps extends Module { val io = IO(new Bundle { diff --git a/src/test/scala/chiselTests/Stack.scala b/src/test/scala/chiselTests/Stack.scala index 9ccfc9ee..f1210260 100644 --- a/src/test/scala/chiselTests/Stack.scala +++ b/src/test/scala/chiselTests/Stack.scala @@ -6,7 +6,7 @@ import scala.collection.mutable.Stack import chisel3._ import chisel3.util._ -import chisel3.NotStrict.NotStrictCompileOptions +import chisel3.NotStrict.CompileOptions class ChiselStack(val depth: Int) extends Module { val io = IO(new Bundle { diff --git a/src/test/scala/chiselTests/Tbl.scala b/src/test/scala/chiselTests/Tbl.scala index 2aa8b031..df8ce02c 100644 --- a/src/test/scala/chiselTests/Tbl.scala +++ b/src/test/scala/chiselTests/Tbl.scala @@ -8,7 +8,7 @@ import org.scalatest.prop._ import chisel3._ import chisel3.testers.BasicTester import chisel3.util._ -import chisel3.NotStrict.NotStrictCompileOptions +import chisel3.NotStrict.CompileOptions class Tbl(w: Int, n: Int) extends Module { val io = IO(new Bundle { diff --git a/src/test/scala/chiselTests/UIntOps.scala b/src/test/scala/chiselTests/UIntOps.scala index 836ad864..237cea16 100644 --- a/src/test/scala/chiselTests/UIntOps.scala +++ b/src/test/scala/chiselTests/UIntOps.scala @@ -5,7 +5,7 @@ package chiselTests import chisel3._ import org.scalatest._ import chisel3.testers.BasicTester -import chisel3.NotStrict.NotStrictCompileOptions +import chisel3.NotStrict.CompileOptions class UIntOps extends Module { val io = IO(new Bundle { diff --git a/src/test/scala/chiselTests/VectorPacketIO.scala b/src/test/scala/chiselTests/VectorPacketIO.scala index 66b599a9..588e1ce2 100644 --- a/src/test/scala/chiselTests/VectorPacketIO.scala +++ b/src/test/scala/chiselTests/VectorPacketIO.scala @@ -5,7 +5,7 @@ package chiselTests import chisel3._ import chisel3.testers.BasicTester import chisel3.util._ -import chisel3.NotStrict.NotStrictCompileOptions +import chisel3.NotStrict.CompileOptions /** * 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 89060941..2a0ac824 100644 --- a/src/test/scala/chiselTests/VendingMachine.scala +++ b/src/test/scala/chiselTests/VendingMachine.scala @@ -4,7 +4,7 @@ package chiselTests import chisel3._ import chisel3.util._ -import chisel3.NotStrict.NotStrictCompileOptions +import chisel3.NotStrict.CompileOptions class VendingMachine extends Module { val io = IO(new Bundle { -- cgit v1.2.3 From 1973e4d7333e2c57be4bcb7204210ecafdacab93 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Mon, 29 Aug 2016 17:04:51 -0700 Subject: Check module-specific compile options. Import chisel3.NotStrict.CompileOptions in Chisel package. Add CompileOptions tests. --- .../src/main/scala/chisel3/core/BiConnect.scala | 12 +- .../src/main/scala/chisel3/core/Binding.scala | 6 +- .../src/main/scala/chisel3/core/MonoConnect.scala | 8 +- .../src/main/scala/chisel3/core/Reg.scala | 2 +- src/main/scala/chisel3/compatibility.scala | 1 + .../scala/chiselTests/CompileOptionsTest.scala | 180 +++++++++++++++++++++ 6 files changed, 196 insertions(+), 13 deletions(-) create mode 100644 src/test/scala/chiselTests/CompileOptionsTest.scala diff --git a/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala b/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala index 857b25aa..969e5654 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala @@ -1,3 +1,5 @@ +// See LICENSE for license details. + package chisel3.core import chisel3.internal.Builder.{compileOptions, pushCommand} @@ -70,7 +72,7 @@ object BiConnect { // Verify right has no extra fields that left doesn't have for((field, right_sub) <- right_b.elements) { if(!left_b.elements.isDefinedAt(field)) { - if (compileOptions.connectFieldsMustMatch) { + if (compileOptions.connectFieldsMustMatch || context_mod.compileOptions.connectFieldsMustMatch) { throw MissingLeftFieldException(field) } } @@ -81,7 +83,7 @@ object BiConnect { right_b.elements.get(field) match { case Some(right_sub) => connect(sourceInfo, left_sub, right_sub, context_mod) case None => { - if (compileOptions.connectFieldsMustMatch) { + if (compileOptions.connectFieldsMustMatch || context_mod.compileOptions.connectFieldsMustMatch) { throw MissingRightFieldException(field) } } @@ -167,7 +169,7 @@ object BiConnect { case (None, Some(Input)) => issueConnectR2L(left, right) case (Some(Input), Some(Input)) => { - if (compileOptions.dontAssumeDirectionality) { + if (compileOptions.dontAssumeDirectionality || context_mod.compileOptions.dontAssumeDirectionality) { throw BothDriversException } else { (left.binding, right.binding) match { @@ -179,7 +181,7 @@ object BiConnect { } } case (Some(Output), Some(Output)) => { - if (compileOptions.dontAssumeDirectionality) { + if (compileOptions.dontAssumeDirectionality || context_mod.compileOptions.dontAssumeDirectionality) { throw BothDriversException } else { (left.binding, right.binding) match { @@ -191,7 +193,7 @@ object BiConnect { } } case (None, None) => { - if (compileOptions.dontAssumeDirectionality) { + if (compileOptions.dontAssumeDirectionality || context_mod.compileOptions.dontAssumeDirectionality) { throw UnknownDriverException } else { issueConnectR2L(left, right) diff --git a/chiselFrontend/src/main/scala/chisel3/core/Binding.scala b/chiselFrontend/src/main/scala/chisel3/core/Binding.scala index a32d3ade..b36794f1 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Binding.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Binding.scala @@ -1,6 +1,6 @@ package chisel3.core -import chisel3.internal.Builder.compileOptions +import chisel3.internal.Builder.{compileOptions, forcedModule} /** * The purpose of a Binding is to indicate what type of hardware 'entity' a @@ -91,7 +91,7 @@ object Binding { element.binding = binder(unbound) } // If autoIOWrap is enabled and we're rebinding a PortBinding, just ignore the rebinding. - case portBound @ PortBinding(_, _) if (!compileOptions.requireIOWrap && binder.isInstanceOf[PortBinder]) => + case portBound @ PortBinding(_, _) if (!(compileOptions.requireIOWrap || forcedModule.compileOptions.requireIOWrap)&& binder.isInstanceOf[PortBinder]) => case binding => throw AlreadyBoundException(binding.toString) } ) @@ -145,7 +145,7 @@ object Binding { case binding => // The following kludge is an attempt to provide backward compatibility // It should be done at at higher level. - if ((compileOptions.requireIOWrap || !elementOfIO(element))) + if ((compileOptions.requireIOWrap || forcedModule.compileOptions.requireIOWrap || !elementOfIO(element))) throw NotSynthesizableException else Binding.bind(element, PortBinder(element._parent.get), "Error: IO") diff --git a/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala b/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala index 66729bac..41754827 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala @@ -79,7 +79,7 @@ object MonoConnect { source_b.elements.get(field) match { case Some(source_sub) => connect(sourceInfo, sink_sub, source_sub, context_mod) case None => { - if (compileOptions.connectFieldsMustMatch) { + if (compileOptions.connectFieldsMustMatch || context_mod.compileOptions.connectFieldsMustMatch) { throw MissingFieldException(field) } } @@ -134,13 +134,13 @@ object MonoConnect { case (Some(Output), Some(Output)) => issueConnect(sink, source) case (Some(Output), Some(Input)) => issueConnect(sink, source) case (_, None) => { - if (!compileOptions.dontAssumeDirectionality) { + if (!(compileOptions.dontAssumeDirectionality || context_mod.compileOptions.dontAssumeDirectionality)) { issueConnect(sink, source) } else { throw UnreadableSourceException } } - case (Some(Input), Some(Output)) if (!compileOptions.dontTryConnectionsSwapped) => issueConnect(source, sink) + case (Some(Input), Some(Output)) if (!(compileOptions.dontTryConnectionsSwapped || context_mod.compileOptions.dontTryConnectionsSwapped)) => issueConnect(source, sink) case (Some(Input), _) => throw UnwritableSinkException } } @@ -172,7 +172,7 @@ object MonoConnect { case (Some(Input), Some(Output)) => issueConnect(sink, source) case (Some(Output), _) => throw UnwritableSinkException case (_, None) => { - if (!compileOptions.dontAssumeDirectionality) { + if (!(compileOptions.dontAssumeDirectionality || context_mod.compileOptions.dontAssumeDirectionality)) { issueConnect(sink, source) } else { throw UnreadableSourceException diff --git a/chiselFrontend/src/main/scala/chisel3/core/Reg.scala b/chiselFrontend/src/main/scala/chisel3/core/Reg.scala index b77c9a31..36c88245 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Reg.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Reg.scala @@ -10,7 +10,7 @@ import chisel3.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) { - if (Builder.compileOptions.declaredTypeMustBeUnbound) { + if (Builder.compileOptions.declaredTypeMustBeUnbound || Builder.forcedModule.compileOptions.declaredTypeMustBeUnbound) { Binding.checkUnbound(t, s"t ($t) must be unbound Type. Try using cloneType?") } t.chiselCloneType diff --git a/src/main/scala/chisel3/compatibility.scala b/src/main/scala/chisel3/compatibility.scala index 35c44330..8524ea2a 100644 --- a/src/main/scala/chisel3/compatibility.scala +++ b/src/main/scala/chisel3/compatibility.scala @@ -4,6 +4,7 @@ // moving to the more standard package naming convention chisel3 (lowercase c). package object Chisel { // scalastyle:ignore package.object.name + import chisel3.NotStrict.CompileOptions type Direction = chisel3.core.Direction val INPUT = chisel3.core.Direction.Input val OUTPUT = chisel3.core.Direction.Output diff --git a/src/test/scala/chiselTests/CompileOptionsTest.scala b/src/test/scala/chiselTests/CompileOptionsTest.scala new file mode 100644 index 00000000..5bd3f959 --- /dev/null +++ b/src/test/scala/chiselTests/CompileOptionsTest.scala @@ -0,0 +1,180 @@ +// See LICENSE for license details. + +package chiselTests + +import org.scalatest._ +import chisel3._ +import chisel3.core.Binding.BindingException +import chisel3.testers.BasicTester + +class CompileOptionsSpec extends ChiselFlatSpec { + + class SmallBundle extends Bundle { + val f1 = UInt(width = 4) + val f2 = UInt(width = 5) + override def cloneType: this.type = (new SmallBundle).asInstanceOf[this.type] + } + class BigBundle extends SmallBundle { + val f3 = UInt(width = 6) + override def cloneType: this.type = (new BigBundle).asInstanceOf[this.type] + } + + "A Module with missing bundle fields when compiled with Strict.CompileOption " should "throw an exception" in { + a [ChiselException] should be thrownBy { + import chisel3.Strict.CompileOptions + + class ConnectFieldMismatchModule extends Module { + val io = IO(new Bundle { + val in = Input(new SmallBundle) + val out = Output(new BigBundle) + }) + io.out := io.in + } + elaborate { new ConnectFieldMismatchModule() } + } + } + + "A Module with missing bundle fields when compiled with NotStrict.CompileOption " should "not throw an exception" in { + import chisel3.NotStrict.CompileOptions + + class ConnectFieldMismatchModule extends Module { + val io = IO(new Bundle { + val in = Input(new SmallBundle) + val out = Output(new BigBundle) + }) + io.out := io.in + } + elaborate { new ConnectFieldMismatchModule() } + } + + "A Module in which a Reg is created with a bound type when compiled with Strict.CompileOption " should "throw an exception" in { + a [BindingException] should be thrownBy { + import chisel3.Strict.CompileOptions + + class CreateRegFromBoundTypeModule extends Module { + val io = IO(new Bundle { + val in = Input(new SmallBundle) + val out = Output(new BigBundle) + }) + val badReg = Reg(UInt(7, width=4)) + } + elaborate { new CreateRegFromBoundTypeModule() } + } + } + + "A Module in which a Reg is created with a bound type when compiled with NotStrict.CompileOption " should "not throw an exception" in { + import chisel3.NotStrict.CompileOptions + + class CreateRegFromBoundTypeModule extends Module { + val io = IO(new Bundle { + val in = Input(new SmallBundle) + val out = Output(new BigBundle) + }) + val badReg = Reg(UInt(7, width=4)) + } + elaborate { new CreateRegFromBoundTypeModule() } + } + + + "A Module with wrapped IO when compiled with Strict.CompileOption " should "not throw an exception" in { + import chisel3.Strict.CompileOptions + + class RequireIOWrapModule extends Module { + val io = IO(new Bundle { + val in = UInt(width = 32).asInput + val out = Bool().asOutput + }) + io.out := io.in(1) + } + elaborate { new RequireIOWrapModule() } +} + + "A Module with unwrapped IO when compiled with NotStrict.CompileOption " should "not throw an exception" in { + import chisel3.NotStrict.CompileOptions + + class RequireIOWrapModule extends Module { + val io = new Bundle { + val in = UInt(width = 32).asInput + val out = Bool().asOutput + } + io.out := io.in(1) + } + elaborate { new RequireIOWrapModule() } + } + + "A Module connecting output as source to input as sink when compiled with Strict.CompileOption " should "throw an exception" in { + a [ChiselException] should be thrownBy { + import chisel3.Strict.CompileOptions + + class SimpleModule extends Module { + val io = IO(new Bundle { + val in = Input(UInt(width = 3)) + val out = Output(UInt(width = 4)) + }) + } + class SwappedConnectionModule extends SimpleModule { + val child = Module(new SimpleModule) + io.in := child.io.out + } + elaborate { new SwappedConnectionModule() } + } + } + + "A Module connecting output as source to input as sink when compiled with NotStrict.CompileOption " should "not throw an exception" in { + import chisel3.NotStrict.CompileOptions + + class SimpleModule extends Module { + val io = IO(new Bundle { + val in = Input(UInt(width = 3)) + val out = Output(UInt(width = 4)) + }) + } + class SwappedConnectionModule extends SimpleModule { + val child = Module(new SimpleModule) + io.in := child.io.out + } + elaborate { new SwappedConnectionModule() } + } + + "A Module with directionless connections when compiled with Strict.CompileOption " should "throw an exception" in { + a [ChiselException] should be thrownBy { + import chisel3.Strict.CompileOptions + + class SimpleModule extends Module { + val io = IO(new Bundle { + val in = Input(UInt(width = 3)) + val out = Output(UInt(width = 4)) + }) + val noDir = Wire(UInt(width = 3)) + } + + class DirectionLessConnectionModule extends SimpleModule { + val a = UInt(0, width = 3) + val b = Wire(UInt(width = 3)) + val child = Module(new SimpleModule) + b := child.noDir + } + elaborate { new DirectionLessConnectionModule() } + } + } + + "A Module with directionless connections when compiled with NotStrict.CompileOption " should "not throw an exception" in { + import chisel3.NotStrict.CompileOptions + + class SimpleModule extends Module { + val io = IO(new Bundle { + val in = Input(UInt(width = 3)) + val out = Output(UInt(width = 4)) + }) + val noDir = Wire(UInt(width = 3)) + } + + class DirectionLessConnectionModule extends SimpleModule { + val a = UInt(0, width = 3) + val b = Wire(UInt(width = 3)) + val child = Module(new SimpleModule) + b := child.noDir + } + elaborate { new DirectionLessConnectionModule() } + } +} -- cgit v1.2.3 From d4375d8c7a380d8002b7d9e79f53883e46279cd9 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Tue, 30 Aug 2016 08:49:52 -0700 Subject: Correct parameter name (topModule) in ScalaDoc. --- src/main/scala/chisel3/Driver.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/chisel3/Driver.scala b/src/main/scala/chisel3/Driver.scala index 0979314f..20a43636 100644 --- a/src/main/scala/chisel3/Driver.scala +++ b/src/main/scala/chisel3/Driver.scala @@ -47,7 +47,7 @@ trait BackendCompilationUtilities { * 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 topModule 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 -- cgit v1.2.3 From 98e35eb6b46b144e3daec78e21e807769e6db505 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Tue, 30 Aug 2016 08:50:52 -0700 Subject: Allow compileOptions as optional arguments to elaborate() and emit(). --- src/main/scala/chisel3/Driver.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/chisel3/Driver.scala b/src/main/scala/chisel3/Driver.scala index 20a43636..8efb529d 100644 --- a/src/main/scala/chisel3/Driver.scala +++ b/src/main/scala/chisel3/Driver.scala @@ -108,9 +108,9 @@ object Driver extends BackendCompilationUtilities { * @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 elaborate[T <: Module](gen: () => T, moduleCompileOptions: Option[ExplicitCompileOptions] = None): Circuit = Builder.build(Module(gen()), moduleCompileOptions) - def emit[T <: Module](gen: () => T): String = Emitter.emit(elaborate(gen)) + def emit[T <: Module](gen: () => T, moduleCompileOptions: Option[ExplicitCompileOptions] = None): String = Emitter.emit(elaborate(gen, moduleCompileOptions)) def dumpFirrtl(ir: Circuit, optName: Option[File]): File = { val f = optName.getOrElse(new File(ir.name + ".fir")) -- cgit v1.2.3 From 5df671531c4a83dc17ecfdce6aecc8789d50fa7f Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Tue, 30 Aug 2016 09:18:35 -0700 Subject: Add abstract classes with explicit connection checking options. --- .../scala/chiselTests/CompileOptionsTest.scala | 81 +++++++++++++++++++--- 1 file changed, 70 insertions(+), 11 deletions(-) diff --git a/src/test/scala/chiselTests/CompileOptionsTest.scala b/src/test/scala/chiselTests/CompileOptionsTest.scala index 5bd3f959..5b27bf90 100644 --- a/src/test/scala/chiselTests/CompileOptionsTest.scala +++ b/src/test/scala/chiselTests/CompileOptionsTest.scala @@ -9,6 +9,9 @@ import chisel3.testers.BasicTester class CompileOptionsSpec extends ChiselFlatSpec { + abstract class StrictModule extends Module()(chisel3.Strict.CompileOptions) + abstract class NotStrictModule extends Module()(chisel3.NotStrict.CompileOptions) + class SmallBundle extends Bundle { val f1 = UInt(width = 4) val f2 = UInt(width = 5) @@ -19,7 +22,7 @@ class CompileOptionsSpec extends ChiselFlatSpec { override def cloneType: this.type = (new BigBundle).asInstanceOf[this.type] } - "A Module with missing bundle fields when compiled with Strict.CompileOption " should "throw an exception" in { + "A Module with missing bundle fields when compiled with implicit Strict.CompileOption " should "throw an exception" in { a [ChiselException] should be thrownBy { import chisel3.Strict.CompileOptions @@ -34,7 +37,7 @@ class CompileOptionsSpec extends ChiselFlatSpec { } } - "A Module with missing bundle fields when compiled with NotStrict.CompileOption " should "not throw an exception" in { + "A Module with missing bundle fields when compiled with implicit NotStrict.CompileOption " should "not throw an exception" in { import chisel3.NotStrict.CompileOptions class ConnectFieldMismatchModule extends Module { @@ -47,7 +50,7 @@ class CompileOptionsSpec extends ChiselFlatSpec { elaborate { new ConnectFieldMismatchModule() } } - "A Module in which a Reg is created with a bound type when compiled with Strict.CompileOption " should "throw an exception" in { + "A Module in which a Reg is created with a bound type when compiled with implicit Strict.CompileOption " should "throw an exception" in { a [BindingException] should be thrownBy { import chisel3.Strict.CompileOptions @@ -62,7 +65,7 @@ class CompileOptionsSpec extends ChiselFlatSpec { } } - "A Module in which a Reg is created with a bound type when compiled with NotStrict.CompileOption " should "not throw an exception" in { + "A Module in which a Reg is created with a bound type when compiled with implicit NotStrict.CompileOption " should "not throw an exception" in { import chisel3.NotStrict.CompileOptions class CreateRegFromBoundTypeModule extends Module { @@ -75,8 +78,7 @@ class CompileOptionsSpec extends ChiselFlatSpec { elaborate { new CreateRegFromBoundTypeModule() } } - - "A Module with wrapped IO when compiled with Strict.CompileOption " should "not throw an exception" in { + "A Module with wrapped IO when compiled with implicit Strict.CompileOption " should "not throw an exception" in { import chisel3.Strict.CompileOptions class RequireIOWrapModule extends Module { @@ -89,7 +91,7 @@ class CompileOptionsSpec extends ChiselFlatSpec { elaborate { new RequireIOWrapModule() } } - "A Module with unwrapped IO when compiled with NotStrict.CompileOption " should "not throw an exception" in { + "A Module with unwrapped IO when compiled with implicit NotStrict.CompileOption " should "not throw an exception" in { import chisel3.NotStrict.CompileOptions class RequireIOWrapModule extends Module { @@ -102,7 +104,24 @@ class CompileOptionsSpec extends ChiselFlatSpec { elaborate { new RequireIOWrapModule() } } - "A Module connecting output as source to input as sink when compiled with Strict.CompileOption " should "throw an exception" in { + "A Module with unwrapped IO when compiled with implicit Strict.CompileOption " should "throw an exception" in { + a [BindingException] should be thrownBy { + import chisel3.Strict.CompileOptions + + class RequireIOWrapModule extends Module { + val io = new Bundle { + val in = UInt(width = 32).asInput + val out = Bool().asOutput + } + io.out := io.in(1) + } + elaborate { + new RequireIOWrapModule() + } + } + } + + "A Module connecting output as source to input as sink when compiled with implicit Strict.CompileOption " should "throw an exception" in { a [ChiselException] should be thrownBy { import chisel3.Strict.CompileOptions @@ -120,7 +139,7 @@ class CompileOptionsSpec extends ChiselFlatSpec { } } - "A Module connecting output as source to input as sink when compiled with NotStrict.CompileOption " should "not throw an exception" in { + "A Module connecting output as source to input as sink when compiled with implicit NotStrict.CompileOption " should "not throw an exception" in { import chisel3.NotStrict.CompileOptions class SimpleModule extends Module { @@ -136,7 +155,7 @@ class CompileOptionsSpec extends ChiselFlatSpec { elaborate { new SwappedConnectionModule() } } - "A Module with directionless connections when compiled with Strict.CompileOption " should "throw an exception" in { + "A Module with directionless connections when compiled with implicit Strict.CompileOption " should "throw an exception" in { a [ChiselException] should be thrownBy { import chisel3.Strict.CompileOptions @@ -158,7 +177,7 @@ class CompileOptionsSpec extends ChiselFlatSpec { } } - "A Module with directionless connections when compiled with NotStrict.CompileOption " should "not throw an exception" in { + "A Module with directionless connections when compiled with implicit NotStrict.CompileOption " should "not throw an exception" in { import chisel3.NotStrict.CompileOptions class SimpleModule extends Module { @@ -177,4 +196,44 @@ class CompileOptionsSpec extends ChiselFlatSpec { } elaborate { new DirectionLessConnectionModule() } } + + "A Module with wrapped IO when compiled with explicit Strict.CompileOption " should "not throw an exception" in { + + class RequireIOWrapModule extends StrictModule { + val io = IO(new Bundle { + val in = UInt(width = 32).asInput + val out = Bool().asOutput + }) + io.out := io.in(1) + } + elaborate { new RequireIOWrapModule() } + } + + "A Module with unwrapped IO when compiled with explicit NotStrict.CompileOption " should "not throw an exception" in { + + class RequireIOWrapModule extends NotStrictModule { + val io = new Bundle { + val in = UInt(width = 32).asInput + val out = Bool().asOutput + } + io.out := io.in(1) + } + elaborate { new RequireIOWrapModule() } + } + + "A Module with unwrapped IO when compiled with explicit Strict.CompileOption " should "throw an exception" in { + a [BindingException] should be thrownBy { + + class RequireIOWrapModule extends StrictModule { + val io = new Bundle { + val in = UInt(width = 32).asInput + val out = Bool().asOutput + } + io.out := io.in(1) + } + elaborate { + new RequireIOWrapModule() + } + } + } } -- cgit v1.2.3 From 55719f690e637700579867edb8f90fae4d3a42ef Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Tue, 30 Aug 2016 10:08:44 -0700 Subject: Use correct case for Strict/NotStrict compile options. --- chiselFrontend/src/main/scala/chisel3/NotStrict.scala | 16 ++++++++++++++++ chiselFrontend/src/main/scala/chisel3/Strict.scala | 16 ++++++++++++++++ chiselFrontend/src/main/scala/chisel3/notstrict.scala | 16 ---------------- chiselFrontend/src/main/scala/chisel3/strict.scala | 16 ---------------- 4 files changed, 32 insertions(+), 32 deletions(-) create mode 100644 chiselFrontend/src/main/scala/chisel3/NotStrict.scala create mode 100644 chiselFrontend/src/main/scala/chisel3/Strict.scala delete mode 100644 chiselFrontend/src/main/scala/chisel3/notstrict.scala delete mode 100644 chiselFrontend/src/main/scala/chisel3/strict.scala diff --git a/chiselFrontend/src/main/scala/chisel3/NotStrict.scala b/chiselFrontend/src/main/scala/chisel3/NotStrict.scala new file mode 100644 index 00000000..bb390e7c --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel3/NotStrict.scala @@ -0,0 +1,16 @@ +// See LICENSE for license details. + +package chisel3 + +import chisel3.internal.ExplicitCompileOptions + + +object NotStrict { + implicit object CompileOptions extends ExplicitCompileOptions { + val connectFieldsMustMatch = false + val declaredTypeMustBeUnbound = false + val requireIOWrap = false + val dontTryConnectionsSwapped = false + val dontAssumeDirectionality = false + } +} diff --git a/chiselFrontend/src/main/scala/chisel3/Strict.scala b/chiselFrontend/src/main/scala/chisel3/Strict.scala new file mode 100644 index 00000000..70240429 --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel3/Strict.scala @@ -0,0 +1,16 @@ +// See LICENSE for license details. + +package chisel3 + +import chisel3.internal.ExplicitCompileOptions + + +object Strict { + implicit object CompileOptions extends ExplicitCompileOptions { + val connectFieldsMustMatch = true + val declaredTypeMustBeUnbound = true + val requireIOWrap = true + val dontTryConnectionsSwapped = true + val dontAssumeDirectionality = true + } +} diff --git a/chiselFrontend/src/main/scala/chisel3/notstrict.scala b/chiselFrontend/src/main/scala/chisel3/notstrict.scala deleted file mode 100644 index bb390e7c..00000000 --- a/chiselFrontend/src/main/scala/chisel3/notstrict.scala +++ /dev/null @@ -1,16 +0,0 @@ -// See LICENSE for license details. - -package chisel3 - -import chisel3.internal.ExplicitCompileOptions - - -object NotStrict { - implicit object CompileOptions extends ExplicitCompileOptions { - val connectFieldsMustMatch = false - val declaredTypeMustBeUnbound = false - val requireIOWrap = false - val dontTryConnectionsSwapped = false - val dontAssumeDirectionality = false - } -} diff --git a/chiselFrontend/src/main/scala/chisel3/strict.scala b/chiselFrontend/src/main/scala/chisel3/strict.scala deleted file mode 100644 index 70240429..00000000 --- a/chiselFrontend/src/main/scala/chisel3/strict.scala +++ /dev/null @@ -1,16 +0,0 @@ -// See LICENSE for license details. - -package chisel3 - -import chisel3.internal.ExplicitCompileOptions - - -object Strict { - implicit object CompileOptions extends ExplicitCompileOptions { - val connectFieldsMustMatch = true - val declaredTypeMustBeUnbound = true - val requireIOWrap = true - val dontTryConnectionsSwapped = true - val dontAssumeDirectionality = true - } -} -- cgit v1.2.3 From 1379a192ca1f6c05aeba454b81e19fb8356e6cf3 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Tue, 30 Aug 2016 10:17:18 -0700 Subject: Add example of specific CompileOptions settings to tests. --- .../scala/chiselTests/CompileOptionsTest.scala | 26 ++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/test/scala/chiselTests/CompileOptionsTest.scala b/src/test/scala/chiselTests/CompileOptionsTest.scala index 5b27bf90..70843c3e 100644 --- a/src/test/scala/chiselTests/CompileOptionsTest.scala +++ b/src/test/scala/chiselTests/CompileOptionsTest.scala @@ -5,6 +5,7 @@ package chiselTests import org.scalatest._ import chisel3._ import chisel3.core.Binding.BindingException +import chisel3.internal.ExplicitCompileOptions import chisel3.testers.BasicTester class CompileOptionsSpec extends ChiselFlatSpec { @@ -236,4 +237,29 @@ class CompileOptionsSpec extends ChiselFlatSpec { } } } + + "A Module with unwrapped IO when compiled with an explicit requireIOWrap false " should "not throw an exception" in { + + object StrictNotIOWrap { + + implicit object CompileOptions extends ExplicitCompileOptions { + val connectFieldsMustMatch = true + val declaredTypeMustBeUnbound = true + val requireIOWrap = false + val dontTryConnectionsSwapped = true + val dontAssumeDirectionality = true + } + + } + class NotIOWrapModule extends Module()(StrictNotIOWrap.CompileOptions) { + val io = new Bundle { + val in = UInt(width = 32).asInput + val out = Bool().asOutput + } + io.out := io.in(1) + } + elaborate { + new NotIOWrapModule() + } + } } -- cgit v1.2.3 From 000bba093609b74d0dbbc73490edac9ed756aa65 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Tue, 30 Aug 2016 13:28:42 -0700 Subject: Explicitly clone the target type in noenq() to avoid "already bound" errors for io ports. --- src/main/scala/chisel3/util/Decoupled.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/scala/chisel3/util/Decoupled.scala b/src/main/scala/chisel3/util/Decoupled.scala index 63831d2f..5ce2583c 100644 --- a/src/main/scala/chisel3/util/Decoupled.scala +++ b/src/main/scala/chisel3/util/Decoupled.scala @@ -40,7 +40,8 @@ object DecoupledIO { */ def noenq(): Unit = { target.valid := Bool(false) - target.bits := target.bits.fromBits(0.asUInt) + // We want the type from the following, not any existing binding. + target.bits := target.bits.cloneType.fromBits(0.asUInt) } /** Assert ready on this port and return the associated data bits. -- cgit v1.2.3 From 8002f7ac6731b1da5e0d8e7b1536995a23878037 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Tue, 30 Aug 2016 13:45:37 -0700 Subject: Make compileOptions in the Chisel package effective. Remove references to the Chisel package in favor of explicit chisel3 imports in tests, --- src/main/scala/chisel3/compatibility.scala | 2 +- src/test/scala/chiselTests/BetterNamingTests.scala | 3 ++- src/test/scala/chiselTests/IOCompatibility.scala | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/scala/chisel3/compatibility.scala b/src/main/scala/chisel3/compatibility.scala index 8524ea2a..85311ba2 100644 --- a/src/main/scala/chisel3/compatibility.scala +++ b/src/main/scala/chisel3/compatibility.scala @@ -4,7 +4,7 @@ // moving to the more standard package naming convention chisel3 (lowercase c). package object Chisel { // scalastyle:ignore package.object.name - import chisel3.NotStrict.CompileOptions + implicit val compileOptions = chisel3.NotStrict.CompileOptions type Direction = chisel3.core.Direction val INPUT = chisel3.core.Direction.Input val OUTPUT = chisel3.core.Direction.Output diff --git a/src/test/scala/chiselTests/BetterNamingTests.scala b/src/test/scala/chiselTests/BetterNamingTests.scala index a480da98..98ca0306 100644 --- a/src/test/scala/chiselTests/BetterNamingTests.scala +++ b/src/test/scala/chiselTests/BetterNamingTests.scala @@ -3,7 +3,8 @@ package chiselTests import org.scalatest.{FlatSpec, Matchers} import collection.mutable -import Chisel._ +import chisel3._ +import chisel3.util._ import chisel3.NotStrict.CompileOptions diff --git a/src/test/scala/chiselTests/IOCompatibility.scala b/src/test/scala/chiselTests/IOCompatibility.scala index aa3bd962..d100df2b 100644 --- a/src/test/scala/chiselTests/IOCompatibility.scala +++ b/src/test/scala/chiselTests/IOCompatibility.scala @@ -2,7 +2,7 @@ package chiselTests -import Chisel._ +import chisel3._ import chisel3.NotStrict.CompileOptions class IOCSimpleIO extends Bundle { -- cgit v1.2.3 From e2c76e1b752cb332d6c3b23dd224db14951c7e72 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Wed, 31 Aug 2016 08:42:39 -0700 Subject: Bump version number in preparation for release. --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index f2074fca..02a0e9f5 100644 --- a/build.sbt +++ b/build.sbt @@ -8,7 +8,7 @@ ghpages.settings lazy val commonSettings = Seq ( organization := "edu.berkeley.cs", - version := "3.0", + version := "3.1-SNAPSHOT", git.remoteRepo := "git@github.com:ucb-bar/chisel3.git", scalaVersion := "2.11.7" ) -- cgit v1.2.3 From 3442fac58a99551ca9e25dbc2c363c866c40e3cf Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Wed, 31 Aug 2016 19:23:11 -0700 Subject: Check that Vecs have homogeneous types Vec[Element] can have heterogeneous widths. Vec[Aggregate] cannot (but possibly could relax this by stripping widths from constituent Elements and relying on width inference). --- .../src/main/scala/chisel3/core/Aggregate.scala | 17 +++++++++++++++-- chiselFrontend/src/main/scala/chisel3/core/Bits.scala | 11 ++++++++--- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala index 82c6097f..e6ecff91 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala @@ -48,8 +48,21 @@ object Vec { // 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)) + def gen = elts.head match { + case e: Element => + // Vec[Element] must have homogeneous types, but may differ in width + for (elt <- elts.tail) + require(e.getClass == elt.getClass, + s"can't create Vec of heterogeneous types ${e.getClass} and ${elt.getClass}") + val maxWidth = elts.map(_.width).reduce(_ max _) + elts.head.cloneTypeWidth(maxWidth) + case a: Aggregate => + // Vec[Aggregate] must be homogeneous in type and width + for (elt <- elts.tail) + require(Mux.typesCompatible(a, elt), s"can't create Vec of heterogeneous types ${a.getClass} and ${elt.getClass}") + elts.head.cloneType + } + val vec = Wire(new Vec(gen, elts.length)) for ((v, e) <- vec zip elts) v := e vec diff --git a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala index 015b9dfb..44beab66 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala @@ -737,10 +737,15 @@ object Mux { pushOp(DefPrim(sourceInfo, d, MultiplexOp, cond.ref, con.ref, alt.ref)) } + private[core] def typesCompatible[T <: Data](x: T, y: T): Boolean = { + val sameTypes = x.getClass == y.getClass + val sameElements = x.flatten zip y.flatten forall { case (a, b) => a.getClass == b.getClass && a.width == b.width } + val sameNumElements = x.flatten.size == y.flatten.size + sameTypes && sameElements && sameNumElements + } + 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") + require(typesCompatible(con, alt), s"can't Mux between heterogeneous types ${con.getClass} and ${alt.getClass}") doMux(cond, con, alt) } } -- cgit v1.2.3 From 4e7e1c2b30bfa06f167b04aae4ef6944794323a9 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Wed, 31 Aug 2016 08:42:39 -0700 Subject: Bump version number in preparation for release. --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index f2074fca..02a0e9f5 100644 --- a/build.sbt +++ b/build.sbt @@ -8,7 +8,7 @@ ghpages.settings lazy val commonSettings = Seq ( organization := "edu.berkeley.cs", - version := "3.0", + version := "3.1-SNAPSHOT", git.remoteRepo := "git@github.com:ucb-bar/chisel3.git", scalaVersion := "2.11.7" ) -- cgit v1.2.3 From 4b88a5dd45337fa88178fe17324eef3661daf1b3 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Thu, 1 Sep 2016 10:21:57 -0700 Subject: Move connection implicits from Module constructor to connection methods. Eliminate builder compileOptions. --- .../src/main/scala/chisel3/core/Aggregate.scala | 23 ++++++++++++-------- .../src/main/scala/chisel3/core/BiConnect.scala | 23 ++++++++++---------- .../src/main/scala/chisel3/core/Binding.scala | 6 +++--- .../src/main/scala/chisel3/core/Bits.scala | 1 + .../src/main/scala/chisel3/core/Data.scala | 19 ++++++++-------- .../src/main/scala/chisel3/core/Mem.scala | 1 + .../src/main/scala/chisel3/core/MonoConnect.scala | 23 +++++++++++--------- .../src/main/scala/chisel3/core/Reg.scala | 14 ++++++------ .../src/main/scala/chisel3/internal/Builder.scala | 11 +++------- src/main/scala/chisel3/Driver.scala | 4 ++-- src/main/scala/chisel3/util/Counter.scala | 1 + src/main/scala/chisel3/util/LFSR.scala | 1 + src/main/scala/chisel3/util/Reg.scala | 1 + src/test/scala/chiselTests/BlackBox.scala | 1 + .../scala/chiselTests/CompileOptionsTest.scala | 25 ++++++++++++++++------ src/test/scala/chiselTests/Counter.scala | 1 + src/test/scala/chiselTests/MultiAssign.scala | 1 + src/test/scala/chiselTests/Reg.scala | 1 + src/test/scala/chiselTests/TesterDriverSpec.scala | 1 + src/test/scala/chiselTests/Vec.scala | 1 + src/test/scala/chiselTests/When.scala | 1 + 21 files changed, 95 insertions(+), 65 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala index 5d294ea9..c579d424 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala @@ -10,6 +10,7 @@ import chisel3.internal._ import chisel3.internal.Builder.pushCommand import chisel3.internal.firrtl._ import chisel3.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, VecTransform, SourceInfoTransform} +import chisel3.Strict.CompileOptions /** An abstract class for data types that solely consist of (are an aggregate * of) other Data objects. @@ -51,10 +52,12 @@ object Vec { val width = elts.map(_.width).reduce(_ max _) // If an element has a direction associated with it, use the bulk connect operator. val vec = Wire(new Vec(elts.head.cloneTypeWidth(width), elts.length)) - def doConnect(sink: T, source: T) = if (elts.head.flatten.exists(_.firrtlDirection != Direction.Unspecified)) { - sink bulkConnect source - } else { - sink connect source + def doConnect(sink: T, source: T) = { + if (elts.head.flatten.exists(_.firrtlDirection != Direction.Unspecified)) { + sink bulkConnect source + } else { + sink connect source + } } for ((v, e) <- vec zip elts) { doConnect(v, e) @@ -138,27 +141,27 @@ sealed class Vec[T <: Data] private (gen: T, val length: Int) * * @note the length of this Vec must match the length of the input Seq */ - def <> (that: Seq[T])(implicit sourceInfo: SourceInfo): Unit = { + def <> (that: Seq[T])(implicit sourceInfo: SourceInfo, moduleCompileOptions: ExplicitCompileOptions): 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 bulkConnect that.asInstanceOf[Data] + def <> (that: Vec[T])(implicit sourceInfo: SourceInfo, moduleCompileOptions: ExplicitCompileOptions): Unit = this bulkConnect that.asInstanceOf[Data] /** 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 = { + def := (that: Seq[T])(implicit sourceInfo: SourceInfo, moduleCompileOptions: ExplicitCompileOptions): 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 + def := (that: Vec[T])(implicit sourceInfo: SourceInfo, moduleCompileOptions: ExplicitCompileOptions): Unit = this connect that /** Creates a dynamically indexed read or write accessor into the array. */ @@ -184,7 +187,9 @@ sealed class Vec[T <: Data] private (gen: T, val length: Int) def read(idx: UInt): T = apply(idx) @deprecated("Use Vec.apply instead", "chisel3") - def write(idx: UInt, data: T): Unit = apply(idx).:=(data)(DeprecatedSourceInfo) + def write(idx: UInt, data: T): Unit = { + apply(idx).:=(data)(DeprecatedSourceInfo, chisel3.Strict.CompileOptions) + } override def cloneType: this.type = { Vec(length, gen).asInstanceOf[this.type] diff --git a/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala b/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala index 969e5654..b0be1c38 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala @@ -2,10 +2,11 @@ package chisel3.core -import chisel3.internal.Builder.{compileOptions, pushCommand} +import chisel3.internal.Builder.pushCommand import chisel3.internal.firrtl.Connect import scala.language.experimental.macros import chisel3.internal.sourceinfo._ +import chisel3.internal.ExplicitCompileOptions /** * BiConnect.connect executes a bidirectional connection element-wise. @@ -49,11 +50,11 @@ object BiConnect { * during the recursive decent and then rethrow them with extra information added. * This gives the user a 'path' to where in the connections things went wrong. */ - def connect(sourceInfo: SourceInfo, left: Data, right: Data, context_mod: Module): Unit = + def connect(sourceInfo: SourceInfo, connectCompileOptions: ExplicitCompileOptions, left: Data, right: Data, context_mod: Module): Unit = (left, right) match { // Handle element case (root case) case (left_e: Element, right_e: Element) => { - elemConnect(sourceInfo, left_e, right_e, context_mod) + elemConnect(sourceInfo, connectCompileOptions, left_e, right_e, context_mod) // TODO(twigg): Verify the element-level classes are connectable } // Handle Vec case @@ -61,7 +62,7 @@ object BiConnect { if(left_v.length != right_v.length) { throw MismatchedVecException } for(idx <- 0 until left_v.length) { try { - connect(sourceInfo, left_v(idx), right_v(idx), context_mod) + connect(sourceInfo, connectCompileOptions, left_v(idx), right_v(idx), context_mod) } catch { case BiConnectException(message) => throw BiConnectException(s"($idx)$message") } @@ -72,7 +73,7 @@ object BiConnect { // Verify right has no extra fields that left doesn't have for((field, right_sub) <- right_b.elements) { if(!left_b.elements.isDefinedAt(field)) { - if (compileOptions.connectFieldsMustMatch || context_mod.compileOptions.connectFieldsMustMatch) { + if (connectCompileOptions.connectFieldsMustMatch) { throw MissingLeftFieldException(field) } } @@ -81,9 +82,9 @@ object BiConnect { for((field, left_sub) <- left_b.elements) { try { right_b.elements.get(field) match { - case Some(right_sub) => connect(sourceInfo, left_sub, right_sub, context_mod) + case Some(right_sub) => connect(sourceInfo, connectCompileOptions, left_sub, right_sub, context_mod) case None => { - if (compileOptions.connectFieldsMustMatch || context_mod.compileOptions.connectFieldsMustMatch) { + if (connectCompileOptions.connectFieldsMustMatch) { throw MissingRightFieldException(field) } } @@ -109,7 +110,7 @@ object BiConnect { // This function checks if element-level connection operation allowed. // Then it either issues it or throws the appropriate exception. - def elemConnect(implicit sourceInfo: SourceInfo, left: Element, right: Element, context_mod: Module): Unit = { + def elemConnect(implicit sourceInfo: SourceInfo, connectCompileOptions: ExplicitCompileOptions, left: Element, right: Element, context_mod: Module): Unit = { import Direction.{Input, Output} // Using extensively so import these // If left or right have no location, assume in context module // This can occur if one of them is a literal, unbound will error previously @@ -169,7 +170,7 @@ object BiConnect { case (None, Some(Input)) => issueConnectR2L(left, right) case (Some(Input), Some(Input)) => { - if (compileOptions.dontAssumeDirectionality || context_mod.compileOptions.dontAssumeDirectionality) { + if (connectCompileOptions.dontAssumeDirectionality) { throw BothDriversException } else { (left.binding, right.binding) match { @@ -181,7 +182,7 @@ object BiConnect { } } case (Some(Output), Some(Output)) => { - if (compileOptions.dontAssumeDirectionality || context_mod.compileOptions.dontAssumeDirectionality) { + if (connectCompileOptions.dontAssumeDirectionality) { throw BothDriversException } else { (left.binding, right.binding) match { @@ -193,7 +194,7 @@ object BiConnect { } } case (None, None) => { - if (compileOptions.dontAssumeDirectionality || context_mod.compileOptions.dontAssumeDirectionality) { + if (connectCompileOptions.dontAssumeDirectionality) { throw UnknownDriverException } else { issueConnectR2L(left, right) diff --git a/chiselFrontend/src/main/scala/chisel3/core/Binding.scala b/chiselFrontend/src/main/scala/chisel3/core/Binding.scala index b36794f1..5378f3ae 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Binding.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Binding.scala @@ -1,6 +1,6 @@ package chisel3.core -import chisel3.internal.Builder.{compileOptions, forcedModule} +import chisel3.internal.Builder.{forcedModule} /** * The purpose of a Binding is to indicate what type of hardware 'entity' a @@ -91,7 +91,7 @@ object Binding { element.binding = binder(unbound) } // If autoIOWrap is enabled and we're rebinding a PortBinding, just ignore the rebinding. - case portBound @ PortBinding(_, _) if (!(compileOptions.requireIOWrap || forcedModule.compileOptions.requireIOWrap)&& binder.isInstanceOf[PortBinder]) => + case portBound @ PortBinding(_, _) if (!(forcedModule.compileOptions.requireIOWrap) && binder.isInstanceOf[PortBinder]) => case binding => throw AlreadyBoundException(binding.toString) } ) @@ -145,7 +145,7 @@ object Binding { case binding => // The following kludge is an attempt to provide backward compatibility // It should be done at at higher level. - if ((compileOptions.requireIOWrap || forcedModule.compileOptions.requireIOWrap || !elementOfIO(element))) + if ((forcedModule.compileOptions.requireIOWrap || !elementOfIO(element))) throw NotSynthesizableException else Binding.bind(element, PortBinder(element._parent.get), "Error: IO") diff --git a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala index c2621251..6fdec340 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala @@ -10,6 +10,7 @@ import chisel3.internal.firrtl._ import chisel3.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, SourceInfoTransform, SourceInfoWhiteboxTransform, UIntTransform, MuxTransform} import chisel3.internal.firrtl.PrimOp._ +import chisel3.Strict.CompileOptions /** Element is a leaf data type: it cannot contain other Data objects. Example * uses are for representing primitive data types, like integers and bits. diff --git a/chiselFrontend/src/main/scala/chisel3/core/Data.scala b/chiselFrontend/src/main/scala/chisel3/core/Data.scala index ce7b58b4..bda06790 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Data.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Data.scala @@ -8,6 +8,7 @@ import chisel3.internal._ import chisel3.internal.Builder.pushCommand import chisel3.internal.firrtl._ import chisel3.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, UnlocatableSourceInfo, WireTransform, SourceInfoTransform} +import chisel3.Strict.CompileOptions sealed abstract class Direction(name: String) { override def toString: String = name @@ -124,11 +125,11 @@ abstract class Data extends HasId { private[core] def badConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit = throwException(s"cannot connect ${this} and ${that}") - private[chisel3] def connect(that: Data)(implicit sourceInfo: SourceInfo): Unit = { + private[chisel3] def connect(that: Data)(implicit sourceInfo: SourceInfo, connectCompileOptions: ExplicitCompileOptions): Unit = { Binding.checkSynthesizable(this, s"'this' ($this)") Binding.checkSynthesizable(that, s"'that' ($that)") try { - MonoConnect.connect(sourceInfo, this, that, Builder.forcedModule) + MonoConnect.connect(sourceInfo, connectCompileOptions, this, that, Builder.forcedModule) } catch { case MonoConnect.MonoConnectException(message) => throwException( @@ -136,11 +137,11 @@ abstract class Data extends HasId { ) } } - private[chisel3] def bulkConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit = { + private[chisel3] def bulkConnect(that: Data)(implicit sourceInfo: SourceInfo, connectCompileOptions: ExplicitCompileOptions): Unit = { Binding.checkSynthesizable(this, s"'this' ($this)") Binding.checkSynthesizable(that, s"'that' ($that)") try { - BiConnect.connect(sourceInfo, this, that, Builder.forcedModule) + BiConnect.connect(sourceInfo, connectCompileOptions, this, that, Builder.forcedModule) } catch { case BiConnect.BiConnectException(message) => throwException( @@ -165,8 +166,8 @@ abstract class Data extends HasId { } clone } - final def := (that: Data)(implicit sourceInfo: SourceInfo): Unit = this connect that - final def <> (that: Data)(implicit sourceInfo: SourceInfo): Unit = this bulkConnect that + final def := (that: Data)(implicit sourceInfo: SourceInfo, connectionCompileOptions: ExplicitCompileOptions): Unit = this.connect(that)(sourceInfo, connectionCompileOptions) + final def <> (that: Data)(implicit sourceInfo: SourceInfo, connectionCompileOptions: ExplicitCompileOptions): Unit = this.bulkConnect(that)(sourceInfo, connectionCompileOptions) def litArg(): Option[LitArg] = None def litValue(): BigInt = litArg.get.num def isLit(): Boolean = litArg.isDefined @@ -254,7 +255,7 @@ object Wire { 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) + val x = Reg.makeType(chisel3.Strict.CompileOptions, t, null.asInstanceOf[T], init) // Bind each element of x to being a Wire Binding.bind(x, WireBinder(Builder.forcedModule), "Error: t") @@ -288,8 +289,8 @@ sealed class Clock extends Element(Width(1)) { private[core] def cloneTypeWidth(width: Width): this.type = cloneType private[chisel3] def toType = "Clock" - override def connect (that: Data)(implicit sourceInfo: SourceInfo): Unit = that match { - case _: Clock => super.connect(that)(sourceInfo) + override def connect (that: Data)(implicit sourceInfo: SourceInfo, connectCompileOptions: ExplicitCompileOptions): Unit = that match { + case _: Clock => super.connect(that)(sourceInfo, connectCompileOptions) case _ => super.badConnect(that)(sourceInfo) } } diff --git a/chiselFrontend/src/main/scala/chisel3/core/Mem.scala b/chiselFrontend/src/main/scala/chisel3/core/Mem.scala index 931a0489..327e119e 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Mem.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Mem.scala @@ -8,6 +8,7 @@ import chisel3.internal._ import chisel3.internal.Builder.pushCommand import chisel3.internal.firrtl._ import chisel3.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, UnlocatableSourceInfo, MemTransform} +import chisel3.Strict.CompileOptions 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/MonoConnect.scala b/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala index 41754827..1925171b 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala @@ -1,9 +1,12 @@ +// See LICENSE for license details. + package chisel3.core -import chisel3.internal.Builder.{compileOptions, pushCommand} +import chisel3.internal.Builder.pushCommand import chisel3.internal.firrtl.Connect import scala.language.experimental.macros import chisel3.internal.sourceinfo.{DeprecatedSourceInfo, SourceInfo, SourceInfoTransform, UnlocatableSourceInfo, WireTransform} +import chisel3.internal.ExplicitCompileOptions /** * MonoConnect.connect executes a mono-directional connection element-wise. @@ -53,11 +56,11 @@ object MonoConnect { * during the recursive decent and then rethrow them with extra information added. * This gives the user a 'path' to where in the connections things went wrong. */ - def connect(sourceInfo: SourceInfo, sink: Data, source: Data, context_mod: Module): Unit = + def connect(sourceInfo: SourceInfo, connectCompileOptions: ExplicitCompileOptions, sink: Data, source: Data, context_mod: Module): Unit = (sink, source) match { // Handle element case (root case) case (sink_e: Element, source_e: Element) => { - elemConnect(sourceInfo, sink_e, source_e, context_mod) + elemConnect(sourceInfo, connectCompileOptions, sink_e, source_e, context_mod) // TODO(twigg): Verify the element-level classes are connectable } // Handle Vec case @@ -65,7 +68,7 @@ object MonoConnect { if(sink_v.length != source_v.length) { throw MismatchedVecException } for(idx <- 0 until sink_v.length) { try { - connect(sourceInfo, sink_v(idx), source_v(idx), context_mod) + connect(sourceInfo, connectCompileOptions, sink_v(idx), source_v(idx), context_mod) } catch { case MonoConnectException(message) => throw MonoConnectException(s"($idx)$message") } @@ -77,9 +80,9 @@ object MonoConnect { for((field, sink_sub) <- sink_b.elements) { try { source_b.elements.get(field) match { - case Some(source_sub) => connect(sourceInfo, sink_sub, source_sub, context_mod) + case Some(source_sub) => connect(sourceInfo, connectCompileOptions, sink_sub, source_sub, context_mod) case None => { - if (compileOptions.connectFieldsMustMatch || context_mod.compileOptions.connectFieldsMustMatch) { + if (connectCompileOptions.connectFieldsMustMatch) { throw MissingFieldException(field) } } @@ -100,7 +103,7 @@ object MonoConnect { // This function checks if element-level connection operation allowed. // Then it either issues it or throws the appropriate exception. - def elemConnect(implicit sourceInfo: SourceInfo, sink: Element, source: Element, context_mod: Module): Unit = { + def elemConnect(implicit sourceInfo: SourceInfo, connectCompileOptions: ExplicitCompileOptions, sink: Element, source: Element, context_mod: Module): Unit = { import Direction.{Input, Output} // Using extensively so import these // If source has no location, assume in context module // This can occur if is a literal, unbound will error previously @@ -134,13 +137,13 @@ object MonoConnect { case (Some(Output), Some(Output)) => issueConnect(sink, source) case (Some(Output), Some(Input)) => issueConnect(sink, source) case (_, None) => { - if (!(compileOptions.dontAssumeDirectionality || context_mod.compileOptions.dontAssumeDirectionality)) { + if (!(connectCompileOptions.dontAssumeDirectionality)) { issueConnect(sink, source) } else { throw UnreadableSourceException } } - case (Some(Input), Some(Output)) if (!(compileOptions.dontTryConnectionsSwapped || context_mod.compileOptions.dontTryConnectionsSwapped)) => issueConnect(source, sink) + case (Some(Input), Some(Output)) if (!(connectCompileOptions.dontTryConnectionsSwapped)) => issueConnect(source, sink) case (Some(Input), _) => throw UnwritableSinkException } } @@ -172,7 +175,7 @@ object MonoConnect { case (Some(Input), Some(Output)) => issueConnect(sink, source) case (Some(Output), _) => throw UnwritableSinkException case (_, None) => { - if (!(compileOptions.dontAssumeDirectionality || context_mod.compileOptions.dontAssumeDirectionality)) { + if (!(connectCompileOptions.dontAssumeDirectionality)) { issueConnect(sink, source) } else { throw UnreadableSourceException diff --git a/chiselFrontend/src/main/scala/chisel3/core/Reg.scala b/chiselFrontend/src/main/scala/chisel3/core/Reg.scala index 36c88245..d147a81d 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Reg.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Reg.scala @@ -8,9 +8,9 @@ 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 = { + private[core] def makeType[T <: Data](compileOptions: ExplicitCompileOptions, t: T = null, next: T = null, init: T = null): T = { if (t ne null) { - if (Builder.compileOptions.declaredTypeMustBeUnbound || Builder.forcedModule.compileOptions.declaredTypeMustBeUnbound) { + if (compileOptions.declaredTypeMustBeUnbound) { Binding.checkUnbound(t, s"t ($t) must be unbound Type. Try using cloneType?") } t.chiselCloneType @@ -40,18 +40,18 @@ object Reg { * 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 = + def apply[T <: Data](t: T = null, next: T = null, init: T = null)(implicit sourceInfo: SourceInfo, compileOptions: ExplicitCompileOptions): T = // Scala macros can't (yet) handle named or default arguments. - do_apply(t, next, init)(UnlocatableSourceInfo) + do_apply(t, next, init)(sourceInfo, compileOptions) /** 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 apply[T <: Data](outType: T)(implicit sourceInfo: SourceInfo, compileOptions: ExplicitCompileOptions): T = Reg[T](outType, null.asInstanceOf[T], null.asInstanceOf[T])(sourceInfo, compileOptions) - def do_apply[T <: Data](t: T, next: T, init: T)(implicit sourceInfo: SourceInfo): T = { + def do_apply[T <: Data](t: T, next: T, init: T)(implicit sourceInfo: SourceInfo, compileOptions: ExplicitCompileOptions = chisel3.Strict.CompileOptions): 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()). @@ -59,7 +59,7 @@ object Reg { // 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 x = makeType(compileOptions, t, next, init) val clock = Node(x._parent.get.clock) // TODO multi-clock // Bind each element of x to being a Reg diff --git a/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala b/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala index 0376e067..8d376810 100644 --- a/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala +++ b/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala @@ -129,16 +129,12 @@ private[chisel3] trait HasId extends InstanceId { } } -private[chisel3] class DynamicContext(moduleCompileOptions: Option[ExplicitCompileOptions] = None) { +private[chisel3] 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 - val compileOptions = moduleCompileOptions match { - case Some(options: ExplicitCompileOptions) => options - case None => chisel3.NotStrict.CompileOptions - } } private[chisel3] object Builder { @@ -150,7 +146,6 @@ private[chisel3] object Builder { def idGen: IdGen = dynamicContext.idGen def globalNamespace: Namespace = dynamicContext.globalNamespace def components: ArrayBuffer[Component] = dynamicContext.components - def compileOptions = dynamicContext.compileOptions def currentModule: Option[Module] = dynamicContext.currentModule def currentModule_=(target: Option[Module]): Unit = { @@ -179,8 +174,8 @@ private[chisel3] object Builder { def errors: ErrorLog = dynamicContext.errors def error(m: => String): Unit = errors.error(m) - def build[T <: Module](f: => T, moduleCompileOptions: Option[ExplicitCompileOptions] = None): Circuit = { - dynamicContextVar.withValue(Some(new DynamicContext(moduleCompileOptions))) { + def build[T <: Module](f: => T): Circuit = { + dynamicContextVar.withValue(Some(new DynamicContext())) { errors.info("Elaborating design...") val mod = f mod.forceName(mod.name, globalNamespace) diff --git a/src/main/scala/chisel3/Driver.scala b/src/main/scala/chisel3/Driver.scala index f9f79f35..5e0a3a0f 100644 --- a/src/main/scala/chisel3/Driver.scala +++ b/src/main/scala/chisel3/Driver.scala @@ -108,9 +108,9 @@ object Driver extends BackendCompilationUtilities { * @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, moduleCompileOptions: Option[ExplicitCompileOptions] = None): Circuit = Builder.build(Module(gen()), moduleCompileOptions) + def elaborate[T <: Module](gen: () => T): Circuit = Builder.build(Module(gen())) - def emit[T <: Module](gen: () => T, moduleCompileOptions: Option[ExplicitCompileOptions] = None): String = Emitter.emit(elaborate(gen, moduleCompileOptions)) + def emit[T <: Module](gen: () => T): String = Emitter.emit(elaborate(gen)) def emit[T <: Module](ir: Circuit): String = Emitter.emit(ir) diff --git a/src/main/scala/chisel3/util/Counter.scala b/src/main/scala/chisel3/util/Counter.scala index 1c95190b..441f5c5b 100644 --- a/src/main/scala/chisel3/util/Counter.scala +++ b/src/main/scala/chisel3/util/Counter.scala @@ -3,6 +3,7 @@ package chisel3.util import chisel3._ +import chisel3.Strict.CompileOptions /** 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/LFSR.scala b/src/main/scala/chisel3/util/LFSR.scala index a30c276f..7146af7e 100644 --- a/src/main/scala/chisel3/util/LFSR.scala +++ b/src/main/scala/chisel3/util/LFSR.scala @@ -6,6 +6,7 @@ package chisel3.util import chisel3._ +import chisel3.Strict.CompileOptions // scalastyle:off magic.number /** linear feedback shift register diff --git a/src/main/scala/chisel3/util/Reg.scala b/src/main/scala/chisel3/util/Reg.scala index 37c28b14..8a9c54a2 100644 --- a/src/main/scala/chisel3/util/Reg.scala +++ b/src/main/scala/chisel3/util/Reg.scala @@ -6,6 +6,7 @@ package chisel3.util import chisel3._ +import chisel3.Strict.CompileOptions object RegNext { diff --git a/src/test/scala/chiselTests/BlackBox.scala b/src/test/scala/chiselTests/BlackBox.scala index c1154883..b26b7d77 100644 --- a/src/test/scala/chiselTests/BlackBox.scala +++ b/src/test/scala/chiselTests/BlackBox.scala @@ -8,6 +8,7 @@ import org.scalatest._ import chisel3._ import chisel3.testers.BasicTester import chisel3.util._ +import chisel3.Strict.CompileOptions class BlackBoxInverter extends BlackBox { val io = IO(new Bundle() { diff --git a/src/test/scala/chiselTests/CompileOptionsTest.scala b/src/test/scala/chiselTests/CompileOptionsTest.scala index 70843c3e..f835ab0d 100644 --- a/src/test/scala/chiselTests/CompileOptionsTest.scala +++ b/src/test/scala/chiselTests/CompileOptionsTest.scala @@ -13,6 +13,16 @@ class CompileOptionsSpec extends ChiselFlatSpec { abstract class StrictModule extends Module()(chisel3.Strict.CompileOptions) abstract class NotStrictModule extends Module()(chisel3.NotStrict.CompileOptions) + // Generate a set of options that do not have requireIOWrap enabled, in order to + // ensure its definition comes from the implicit options passed to the Module constructor. + object StrictWithoutIOWrap extends ExplicitCompileOptions { + val connectFieldsMustMatch = true + val declaredTypeMustBeUnbound = true + val requireIOWrap = false + val dontTryConnectionsSwapped = true + val dontAssumeDirectionality = true + } + class SmallBundle extends Bundle { val f1 = UInt(width = 4) val f2 = UInt(width = 5) @@ -199,7 +209,7 @@ class CompileOptionsSpec extends ChiselFlatSpec { } "A Module with wrapped IO when compiled with explicit Strict.CompileOption " should "not throw an exception" in { - + implicit val strictWithoutIOWrap = StrictWithoutIOWrap class RequireIOWrapModule extends StrictModule { val io = IO(new Bundle { val in = UInt(width = 32).asInput @@ -207,11 +217,13 @@ class CompileOptionsSpec extends ChiselFlatSpec { }) io.out := io.in(1) } - elaborate { new RequireIOWrapModule() } + elaborate { + new RequireIOWrapModule() + } } "A Module with unwrapped IO when compiled with explicit NotStrict.CompileOption " should "not throw an exception" in { - + implicit val strictWithoutIOWrap = StrictWithoutIOWrap class RequireIOWrapModule extends NotStrictModule { val io = new Bundle { val in = UInt(width = 32).asInput @@ -219,12 +231,14 @@ class CompileOptionsSpec extends ChiselFlatSpec { } io.out := io.in(1) } - elaborate { new RequireIOWrapModule() } + elaborate { + new RequireIOWrapModule() + } } "A Module with unwrapped IO when compiled with explicit Strict.CompileOption " should "throw an exception" in { a [BindingException] should be thrownBy { - + implicit val strictWithoutIOWrap = StrictWithoutIOWrap class RequireIOWrapModule extends StrictModule { val io = new Bundle { val in = UInt(width = 32).asInput @@ -256,7 +270,6 @@ class CompileOptionsSpec extends ChiselFlatSpec { val in = UInt(width = 32).asInput val out = Bool().asOutput } - io.out := io.in(1) } elaborate { new NotIOWrapModule() diff --git a/src/test/scala/chiselTests/Counter.scala b/src/test/scala/chiselTests/Counter.scala index 69d8a44a..46ab6dfc 100644 --- a/src/test/scala/chiselTests/Counter.scala +++ b/src/test/scala/chiselTests/Counter.scala @@ -8,6 +8,7 @@ import org.scalatest.prop._ import chisel3._ import chisel3.testers.BasicTester import chisel3.util._ +import chisel3.Strict.CompileOptions class CountTester(max: Int) extends BasicTester { val cnt = Counter(max) diff --git a/src/test/scala/chiselTests/MultiAssign.scala b/src/test/scala/chiselTests/MultiAssign.scala index fa4c4898..8fc1d0cb 100644 --- a/src/test/scala/chiselTests/MultiAssign.scala +++ b/src/test/scala/chiselTests/MultiAssign.scala @@ -7,6 +7,7 @@ import org.scalatest._ import chisel3._ import chisel3.testers.BasicTester import chisel3.util._ +import chisel3.Strict.CompileOptions class LastAssignTester() extends BasicTester { val cnt = Counter(2) diff --git a/src/test/scala/chiselTests/Reg.scala b/src/test/scala/chiselTests/Reg.scala index a9086223..741393b0 100644 --- a/src/test/scala/chiselTests/Reg.scala +++ b/src/test/scala/chiselTests/Reg.scala @@ -6,6 +6,7 @@ import org.scalatest._ import chisel3._ import chisel3.core.DataMirror import chisel3.testers.BasicTester +import chisel3.Strict.CompileOptions class RegSpec extends ChiselFlatSpec { "A Reg" should "throw an exception if not given any parameters" in { diff --git a/src/test/scala/chiselTests/TesterDriverSpec.scala b/src/test/scala/chiselTests/TesterDriverSpec.scala index 23eed15f..6dc075d7 100644 --- a/src/test/scala/chiselTests/TesterDriverSpec.scala +++ b/src/test/scala/chiselTests/TesterDriverSpec.scala @@ -5,6 +5,7 @@ package chiselTests import chisel3._ import chisel3.testers.BasicTester import chisel3.util._ +import chisel3.Strict.CompileOptions /** 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 e8bd66bd..abe483a4 100644 --- a/src/test/scala/chiselTests/Vec.scala +++ b/src/test/scala/chiselTests/Vec.scala @@ -8,6 +8,7 @@ import org.scalatest.prop._ import chisel3._ import chisel3.testers.BasicTester import chisel3.util._ +import chisel3.Strict.CompileOptions 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/When.scala b/src/test/scala/chiselTests/When.scala index 07ab3444..1920b30e 100644 --- a/src/test/scala/chiselTests/When.scala +++ b/src/test/scala/chiselTests/When.scala @@ -7,6 +7,7 @@ import org.scalatest._ import chisel3._ import chisel3.testers.BasicTester import chisel3.util._ +import chisel3.Strict.CompileOptions class WhenTester() extends BasicTester { val cnt = Counter(4) -- cgit v1.2.3 From fcdc5035675e9891d6c68c97d270a25fb60b3d64 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Thu, 1 Sep 2016 13:02:09 -0700 Subject: Deprecate Vec.fill() offering Vec(Seq.fill()). --- chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala | 1 + 1 file changed, 1 insertion(+) diff --git a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala index c579d424..ed5a8fb3 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala @@ -99,6 +99,7 @@ object Vec { * @param gen function that generates the [[Data]] that becomes the output * element */ + @deprecated("Vec.fill(n)(gen) is deprecated. Please use Vec(Seq.fill(n)(gen))", "chisel3") 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] = -- cgit v1.2.3 From ace6afb3177fbb14b8b85a16d6724ce784277f95 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Thu, 1 Sep 2016 20:37:06 -0700 Subject: Remove O(n^2) code in Vec.apply(Seq) The O(n) type legality check was redundantly executed n times. D'oh. --- .../src/main/scala/chisel3/core/Aggregate.scala | 26 ++++++++++------------ 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala index e6ecff91..f80c8d8e 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala @@ -47,22 +47,20 @@ object Vec { // 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. + + // Check that types are homogeneous. Width mismatch for Elements is safe. require(!elts.isEmpty) - def gen = elts.head match { - case e: Element => - // Vec[Element] must have homogeneous types, but may differ in width - for (elt <- elts.tail) - require(e.getClass == elt.getClass, - s"can't create Vec of heterogeneous types ${e.getClass} and ${elt.getClass}") - val maxWidth = elts.map(_.width).reduce(_ max _) - elts.head.cloneTypeWidth(maxWidth) - case a: Aggregate => - // Vec[Aggregate] must be homogeneous in type and width - for (elt <- elts.tail) - require(Mux.typesCompatible(a, elt), s"can't create Vec of heterogeneous types ${a.getClass} and ${elt.getClass}") - elts.head.cloneType + def eltsCompatible(a: Data, b: Data) = a match { + case _: Element => a.getClass == b.getClass + case _: Aggregate => Mux.typesCompatible(a, b) } - val vec = Wire(new Vec(gen, elts.length)) + + val t = elts.head + for (e <- elts.tail) + require(eltsCompatible(t, e), s"can't create Vec of heterogeneous types ${t.getClass} and ${e.getClass}") + + val maxWidth = elts.map(_.width).reduce(_ max _) + val vec = Wire(new Vec(t.cloneTypeWidth(maxWidth), elts.length)) for ((v, e) <- vec zip elts) v := e vec -- cgit v1.2.3 From 16426b3a68d85ce7dd9655b0ce773431eb69fc74 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Fri, 2 Sep 2016 11:14:57 -0700 Subject: Deprecate asBits; modify deprecation warnings accordingly --- chiselFrontend/src/main/scala/chisel3/core/Bits.scala | 3 ++- chiselFrontend/src/main/scala/chisel3/core/Data.scala | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala index 44beab66..57f6d8e0 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala @@ -211,6 +211,7 @@ sealed abstract class Bits(dirArg: Direction, width: Width, override val litArg: def do_asSInt(implicit sourceInfo: SourceInfo): SInt /** Reinterpret cast to Bits. */ + @deprecated("Use asUInt, which does the same thing but returns a more concrete type", "chisel3") final def asBits(): Bits = macro SourceInfoTransform.noArg def do_asBits(implicit sourceInfo: SourceInfo): Bits = asUInt() @@ -241,7 +242,7 @@ sealed abstract class Bits(dirArg: Direction, width: Width, override val litArg: 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") + @deprecated("Use asUInt, which does the same thing but makes the reinterpret cast more explicit", "chisel3") override def toBits: UInt = do_asUInt(DeprecatedSourceInfo) override def do_fromBits(that: Bits)(implicit sourceInfo: SourceInfo): this.type = { diff --git a/chiselFrontend/src/main/scala/chisel3/core/Data.scala b/chiselFrontend/src/main/scala/chisel3/core/Data.scala index 8826af51..5ae8c84d 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Data.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Data.scala @@ -118,7 +118,7 @@ abstract class Data(dirArg: Direction) extends HasId { * * This performs the inverse operation of fromBits(Bits). */ - @deprecated("Use asBits, which makes the reinterpret cast more explicit and actually returns Bits", "chisel3") + @deprecated("Use asUInt, which does the same thing but makes the reinterpret cast more explicit", "chisel3") def toBits(): UInt = SeqUtils.do_asUInt(this.flatten)(DeprecatedSourceInfo) /** Reinterpret cast to UInt. -- cgit v1.2.3 From 85a65019641130949fcc9082e42231a7c3618f0a Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Fri, 2 Sep 2016 14:47:29 -0700 Subject: Add/cleanup UInt/SInt factory methods. --- chiselFrontend/src/main/scala/chisel3/core/Bits.scala | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala index 6fdec340..625f985d 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala @@ -538,12 +538,16 @@ private[core] sealed trait UIntFactory { } /** Create a UInt with a specified width - compatibility with Chisel2. */ + // NOTE: This resolves UInt(width = 32) def apply(dir: Option[Direction] = None, width: Int): UInt = apply(Width(width)) /** Create a UInt literal with inferred width.- compatibility with Chisel2. */ def apply(value: BigInt): UInt = apply(value, Width()) /** Create a UInt with a specified direction and width - compatibility with Chisel2. */ - def apply(dir: Direction, width: Int): UInt = { - val result = apply(Width(width)) + def apply(dir: Direction, width: Int): UInt = apply(dir, Width(width)) + /** Create a UInt with a specified direction, but unspecified width - compatibility with Chisel2. */ + def apply(dir: Direction): UInt = apply(dir, Width()) + def apply(dir: Direction, wWidth: Width): UInt = { + val result = apply(wWidth) dir match { case Direction.Input => Input(result) case Direction.Output => Output(result) @@ -707,8 +711,11 @@ object SInt { /** Create a SInt with a specified width - compatibility with Chisel2. */ def apply(dir: Option[Direction] = None, width: Int): SInt = apply(Width(width)) /** Create a SInt with a specified direction and width - compatibility with Chisel2. */ - def apply(dir: Direction, width: Int): SInt = { - val result = apply(Width(width)) + def apply(dir: Direction, width: Int): SInt = apply(dir, Width(width)) + /** Create a SInt with a specified direction, but unspecified width - compatibility with Chisel2. */ + def apply(dir: Direction): SInt = apply(dir, Width()) + def apply(dir: Direction, wWidth: Width): SInt = { + val result = apply(wWidth) dir match { case Direction.Input => Input(result) case Direction.Output => Output(result) -- cgit v1.2.3 From 3451ac840b3008597a6905c21d0e77ed613d5dbd Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Fri, 2 Sep 2016 17:07:32 -0700 Subject: Rename implicit compileOptions to defaultCompileOptions. --- src/main/scala/chisel3/compatibility.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/chisel3/compatibility.scala b/src/main/scala/chisel3/compatibility.scala index 85311ba2..49b8bb2c 100644 --- a/src/main/scala/chisel3/compatibility.scala +++ b/src/main/scala/chisel3/compatibility.scala @@ -4,7 +4,7 @@ // moving to the more standard package naming convention chisel3 (lowercase c). package object Chisel { // scalastyle:ignore package.object.name - implicit val compileOptions = chisel3.NotStrict.CompileOptions + implicit val defaultCompileOptions = chisel3.NotStrict.CompileOptions type Direction = chisel3.core.Direction val INPUT = chisel3.core.Direction.Input val OUTPUT = chisel3.core.Direction.Output -- cgit v1.2.3 From 8e2615fd3852c7ffa5ee1884cca0f77062f3cc21 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Tue, 6 Sep 2016 08:46:16 -0700 Subject: Verify we can suppress the inclusion of default compileOptions. --- src/test/scala/chiselTests/CompileOptionsTest.scala | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/scala/chiselTests/CompileOptionsTest.scala b/src/test/scala/chiselTests/CompileOptionsTest.scala index f835ab0d..de75d07b 100644 --- a/src/test/scala/chiselTests/CompileOptionsTest.scala +++ b/src/test/scala/chiselTests/CompileOptionsTest.scala @@ -168,6 +168,8 @@ class CompileOptionsSpec extends ChiselFlatSpec { "A Module with directionless connections when compiled with implicit Strict.CompileOption " should "throw an exception" in { a [ChiselException] should be thrownBy { + // Verify we can suppress the inclusion of default compileOptions + import Chisel.{defaultCompileOptions => _, _} import chisel3.Strict.CompileOptions class SimpleModule extends Module { -- cgit v1.2.3 From 0ed5eb48cdb916b644aaf9e5dbf48f6cfb6c60f4 Mon Sep 17 00:00:00 2001 From: Jack Koenig Date: Wed, 7 Sep 2016 14:18:29 -0700 Subject: Add Printable (#270) Printable is a new type that changes how printing of Chisel types is represented It uses an ordered collection rather than a format string and specifiers Features: - Custom String Interpolator for Scala-like printf - String-like manipulation of "hardware strings" for custom pretty-printing - Default pretty-printing for Chisel data types--- .../src/main/scala/chisel3/core/Aggregate.scala | 26 ++++ .../src/main/scala/chisel3/core/Bits.scala | 3 + .../src/main/scala/chisel3/core/Data.scala | 6 + .../src/main/scala/chisel3/core/Printable.scala | 150 +++++++++++++++++++ .../src/main/scala/chisel3/core/Printf.scala | 44 +++++- .../main/scala/chisel3/internal/firrtl/IR.scala | 18 +-- .../scala/chisel3/internal/firrtl/Emitter.scala | 6 +- src/main/scala/chisel3/package.scala | 51 +++++++ src/test/scala/chiselTests/PrintableSpec.scala | 162 +++++++++++++++++++++ src/test/scala/chiselTests/Printf.scala | 9 ++ 10 files changed, 452 insertions(+), 23 deletions(-) create mode 100644 chiselFrontend/src/main/scala/chisel3/core/Printable.scala create mode 100644 src/test/scala/chiselTests/PrintableSpec.scala diff --git a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala index f80c8d8e..d07c5dcd 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala @@ -180,6 +180,17 @@ sealed class Vec[T <: Data] private (gen: => T, val length: Int) for ((elt, i) <- self zipWithIndex) elt.setRef(this, i) + + /** Default "pretty-print" implementation + * Analogous to printing a Seq + * Results in "Vec(elt0, elt1, ...)" + */ + def toPrintable: Printable = { + val elts = + if (length == 0) List.empty[Printable] + else self flatMap (e => List(e.toPrintable, PString(", "))) dropRight 1 + PString("Vec(") + Printables(elts) + PString(")") + } } /** A trait for [[Vec]]s containing common hardware generators for collection @@ -381,6 +392,21 @@ class Bundle extends Aggregate(NO_DIR) { this } } + + /** Default "pretty-print" implementation + * Analogous to printing a Map + * Results in "Bundle(elt0.name -> elt0.value, ...)" + */ + def toPrintable: Printable = { + val elts = + if (elements.isEmpty) List.empty[Printable] + else { + elements.toList.reverse flatMap { case (name, data) => + List(PString(s"$name -> "), data.toPrintable, PString(", ")) + } dropRight 1 // Remove trailing ", " + } + PString("Bundle(") + Printables(elts) + PString(")") + } } private[core] object Bundle { diff --git a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala index 57f6d8e0..77a31252 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala @@ -250,6 +250,9 @@ sealed abstract class Bits(dirArg: Direction, width: Width, override val litArg: res := that res } + + /** Default print as [[Decimal]] */ + final def toPrintable: Printable = Decimal(this) } /** Provides a set of operations to create UInt types and literals. diff --git a/chiselFrontend/src/main/scala/chisel3/core/Data.scala b/chiselFrontend/src/main/scala/chisel3/core/Data.scala index 5ae8c84d..573632ab 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Data.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Data.scala @@ -132,6 +132,9 @@ abstract class Data(dirArg: Direction) extends HasId { def do_asUInt(implicit sourceInfo: SourceInfo): UInt = SeqUtils.do_asUInt(this.flatten)(sourceInfo) + + /** Default pretty printing */ + def toPrintable: Printable } object Wire { @@ -171,4 +174,7 @@ sealed class Clock(dirArg: Direction) extends Element(dirArg, Width(1)) { case _: Clock => this connect that case _ => this badConnect that } + + /** Not really supported */ + def toPrintable: Printable = PString("CLOCK") } diff --git a/chiselFrontend/src/main/scala/chisel3/core/Printable.scala b/chiselFrontend/src/main/scala/chisel3/core/Printable.scala new file mode 100644 index 00000000..13d5d74e --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel3/core/Printable.scala @@ -0,0 +1,150 @@ +// See LICENSE for license details. + +package chisel3.core + +import chisel3.internal.firrtl.Component +import chisel3.internal.HasId + +import scala.collection.mutable + +import java.util.{ + MissingFormatArgumentException, + UnknownFormatConversionException +} + +/** Superclass of things that can be printed in the resulting circuit + * + * Usually created using the custom string interpolator p"..." + * TODO Should we provide more functions like map and mkPrintable? + */ +sealed abstract class Printable { + /** Unpack into format String and a List of String arguments (identifiers) + * @note This must be called after elaboration when Chisel nodes actually + * have names + */ + def unpack: (String, Iterable[String]) + /** Allow for appending Printables like Strings */ + final def +(that: Printable) = Printables(List(this, that)) + /** Allow for appending Strings to Printables */ + final def +(that: String) = Printables(List(this, PString(that))) +} +object Printable { + /** Pack standard printf fmt, args* style into Printable + */ + def pack(fmt: String, data: Data*): Printable = { + val args = data.toIterator + + // Error handling + def carrotAt(index: Int) = (" " * index) + "^" + def errorMsg(index: Int) = + s"""| fmt = "$fmt" + | ${carrotAt(index)} + | data = ${data mkString ", "}""".stripMargin + def getArg(i: Int): Data = { + if (!args.hasNext) { + val msg = "has no matching argument!\n" + errorMsg(i) + // Exception wraps msg in s"Format Specifier '$msg'" + throw new MissingFormatArgumentException(msg) + } + args.next() + } + + val pables = mutable.ListBuffer.empty[Printable] + var str = "" + var percent = false + for ((c, i) <- fmt.zipWithIndex) { + if (percent) { + val arg = c match { + case FirrtlFormat(x) => FirrtlFormat(x.toString, getArg(i)) + case 'n' => Name(getArg(i)) + case 'N' => FullName(getArg(i)) + case '%' => Percent + case x => + val msg = s"Illegal format specifier '$x'!\n" + errorMsg(i) + throw new UnknownFormatConversionException(msg) + } + pables += PString(str dropRight 1) // remove format % + pables += arg + str = "" + percent = false + } else { + str += c + percent = c == '%' + } + } + if (percent) { + val msg = s"Trailing %\n" + errorMsg(fmt.size - 1) + throw new UnknownFormatConversionException(msg) + } + require(!args.hasNext, + s"Too many arguments! More format specifier(s) expected!\n" + + errorMsg(fmt.size)) + + pables += PString(str) + Printables(pables) + } +} + +case class Printables(pables: Iterable[Printable]) extends Printable { + require(pables.hasDefiniteSize, "Infinite-sized iterables are not supported!") + final def unpack: (String, Iterable[String]) = { + val (fmts, args) = pables.map(_.unpack).unzip + (fmts.mkString, args.flatten) + } +} +/** Wrapper for printing Scala Strings */ +case class PString(str: String) extends Printable { + final def unpack: (String, Iterable[String]) = + (str replaceAll ("%", "%%"), List.empty) +} +/** Superclass for Firrtl format specifiers for Bits */ +sealed abstract class FirrtlFormat(specifier: Char) extends Printable { + def bits: Bits + def unpack: (String, Iterable[String]) = { + val id = if (bits.isLit) bits.ref.name else bits.instanceName + (s"%$specifier", List(id)) + } +} +object FirrtlFormat { + final val legalSpecifiers = List('d', 'x', 'b', 'c') + + def unapply(x: Char): Option[Char] = + Option(x) filter (x => legalSpecifiers contains x) + + /** Helper for constructing Firrtl Formats + * Accepts data to simplify pack + */ + def apply(specifier: String, data: Data): FirrtlFormat = { + val bits = data match { + case b: Bits => b + case d => throw new Exception(s"Trying to construct FirrtlFormat with non-bits $d!") + } + specifier match { + case "d" => Decimal(bits) + case "x" => Hexadecimal(bits) + case "b" => Binary(bits) + case "c" => Character(bits) + case c => throw new Exception(s"Illegal format specifier '$c'!") + } + } +} +/** Format bits as Decimal */ +case class Decimal(bits: Bits) extends FirrtlFormat('d') +/** Format bits as Hexidecimal */ +case class Hexadecimal(bits: Bits) extends FirrtlFormat('x') +/** Format bits as Binary */ +case class Binary(bits: Bits) extends FirrtlFormat('b') +/** Format bits as Character */ +case class Character(bits: Bits) extends FirrtlFormat('c') +/** Put innermost name (eg. field of bundle) */ +case class Name(data: Data) extends Printable { + final def unpack: (String, Iterable[String]) = (data.ref.name, List.empty) +} +/** Put full name within parent namespace (eg. bundleName.field) */ +case class FullName(hasId: HasId) extends Printable { + final def unpack: (String, Iterable[String]) = (hasId.instanceName, List.empty) +} +/** Represents escaped percents */ +case object Percent extends Printable { + final def unpack: (String, Iterable[String]) = ("%%", List.empty) +} diff --git a/chiselFrontend/src/main/scala/chisel3/core/Printf.scala b/chiselFrontend/src/main/scala/chisel3/core/Printf.scala index b0a3c955..55197425 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Printf.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Printf.scala @@ -10,6 +10,24 @@ import chisel3.internal.firrtl._ import chisel3.internal.sourceinfo.SourceInfo object printf { // scalastyle:ignore object.name + /** Helper for packing escape characters */ + private[chisel3] def format(formatIn: String): String = { + require(formatIn forall (c => c.toInt > 0 && c.toInt < 128), + "format strings must comprise non-null ASCII values") + 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 "" + } + /** Prints a message in simulation. * * Does not fire when in reset (defined as the encapsulating Module's @@ -23,14 +41,30 @@ object printf { // scalastyle:ignore object.name * @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:_*) + def apply(fmt: String, data: Bits*)(implicit sourceInfo: SourceInfo): Unit = + apply(Printable.pack(fmt, data:_*)) + /** 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 pable [[Printable]] to print + */ + def apply(pable: Printable)(implicit sourceInfo: SourceInfo): Unit = { + when (!Builder.dynamicContext.currentModule.get.reset) { + printfWithoutReset(pable) } } - private[core] def printfWithoutReset(fmt: String, data: Bits*)(implicit sourceInfo: SourceInfo) { + private[chisel3] def printfWithoutReset(pable: Printable)(implicit sourceInfo: SourceInfo): Unit = { val clock = Builder.dynamicContext.currentModule.get.clock - pushCommand(Printf(sourceInfo, Node(clock), fmt, data.map((d: Bits) => d.ref))) + pushCommand(Printf(sourceInfo, Node(clock), pable)) } + private[chisel3] def printfWithoutReset(fmt: String, data: Bits*)(implicit sourceInfo: SourceInfo): Unit = + printfWithoutReset(Printable.pack(fmt, data:_*)) } diff --git a/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala b/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala index 64d7d5fd..1f05b6e2 100644 --- a/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala +++ b/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala @@ -169,22 +169,6 @@ case class ConnectInit(sourceInfo: SourceInfo, loc: Node, exp: Arg) extends Comm 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 Printf(sourceInfo: SourceInfo, clk: Arg, pable: Printable) extends Command case class Circuit(name: String, components: Seq[Component]) diff --git a/src/main/scala/chisel3/internal/firrtl/Emitter.scala b/src/main/scala/chisel3/internal/firrtl/Emitter.scala index 8b94c68f..8ace27f9 100644 --- a/src/main/scala/chisel3/internal/firrtl/Emitter.scala +++ b/src/main/scala/chisel3/internal/firrtl/Emitter.scala @@ -25,7 +25,11 @@ private class Emitter(circuit: Circuit) { 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: Printf => + val (fmt, args) = e.pable.unpack + val printfArgs = Seq(e.clk.fullName(ctx), "UInt<1>(1)", + "\"" + printf.format(fmt) + "\"") ++ args + printfArgs mkString ("printf(", ", ", ")") case e: DefInvalid => s"${e.arg.fullName(ctx)} is invalid" case e: DefInstance => s"inst ${e.name} of ${e.id.modName}" case w: WhenBegin => diff --git a/src/main/scala/chisel3/package.scala b/src/main/scala/chisel3/package.scala index 0b548683..30e2b5c3 100644 --- a/src/main/scala/chisel3/package.scala +++ b/src/main/scala/chisel3/package.scala @@ -54,6 +54,27 @@ package object chisel3 { val when = chisel3.core.when type WhenContext = chisel3.core.WhenContext + type Printable = chisel3.core.Printable + val Printable = chisel3.core.Printable + type Printables = chisel3.core.Printables + val Printables = chisel3.core.Printables + type PString = chisel3.core.PString + val PString = chisel3.core.PString + type FirrtlFormat = chisel3.core.FirrtlFormat + val FirrtlFormat = chisel3.core.FirrtlFormat + type Decimal = chisel3.core.Decimal + val Decimal = chisel3.core.Decimal + type Hexadecimal = chisel3.core.Hexadecimal + val Hexadecimal = chisel3.core.Hexadecimal + type Binary = chisel3.core.Binary + val Binary = chisel3.core.Binary + type Character = chisel3.core.Character + val Character = chisel3.core.Character + type Name = chisel3.core.Name + val Name = chisel3.core.Name + type FullName = chisel3.core.FullName + val FullName = chisel3.core.FullName + val Percent = chisel3.core.Percent implicit class fromBigIntToLiteral(val x: BigInt) extends AnyVal { def U: UInt = UInt(x, Width()) @@ -79,4 +100,34 @@ package object chisel3 { def do_!= (that: BitPat)(implicit sourceInfo: SourceInfo): Bool = that != x def do_=/= (that: BitPat)(implicit sourceInfo: SourceInfo): Bool = that =/= x } + + /** Implicit for custom Printable string interpolator */ + implicit class PrintableHelper(val sc: StringContext) extends AnyVal { + /** Custom string interpolator for generating Printables: p"..." + * Will call .toString on any non-Printable arguments (mimicking s"...") + */ + def p(args: Any*): Printable = { + sc.checkLengths(args) // Enforce sc.parts.size == pargs.size + 1 + val pargs: Seq[Option[Printable]] = args map { + case p: Printable => Some(p) + case d: Data => Some(d.toPrintable) + case any => for { + v <- Option(any) // Handle null inputs + str = v.toString + if !str.isEmpty // Handle empty Strings + } yield PString(str) + } + val parts = sc.parts map StringContext.treatEscapes + // Zip sc.parts and pargs together ito flat Seq + // eg. Seq(sc.parts(0), pargs(0), sc.parts(1), pargs(1), ...) + val seq = for { // append None because sc.parts.size == pargs.size + 1 + (literal, arg) <- parts zip (pargs :+ None) + optPable <- Seq(Some(PString(literal)), arg) + pable <- optPable // Remove Option[_] + } yield pable + Printables(seq) + } + } + + implicit def string2Printable(str: String): Printable = PString(str) } diff --git a/src/test/scala/chiselTests/PrintableSpec.scala b/src/test/scala/chiselTests/PrintableSpec.scala new file mode 100644 index 00000000..a2c8c62a --- /dev/null +++ b/src/test/scala/chiselTests/PrintableSpec.scala @@ -0,0 +1,162 @@ +package chiselTests + +import org.scalatest.{FlatSpec, Matchers} +import scala.collection.mutable + +import chisel3._ +import chisel3.testers.BasicTester + +/* Printable Tests */ +class PrintableSpec extends FlatSpec with Matchers { + private val PrintfRegex = """\s*printf\((.*)\).*""".r + // This regex is brittle, it relies on the first two arguments of the printf + // not containing quotes, problematic if Chisel were to emit UInt<1>("h01") + // instead of the current UInt<1>(1) for the enable signal + private val StringRegex = """([^"]*)"(.*?)"(.*)""".r + private case class Printf(str: String, args: Seq[String]) + private def getPrintfs(firrtl: String): Seq[Printf] = { + def processArgs(str: String): Seq[String] = + str split "," map (_.trim) filter (_.nonEmpty) + def processBody(str: String): (String, Seq[String]) = { + str match { + case StringRegex(_, fmt, args) => + (fmt, processArgs(args)) + case _ => fail(s"Regex to process Printf should work on $str!") + } + } + + firrtl split "\n" collect { + case PrintfRegex(matched) => + val (str, args) = processBody(matched) + Printf(str, args) + } + } + + behavior of "Printable & Custom Interpolator" + + it should "pass exact strings through" in { + class MyModule extends BasicTester { + printf(p"An exact string") + } + val firrtl = Driver.emit(() => new MyModule) + getPrintfs(firrtl) match { + case Seq(Printf("An exact string", Seq())) => + case e => fail() + } + } + it should "handle Printable and String concatination" in { + class MyModule extends BasicTester { + printf(p"First " + PString("Second ") + "Third") + } + val firrtl = Driver.emit(() => new MyModule) + getPrintfs(firrtl) match { + case Seq(Printf("First Second Third", Seq())) => + case e => fail() + } + } + it should "call toString on non-Printable objects" in { + class MyModule extends BasicTester { + val myInt = 1234 + printf(p"myInt = $myInt") + } + val firrtl = Driver.emit(() => new MyModule) + getPrintfs(firrtl) match { + case Seq(Printf("myInt = 1234", Seq())) => + case e => fail() + } + } + it should "generate proper printf for simple Decimal printing" in { + class MyModule extends BasicTester { + val myWire = Wire(init = UInt(1234)) + printf(p"myWire = ${Decimal(myWire)}") + } + val firrtl = Driver.emit(() => new MyModule) + getPrintfs(firrtl) match { + case Seq(Printf("myWire = %d", Seq("myWire"))) => + case e => fail() + } + } + it should "handle printing literals" in { + class MyModule extends BasicTester { + printf(Decimal(UInt(10, 32))) + } + val firrtl = Driver.emit(() => new MyModule) + getPrintfs(firrtl) match { + case Seq(Printf("%d", Seq(lit))) => + assert(lit contains "UInt<32>") + case e => fail() + } + } + it should "correctly escape percent" in { + class MyModule extends BasicTester { + printf(p"%") + } + val firrtl = Driver.emit(() => new MyModule) + getPrintfs(firrtl) match { + case Seq(Printf("%%", Seq())) => + case e => fail() + } + } + it should "support names of circuit elements and the current module" in { + class MyBundle extends Bundle { + val foo = UInt(width = 32) + override def cloneType = (new MyBundle).asInstanceOf[this.type] + } + class MyModule extends BasicTester { + override def desiredName = "MyModule" + val myWire = Wire(new MyBundle) + printf(p"${Name(myWire.foo)}") + printf(p"${FullName(myWire.foo)}") + printf(p"${FullName(this)}") + } + val firrtl = Driver.emit(() => new MyModule) + getPrintfs(firrtl) match { + case Seq(Printf("foo", Seq()), + Printf("myWire.foo", Seq()), + Printf("MyModule", Seq())) => + case e => fail() + } + } + it should "print UInts and SInts as Decimal by default" in { + class MyModule extends BasicTester { + val myUInt = Wire(init = UInt(0)) + val mySInt = Wire(init = SInt(-1)) + printf(p"$myUInt & $mySInt") + } + val firrtl = Driver.emit(() => new MyModule) + getPrintfs(firrtl) match { + case Seq(Printf("%d & %d", Seq("myUInt", "mySInt"))) => + case e => fail() + } + } + it should "print Vecs like Scala Seqs by default" in { + class MyModule extends BasicTester { + val myVec = Wire(Vec(4, UInt(width = 32))) + myVec foreach (_ := UInt(0)) + printf(p"$myVec") + } + val firrtl = Driver.emit(() => new MyModule) + getPrintfs(firrtl) match { + case Seq(Printf("Vec(%d, %d, %d, %d)", + Seq("myVec[0]", "myVec[1]", "myVec[2]", "myVec[3]"))) => + case e => fail() + } + } + it should "print Bundles like Scala Maps by default" in { + class MyModule extends BasicTester { + val myBun = Wire(new Bundle { + val foo = UInt(width = 32) + val bar = UInt(width = 32) + }) + myBun.foo := UInt(0) + myBun.bar := UInt(0) + printf(p"$myBun") + } + val firrtl = Driver.emit(() => new MyModule) + getPrintfs(firrtl) match { + case Seq(Printf("Bundle(foo -> %d, bar -> %d)", + Seq("myBun.foo", "myBun.bar"))) => + case e => fail() + } + } +} diff --git a/src/test/scala/chiselTests/Printf.scala b/src/test/scala/chiselTests/Printf.scala index c872fde4..28b6132b 100644 --- a/src/test/scala/chiselTests/Printf.scala +++ b/src/test/scala/chiselTests/Printf.scala @@ -4,6 +4,7 @@ package chiselTests import org.scalatest._ import chisel3._ +import chisel3.util._ import chisel3.testers.BasicTester class SinglePrintfTester() extends BasicTester { @@ -24,6 +25,11 @@ class MultiPrintfTester() extends BasicTester { stop() } +class ASCIIPrintableTester extends BasicTester { + printf(PString((0x20 to 0x7e) map (_.toChar) mkString "")) + stop() +} + class PrintfSpec extends ChiselFlatSpec { "A printf with a single argument" should "run" in { assertTesterPasses { new SinglePrintfTester } @@ -34,4 +40,7 @@ class PrintfSpec extends ChiselFlatSpec { "A printf with ASCII characters 1-127" should "run" in { assertTesterPasses { new ASCIIPrintfTester } } + "A printf with Printable ASCII characters 1-127" should "run" in { + assertTesterPasses { new ASCIIPrintableTester } + } } -- cgit v1.2.3 From f793453ba6c4c42ef61eda3af8f04f7cadf80b95 Mon Sep 17 00:00:00 2001 From: jackkoenig Date: Wed, 7 Sep 2016 17:51:30 -0700 Subject: Fix bug in Printable FullName of submodule port Printable was using HasId.instanceName to get full names of Chisel nodes. instanceName uses the parent module of the HasId to get the Component to use in calling fullName on the underlying Ref. Unfortunately this means that any reference to a port of a instance will leave off the instance name. Fixing this required the following: - Add Component argument to Printable.unpack so that we can call Arg.fullName directly in the Printable - Pass the currently emitting module as the Component to Printable.unpack in the Emitter - Remove ability to create FullName Printables from Modules since the Module name is not known until after the printf is already emitted This commit also updates the PrintableSpec test to check that FullName and Decimal printing work on ports of instances --- .../src/main/scala/chisel3/core/Printable.scala | 24 +++++++++-------- .../scala/chisel3/internal/firrtl/Emitter.scala | 2 +- src/test/scala/chiselTests/PrintableSpec.scala | 31 +++++++++++++++++++--- 3 files changed, 42 insertions(+), 15 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/Printable.scala b/chiselFrontend/src/main/scala/chisel3/core/Printable.scala index 13d5d74e..f6e63936 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Printable.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Printable.scala @@ -15,6 +15,9 @@ import java.util.{ /** Superclass of things that can be printed in the resulting circuit * * Usually created using the custom string interpolator p"..." + * TODO Add support for names of Modules + * Currently impossible because unpack is called before the name is selected + * Could be implemented by adding a new format specifier to Firrtl (eg. %m) * TODO Should we provide more functions like map and mkPrintable? */ sealed abstract class Printable { @@ -22,7 +25,7 @@ sealed abstract class Printable { * @note This must be called after elaboration when Chisel nodes actually * have names */ - def unpack: (String, Iterable[String]) + def unpack(ctx: Component): (String, Iterable[String]) /** Allow for appending Printables like Strings */ final def +(that: Printable) = Printables(List(this, that)) /** Allow for appending Strings to Printables */ @@ -87,22 +90,21 @@ object Printable { case class Printables(pables: Iterable[Printable]) extends Printable { require(pables.hasDefiniteSize, "Infinite-sized iterables are not supported!") - final def unpack: (String, Iterable[String]) = { - val (fmts, args) = pables.map(_.unpack).unzip + final def unpack(ctx: Component): (String, Iterable[String]) = { + val (fmts, args) = pables.map(_ unpack ctx).unzip (fmts.mkString, args.flatten) } } /** Wrapper for printing Scala Strings */ case class PString(str: String) extends Printable { - final def unpack: (String, Iterable[String]) = + final def unpack(ctx: Component): (String, Iterable[String]) = (str replaceAll ("%", "%%"), List.empty) } /** Superclass for Firrtl format specifiers for Bits */ sealed abstract class FirrtlFormat(specifier: Char) extends Printable { def bits: Bits - def unpack: (String, Iterable[String]) = { - val id = if (bits.isLit) bits.ref.name else bits.instanceName - (s"%$specifier", List(id)) + def unpack(ctx: Component): (String, Iterable[String]) = { + (s"%$specifier", List(bits.ref.fullName(ctx))) } } object FirrtlFormat { @@ -138,13 +140,13 @@ case class Binary(bits: Bits) extends FirrtlFormat('b') case class Character(bits: Bits) extends FirrtlFormat('c') /** Put innermost name (eg. field of bundle) */ case class Name(data: Data) extends Printable { - final def unpack: (String, Iterable[String]) = (data.ref.name, List.empty) + final def unpack(ctx: Component): (String, Iterable[String]) = (data.ref.name, List.empty) } /** Put full name within parent namespace (eg. bundleName.field) */ -case class FullName(hasId: HasId) extends Printable { - final def unpack: (String, Iterable[String]) = (hasId.instanceName, List.empty) +case class FullName(data: Data) extends Printable { + final def unpack(ctx: Component): (String, Iterable[String]) = (data.ref.fullName(ctx), List.empty) } /** Represents escaped percents */ case object Percent extends Printable { - final def unpack: (String, Iterable[String]) = ("%%", List.empty) + final def unpack(ctx: Component): (String, Iterable[String]) = ("%%", List.empty) } diff --git a/src/main/scala/chisel3/internal/firrtl/Emitter.scala b/src/main/scala/chisel3/internal/firrtl/Emitter.scala index 8ace27f9..8849077d 100644 --- a/src/main/scala/chisel3/internal/firrtl/Emitter.scala +++ b/src/main/scala/chisel3/internal/firrtl/Emitter.scala @@ -26,7 +26,7 @@ private class Emitter(circuit: Circuit) { 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 => - val (fmt, args) = e.pable.unpack + val (fmt, args) = e.pable.unpack(ctx) val printfArgs = Seq(e.clk.fullName(ctx), "UInt<1>(1)", "\"" + printf.format(fmt) + "\"") ++ args printfArgs mkString ("printf(", ", ", ")") diff --git a/src/test/scala/chiselTests/PrintableSpec.scala b/src/test/scala/chiselTests/PrintableSpec.scala index a2c8c62a..12564a40 100644 --- a/src/test/scala/chiselTests/PrintableSpec.scala +++ b/src/test/scala/chiselTests/PrintableSpec.scala @@ -97,7 +97,14 @@ class PrintableSpec extends FlatSpec with Matchers { case e => fail() } } - it should "support names of circuit elements and the current module" in { + it should "support names of circuit elements including submodule IO" in { + // Submodule IO is a subtle issue because the Chisel element has a different + // parent module + class MySubModule extends Module { + val io = new Bundle { + val fizz = UInt(width = 32) + } + } class MyBundle extends Bundle { val foo = UInt(width = 32) override def cloneType = (new MyBundle).asInstanceOf[this.type] @@ -105,15 +112,33 @@ class PrintableSpec extends FlatSpec with Matchers { class MyModule extends BasicTester { override def desiredName = "MyModule" val myWire = Wire(new MyBundle) + val myInst = Module(new MySubModule) printf(p"${Name(myWire.foo)}") printf(p"${FullName(myWire.foo)}") - printf(p"${FullName(this)}") + printf(p"${FullName(myInst.io.fizz)}") } val firrtl = Driver.emit(() => new MyModule) + println(firrtl) getPrintfs(firrtl) match { case Seq(Printf("foo", Seq()), Printf("myWire.foo", Seq()), - Printf("MyModule", Seq())) => + Printf("myInst.io.fizz", Seq())) => + case e => fail() + } + } + it should "handle printing ports of submodules" in { + class MySubModule extends Module { + val io = new Bundle { + val fizz = UInt(width = 32) + } + } + class MyModule extends BasicTester { + val myInst = Module(new MySubModule) + printf(p"${myInst.io.fizz}") + } + val firrtl = Driver.emit(() => new MyModule) + getPrintfs(firrtl) match { + case Seq(Printf("%d", Seq("myInst.io.fizz"))) => case e => fail() } } -- cgit v1.2.3 From bb240453abf96b4c2d75ebb2cdc7e3159068431d Mon Sep 17 00:00:00 2001 From: Henry Cook Date: Thu, 8 Sep 2016 13:02:22 -0700 Subject: Add IrrevocableIO alternative to DecoupledIO (#274) Add IrrevocableIO subclass of DecoupledIO that promises not to change .bits on a cycle after .valid is high and .ready is low--- src/main/scala/chisel3/util/Decoupled.scala | 99 ++++++++++++++++++++++++----- 1 file changed, 83 insertions(+), 16 deletions(-) diff --git a/src/main/scala/chisel3/util/Decoupled.scala b/src/main/scala/chisel3/util/Decoupled.scala index f37a5c31..51f5bd6a 100644 --- a/src/main/scala/chisel3/util/Decoupled.scala +++ b/src/main/scala/chisel3/util/Decoupled.scala @@ -7,23 +7,68 @@ package chisel3.util 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 +/** An I/O Bundle containing 'valid' and 'ready' signals that handshake + * the transfer of data stored in the 'bits' subfield. + * The base protocol implied by the directionality is that the consumer + * uses the flipped interface. Actual semantics of ready/valid are + * enforced via use of concrete subclasses. + */ +abstract class ReadyValidIO[+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. +/** A concrete subclass of ReadyValidIO signalling that the user expects a + * "decoupled" interface: 'valid' indicates that the producer has + * put valid data in 'bits', and 'ready' indicates that the consumer is ready + * to accept the data this cycle. No requirements are placed on the signalling + * of ready or valid. */ -object Decoupled { +class DecoupledIO[+T <: Data](gen: T) extends ReadyValidIO[T](gen) +{ + override def cloneType: this.type = new DecoupledIO(gen).asInstanceOf[this.type] +} + +/** This factory adds a decoupled handshaking protocol to a data bundle. */ +object Decoupled +{ + /** Take any Data and wrap it in a DecoupledIO interface */ def apply[T <: Data](gen: T): DecoupledIO[T] = new DecoupledIO(gen) + + /** Take an IrrevocableIO and cast it to a DecoupledIO. + * This cast is only safe to do in cases where the IrrevocableIO + * is being produced as an output. + */ + def apply[T <: Data](irr: IrrevocableIO[T]): DecoupledIO[T] = { + require(irr.bits.dir == OUTPUT, "Only safe to cast produced Irrevocable bits to Decoupled.") + val d = Wire(new DecoupledIO(irr.bits)) + d.bits := irr.bits + d.valid := irr.valid + irr.ready := d.ready + d + } +} + +/** A concrete subclass of ReadyValidIO that promises to not change + * the value of 'bits' after a cycle where 'valid' is high and 'ready' is low. + * Additionally, once 'valid' is raised it will never be lowered until after + * 'ready' has also been raised. + */ +class IrrevocableIO[+T <: Data](gen: T) extends ReadyValidIO[T](gen) +{ + override def cloneType: this.type = new IrrevocableIO(gen).asInstanceOf[this.type] +} + +/** Factory adds an irrevocable handshaking protocol to a data bundle. */ +object Irrevocable +{ + def apply[T <: Data](gen: T): IrrevocableIO[T] = new IrrevocableIO(gen) } + /** An I/O bundle for enqueuing data with valid/ready handshaking * Initialization must be handled, if necessary, by the parent circuit */ @@ -103,7 +148,8 @@ class QueueIO[T <: Data](gen: T, entries: Int) extends Bundle * q.io.enq <> producer.io.out * consumer.io.in <> q.io.deq }}} */ -class Queue[T <: Data](gen: T, val entries: Int, +class Queue[T <: Data](gen: T, + val entries: Int, pipe: Boolean = false, flow: Boolean = false, override_reset: Option[Bool] = None) @@ -164,22 +210,43 @@ extends Module(override_reset=override_reset) { } } -/** 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 }}} +/** Factory for a generic hardware queue. Required parameter 'entries' controls + * the depth of the queues. The width of the queue is determined + * from the input 'enq'. + * + * Example usage: + * {{{ consumer.io.in <> Queue(producer.io.out, 16) }}} */ object Queue { - def apply[T <: Data](enq: DecoupledIO[T], entries: Int = 2, pipe: Boolean = false): DecoupledIO[T] = { + /** Create a queue and supply a DecoupledIO containing the product. */ + def apply[T <: Data]( + enq: ReadyValidIO[T], + entries: Int = 2, + pipe: Boolean = false, + flow: 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) } + + /** Create a queue and supply a IrrevocableIO containing the product. + * Casting from Decoupled is safe here because we know the Queue has + * Irrevocable semantics; we didn't want to change the return type of + * apply() for backwards compatibility reasons. + */ + def irrevocable[T <: Data]( + enq: ReadyValidIO[T], + entries: Int = 2, + pipe: Boolean = false, + flow: Boolean = false): IrrevocableIO[T] = { + val deq = apply(enq, entries, pipe) + val irr = Wire(new IrrevocableIO(deq.bits)) + irr.bits := deq.bits + irr.valid := deq.valid + deq.ready := irr.ready + irr + } } -- cgit v1.2.3 From 19f5b7c6841bda318288990e643eb02fa22a49e2 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Fri, 9 Sep 2016 17:23:14 -0700 Subject: Convert to NotStrict for internal connection checks. --- chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala | 4 ++-- chiselFrontend/src/main/scala/chisel3/core/Bits.scala | 2 +- chiselFrontend/src/main/scala/chisel3/core/Data.scala | 4 ++-- chiselFrontend/src/main/scala/chisel3/core/Mem.scala | 2 +- chiselFrontend/src/main/scala/chisel3/core/Reg.scala | 2 +- src/main/scala/chisel3/util/Reg.scala | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala index ed5a8fb3..596a7244 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala @@ -10,7 +10,7 @@ import chisel3.internal._ import chisel3.internal.Builder.pushCommand import chisel3.internal.firrtl._ import chisel3.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, VecTransform, SourceInfoTransform} -import chisel3.Strict.CompileOptions +import chisel3.NotStrict.CompileOptions /** An abstract class for data types that solely consist of (are an aggregate * of) other Data objects. @@ -189,7 +189,7 @@ sealed class Vec[T <: Data] private (gen: T, val length: Int) @deprecated("Use Vec.apply instead", "chisel3") def write(idx: UInt, data: T): Unit = { - apply(idx).:=(data)(DeprecatedSourceInfo, chisel3.Strict.CompileOptions) + apply(idx).:=(data)(DeprecatedSourceInfo, chisel3.NotStrict.CompileOptions) } override def cloneType: this.type = { diff --git a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala index 625f985d..8a8721f9 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala @@ -10,7 +10,7 @@ import chisel3.internal.firrtl._ import chisel3.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, SourceInfoTransform, SourceInfoWhiteboxTransform, UIntTransform, MuxTransform} import chisel3.internal.firrtl.PrimOp._ -import chisel3.Strict.CompileOptions +import chisel3.NotStrict.CompileOptions /** Element is a leaf data type: it cannot contain other Data objects. Example * uses are for representing primitive data types, like integers and bits. diff --git a/chiselFrontend/src/main/scala/chisel3/core/Data.scala b/chiselFrontend/src/main/scala/chisel3/core/Data.scala index bda06790..991b1898 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Data.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Data.scala @@ -8,7 +8,7 @@ import chisel3.internal._ import chisel3.internal.Builder.pushCommand import chisel3.internal.firrtl._ import chisel3.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, UnlocatableSourceInfo, WireTransform, SourceInfoTransform} -import chisel3.Strict.CompileOptions +import chisel3.NotStrict.CompileOptions sealed abstract class Direction(name: String) { override def toString: String = name @@ -255,7 +255,7 @@ object Wire { do_apply(t, init)(UnlocatableSourceInfo) def do_apply[T <: Data](t: T, init: T)(implicit sourceInfo: SourceInfo): T = { - val x = Reg.makeType(chisel3.Strict.CompileOptions, t, null.asInstanceOf[T], init) + val x = Reg.makeType(chisel3.NotStrict.CompileOptions, t, null.asInstanceOf[T], init) // Bind each element of x to being a Wire Binding.bind(x, WireBinder(Builder.forcedModule), "Error: t") diff --git a/chiselFrontend/src/main/scala/chisel3/core/Mem.scala b/chiselFrontend/src/main/scala/chisel3/core/Mem.scala index 327e119e..5eaaf262 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Mem.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Mem.scala @@ -8,7 +8,7 @@ import chisel3.internal._ import chisel3.internal.Builder.pushCommand import chisel3.internal.firrtl._ import chisel3.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, UnlocatableSourceInfo, MemTransform} -import chisel3.Strict.CompileOptions +import chisel3.NotStrict.CompileOptions 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/Reg.scala b/chiselFrontend/src/main/scala/chisel3/core/Reg.scala index d147a81d..2569e9ea 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Reg.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Reg.scala @@ -51,7 +51,7 @@ object Reg { */ def apply[T <: Data](outType: T)(implicit sourceInfo: SourceInfo, compileOptions: ExplicitCompileOptions): T = Reg[T](outType, null.asInstanceOf[T], null.asInstanceOf[T])(sourceInfo, compileOptions) - def do_apply[T <: Data](t: T, next: T, init: T)(implicit sourceInfo: SourceInfo, compileOptions: ExplicitCompileOptions = chisel3.Strict.CompileOptions): T = { + def do_apply[T <: Data](t: T, next: T, init: T)(implicit sourceInfo: SourceInfo, compileOptions: ExplicitCompileOptions = chisel3.NotStrict.CompileOptions): 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()). diff --git a/src/main/scala/chisel3/util/Reg.scala b/src/main/scala/chisel3/util/Reg.scala index 8a9c54a2..33508dcd 100644 --- a/src/main/scala/chisel3/util/Reg.scala +++ b/src/main/scala/chisel3/util/Reg.scala @@ -6,7 +6,7 @@ package chisel3.util import chisel3._ -import chisel3.Strict.CompileOptions +import chisel3.NotStrict.CompileOptions object RegNext { -- cgit v1.2.3 From 2ff229dac5f915e7f583cbf9cc8118674a4e52a5 Mon Sep 17 00:00:00 2001 From: Henry Cook Date: Tue, 13 Sep 2016 15:51:18 -0700 Subject: Bugfix: actually pass flow parameter from Queue factory to Queue module constructor --- src/main/scala/chisel3/util/Decoupled.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/chisel3/util/Decoupled.scala b/src/main/scala/chisel3/util/Decoupled.scala index 51f5bd6a..b2634bec 100644 --- a/src/main/scala/chisel3/util/Decoupled.scala +++ b/src/main/scala/chisel3/util/Decoupled.scala @@ -225,7 +225,7 @@ object Queue entries: Int = 2, pipe: Boolean = false, flow: Boolean = false): DecoupledIO[T] = { - val q = Module(new Queue(enq.bits.cloneType, entries, pipe)) + val q = Module(new Queue(enq.bits.cloneType, entries, pipe, flow)) 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 @@ -242,7 +242,7 @@ object Queue entries: Int = 2, pipe: Boolean = false, flow: Boolean = false): IrrevocableIO[T] = { - val deq = apply(enq, entries, pipe) + val deq = apply(enq, entries, pipe, flow) val irr = Wire(new IrrevocableIO(deq.bits)) irr.bits := deq.bits irr.valid := deq.valid -- cgit v1.2.3 From 920f6dc168d8e486733666368c7e363065b685ee Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Fri, 2 Sep 2016 12:53:08 -0700 Subject: Add direction-only (no width) UInt factory method. --- chiselFrontend/src/main/scala/chisel3/core/Bits.scala | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala index 8b3723f5..611a49be 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala @@ -558,6 +558,15 @@ private[core] sealed trait UIntFactory { case Direction.Unspecified => result } } + /** Create a UInt with a specified direction, but unspecified width - compatibility with Chisel2. */ + def apply(dir: Direction): UInt = { + val result = apply(Width()) + dir match { + case Direction.Input => Input(result) + case Direction.Output => Output(result) + case Direction.Unspecified => result + } + } private def parse(n: String) = { val (base, num) = n.splitAt(1) -- cgit v1.2.3 From 64e4df3d92727d83d5d627114d7002b97f901052 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Thu, 15 Sep 2016 14:36:29 -0700 Subject: Revert "Add direction-only (no width) UInt factory method." This reverts commit 920f6dc168d8e486733666368c7e363065b685ee. --- chiselFrontend/src/main/scala/chisel3/core/Bits.scala | 9 --------- 1 file changed, 9 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala index 611a49be..8b3723f5 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala @@ -558,15 +558,6 @@ private[core] sealed trait UIntFactory { case Direction.Unspecified => result } } - /** Create a UInt with a specified direction, but unspecified width - compatibility with Chisel2. */ - def apply(dir: Direction): UInt = { - val result = apply(Width()) - dir match { - case Direction.Input => Input(result) - case Direction.Output => Output(result) - case Direction.Unspecified => result - } - } private def parse(n: String) = { val (base, num) = n.splitAt(1) -- cgit v1.2.3 From dbf4278afbc5ce157ab1b946681a364f20778352 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Thu, 15 Sep 2016 15:42:21 -0700 Subject: move AddMethodsToDecoupled to ReadyValid --- src/main/scala/chisel3/util/Decoupled.scala | 41 ++++++++++++++++------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/src/main/scala/chisel3/util/Decoupled.scala b/src/main/scala/chisel3/util/Decoupled.scala index d178cec5..14637c9b 100644 --- a/src/main/scala/chisel3/util/Decoupled.scala +++ b/src/main/scala/chisel3/util/Decoupled.scala @@ -21,26 +21,9 @@ abstract class ReadyValidIO[+T <: Data](gen: T) extends Bundle val bits = Output(gen.chiselCloneType) } -object DecoupledIO { - /** Adds a ready-valid handshaking protocol to any interface. - * The standard used is that the consumer uses the flipped interface. - */ - def apply[T <: Data](gen: T): DecoupledIO[T] = new DecoupledIO(gen) +object ReadyValidIO { - /** Take an IrrevocableIO and cast it to a DecoupledIO. - * This cast is only safe to do in cases where the IrrevocableIO - * is being produced as an output. - */ - def apply[T <: Data](irr: IrrevocableIO[T]): DecoupledIO[T] = { - require(getFirrtlDirection(irr.bits) == OUTPUT, "Only safe to cast produced Irrevocable bits to Decoupled.") - val d = Wire(new DecoupledIO(irr.bits)) - d.bits := irr.bits - d.valid := irr.valid - irr.ready := d.ready - d - } - - implicit class AddMethodsToDecoupled[T<:Data](val target: DecoupledIO[T]) extends AnyVal { + implicit class AddMethodsToReadyValid[T<:Data](val target: ReadyValidIO[T]) extends AnyVal { def fire(): Bool = target.ready && target.valid /** push dat onto the output bits of this interface to let the consumer know it has happened. @@ -77,6 +60,26 @@ object DecoupledIO { target.ready := Bool(false) } } +} + +object DecoupledIO { + /** Adds a ready-valid handshaking protocol to any interface. + * The standard used is that the consumer uses the flipped interface. + */ + def apply[T <: Data](gen: T): DecoupledIO[T] = new DecoupledIO(gen) + + /** Take an IrrevocableIO and cast it to a DecoupledIO. + * This cast is only safe to do in cases where the IrrevocableIO + * is being produced as an output. + */ + def apply[T <: Data](irr: IrrevocableIO[T]): DecoupledIO[T] = { + require(getFirrtlDirection(irr.bits) == OUTPUT, "Only safe to cast produced Irrevocable bits to Decoupled.") + val d = Wire(new DecoupledIO(irr.bits)) + d.bits := irr.bits + d.valid := irr.valid + irr.ready := d.ready + d + } // override def cloneType: this.type = { // DeqIO(gen).asInstanceOf[this.type] // } -- cgit v1.2.3 From 53721ff4fd53f27edd75de8eb649a2e20390cceb Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Thu, 15 Sep 2016 15:43:52 -0700 Subject: add optional directionality assumption to BiConnect.elemConnect --- chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala b/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala index b0be1c38..ce70a19a 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala @@ -217,8 +217,18 @@ object BiConnect { case (Some(Input), Some(Input)) => throw NeitherDriverException case (Some(Output), Some(Output)) => throw BothDriversException - case (_, None) => throw UnknownRelationException - case (None, _) => throw UnknownRelationException + case (_, None) => + if (connectCompileOptions.dontAssumeDirectionality) { + throw UnknownRelationException + } else { + issueConnectR2L(left, right) + } + case (None, _) => + if (connectCompileOptions.dontAssumeDirectionality) { + throw UnknownRelationException + } else { + issueConnectR2L(left, right) + } } } -- cgit v1.2.3 From dda64c1dee16b5da15ac690bd3cd6759c3d5c032 Mon Sep 17 00:00:00 2001 From: Wesley W. Terpstra Date: Thu, 15 Sep 2016 19:08:30 -0700 Subject: Decoupled: cast DecoupledIO to IrrevocableIO as an input (#280) --- src/main/scala/chisel3/util/Decoupled.scala | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/main/scala/chisel3/util/Decoupled.scala b/src/main/scala/chisel3/util/Decoupled.scala index b2634bec..77990777 100644 --- a/src/main/scala/chisel3/util/Decoupled.scala +++ b/src/main/scala/chisel3/util/Decoupled.scala @@ -66,6 +66,19 @@ class IrrevocableIO[+T <: Data](gen: T) extends ReadyValidIO[T](gen) object Irrevocable { def apply[T <: Data](gen: T): IrrevocableIO[T] = new IrrevocableIO(gen) + + /** Take a DecoupledIO and cast it to an IrrevocableIO. + * This cast is only safe to do in cases where the IrrevocableIO + * is being consumed as an input. + */ + def apply[T <: Data](dec: DecoupledIO[T]): IrrevocableIO[T] = { + require(dec.bits.dir == INPUT, "Only safe to cast consumed Decoupled bits to Irrevocable.") + val i = Wire(new IrrevocableIO(dec.bits)) + dec.bits := i.bits + dec.valid := i.valid + i.ready := dec.ready + i + } } -- cgit v1.2.3 From 6d8acee760c8c41fcae2ab252161bac96e6954dc Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Fri, 16 Sep 2016 09:07:15 -0700 Subject: Rename DecoupledIO object to Decoupled (compatibility). --- src/main/scala/chisel3/compatibility.scala | 4 ++-- src/main/scala/chisel3/package.scala | 2 +- src/main/scala/chisel3/util/Arbiter.scala | 4 ++-- src/main/scala/chisel3/util/Decoupled.scala | 6 +++--- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/scala/chisel3/compatibility.scala b/src/main/scala/chisel3/compatibility.scala index 49b8bb2c..3b1b5b0a 100644 --- a/src/main/scala/chisel3/compatibility.scala +++ b/src/main/scala/chisel3/compatibility.scala @@ -146,8 +146,8 @@ package object Chisel { // scalastyle:ignore package.object.name val Counter = chisel3.util.Counter type DecoupledIO[+T <: Data] = chisel3.util.DecoupledIO[T] - val DecoupledIO = chisel3.util.DecoupledIO - val Decoupled = chisel3.util.DecoupledIO + val DecoupledIO = chisel3.util.Decoupled + val Decoupled = chisel3.util.Decoupled class EnqIO[+T <: Data](gen: T) extends DecoupledIO(gen) { def init(): Unit = { this.noenq() diff --git a/src/main/scala/chisel3/package.scala b/src/main/scala/chisel3/package.scala index 8f01779f..24deb64f 100644 --- a/src/main/scala/chisel3/package.scala +++ b/src/main/scala/chisel3/package.scala @@ -167,7 +167,7 @@ package object chisel3 { // scalastyle:ignore package.object.name type ChiselException = chisel3.internal.ChiselException type ValidIO[+T <: Data] = chisel3.util.Valid[T] val ValidIO = chisel3.util.Valid - val Decoupled = chisel3.util.DecoupledIO + val DecoupledIO = chisel3.util.Decoupled class EnqIO[+T <: Data](gen: T) extends DecoupledIO(gen) { def init(): Unit = { diff --git a/src/main/scala/chisel3/util/Arbiter.scala b/src/main/scala/chisel3/util/Arbiter.scala index 5d46b7b9..c80f1908 100644 --- a/src/main/scala/chisel3/util/Arbiter.scala +++ b/src/main/scala/chisel3/util/Arbiter.scala @@ -10,8 +10,8 @@ import chisel3.NotStrict.CompileOptions /** An I/O bundle for the Arbiter */ class ArbiterIO[T <: Data](gen: T, n: Int) extends Bundle { - val in = Flipped(Vec(n, DecoupledIO(gen))) - val out = DecoupledIO(gen) + val in = Flipped(Vec(n, Decoupled(gen))) + val out = Decoupled(gen) val chosen = Output(UInt.width(log2Up(n))) } diff --git a/src/main/scala/chisel3/util/Decoupled.scala b/src/main/scala/chisel3/util/Decoupled.scala index 14637c9b..7c377bfb 100644 --- a/src/main/scala/chisel3/util/Decoupled.scala +++ b/src/main/scala/chisel3/util/Decoupled.scala @@ -62,7 +62,7 @@ object ReadyValidIO { } } -object DecoupledIO { +object Decoupled { /** Adds a ready-valid handshaking protocol to any interface. * The standard used is that the consumer uses the flipped interface. */ @@ -113,10 +113,10 @@ object Irrevocable } object EnqIO { - def apply[T<:Data](gen: T): DecoupledIO[T] = DecoupledIO(gen) + def apply[T<:Data](gen: T): DecoupledIO[T] = Decoupled(gen) } object DeqIO { - def apply[T<:Data](gen: T): DecoupledIO[T] = Flipped(DecoupledIO(gen)) + def apply[T<:Data](gen: T): DecoupledIO[T] = Flipped(Decoupled(gen)) } /** An I/O Bundle for Queues -- cgit v1.2.3 From a2cb95bfe9e9c30b73284e97048fa0187ab0ee1d Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Wed, 21 Sep 2016 12:44:36 -0700 Subject: Make implicit clock name consistent (#288) In the Chisel frontend, the implicit clock is named clock, but in the generated FIRRTL, it is named clk. There is no reason for this discrepancy, and yet fixing it is painful, as it will break test harnesses. Better to take the pain now than later. Resolves #258.--- chiselFrontend/src/main/scala/chisel3/core/Module.scala | 2 +- chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala | 4 ++-- src/main/resources/top.cpp | 8 ++++---- src/main/scala/chisel3/internal/firrtl/Emitter.scala | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/Module.scala b/chiselFrontend/src/main/scala/chisel3/core/Module.scala index 2426ae78..8093babc 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Module.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Module.scala @@ -94,7 +94,7 @@ extends HasId { private[chisel3] def addId(d: HasId) { _ids += d } private[core] def ports: Seq[(String,Data)] = Vector( - ("clk", clock), ("reset", reset), ("io", io) + ("clock", clock), ("reset", reset), ("io", io) ) private[core] def computePorts = for((name, port) <- ports) yield { diff --git a/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala b/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala index 1f05b6e2..e39b007e 100644 --- a/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala +++ b/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala @@ -166,9 +166,9 @@ 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 Stop(sourceInfo: SourceInfo, clock: 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, pable: Printable) extends Command +case class Printf(sourceInfo: SourceInfo, clock: Arg, pable: Printable) extends Command case class Circuit(name: String, components: Seq[Component]) diff --git a/src/main/resources/top.cpp b/src/main/resources/top.cpp index 8bfe2a99..075d7085 100644 --- a/src/main/resources/top.cpp +++ b/src/main/resources/top.cpp @@ -44,10 +44,10 @@ int main(int argc, char** argv) { top->reset = 0; // Deassert reset } if ((main_time % 10) == 1) { - top->clk = 1; // Toggle clock + top->clock = 1; // Toggle clock } if ((main_time % 10) == 6) { - top->clk = 0; + top->clock = 0; } top->eval(); // Evaluate model #if VM_TRACE @@ -69,10 +69,10 @@ int main(int argc, char** argv) { vluint64_t end_time = main_time + 100; while (main_time < end_time) { if ((main_time % 10) == 1) { - top->clk = 1; // Toggle clock + top->clock = 1; // Toggle clock } if ((main_time % 10) == 6) { - top->clk = 0; + top->clock = 0; } top->eval(); // Evaluate model #if VM_TRACE diff --git a/src/main/scala/chisel3/internal/firrtl/Emitter.scala b/src/main/scala/chisel3/internal/firrtl/Emitter.scala index 8849077d..f1908089 100644 --- a/src/main/scala/chisel3/internal/firrtl/Emitter.scala +++ b/src/main/scala/chisel3/internal/firrtl/Emitter.scala @@ -24,10 +24,10 @@ private class Emitter(circuit: Circuit) { 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: Stop => s"stop(${e.clock.fullName(ctx)}, UInt<1>(1), ${e.ret})" case e: Printf => val (fmt, args) = e.pable.unpack(ctx) - val printfArgs = Seq(e.clk.fullName(ctx), "UInt<1>(1)", + val printfArgs = Seq(e.clock.fullName(ctx), "UInt<1>(1)", "\"" + printf.format(fmt) + "\"") ++ args printfArgs mkString ("printf(", ", ", ")") case e: DefInvalid => s"${e.arg.fullName(ctx)} is invalid" -- cgit v1.2.3 From 9c88d767e04ac25ab72380c39f30e39c83abf563 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Wed, 21 Sep 2016 15:22:54 -0700 Subject: Use correct scope for util synonyms. --- src/main/scala/chisel3/package.scala | 3 --- src/main/scala/chisel3/util/util.scala | 12 ++++++++++++ 2 files changed, 12 insertions(+), 3 deletions(-) create mode 100644 src/main/scala/chisel3/util/util.scala diff --git a/src/main/scala/chisel3/package.scala b/src/main/scala/chisel3/package.scala index 24deb64f..17ddd55a 100644 --- a/src/main/scala/chisel3/package.scala +++ b/src/main/scala/chisel3/package.scala @@ -165,9 +165,6 @@ package object chisel3 { // scalastyle:ignore package.object.name val OUTPUT = chisel3.core.Direction.Output val NODIR = chisel3.core.Direction.Unspecified type ChiselException = chisel3.internal.ChiselException - type ValidIO[+T <: Data] = chisel3.util.Valid[T] - val ValidIO = chisel3.util.Valid - val DecoupledIO = chisel3.util.Decoupled class EnqIO[+T <: Data](gen: T) extends DecoupledIO(gen) { def init(): Unit = { diff --git a/src/main/scala/chisel3/util/util.scala b/src/main/scala/chisel3/util/util.scala new file mode 100644 index 00000000..812af21c --- /dev/null +++ b/src/main/scala/chisel3/util/util.scala @@ -0,0 +1,12 @@ +// See LICENSE for license details. + +package chisel3 + +package object util { + + /** Synonyms, moved from main package object - maintain scope. */ + type ValidIO[+T <: Data] = chisel3.util.Valid[T] + val ValidIO = chisel3.util.Valid + val DecoupledIO = chisel3.util.Decoupled + +} -- cgit v1.2.3 From b18e98ba2d058c7dd24f96f005486b70c856aeca Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Wed, 21 Sep 2016 16:16:25 -0700 Subject: Expose FIRRTL asClock construct Additionally, fix Clock.asUInt (previously, it threw an esoteric exception), and add a simple test of both.--- .../src/main/scala/chisel3/core/Bits.scala | 5 +++++ .../src/main/scala/chisel3/core/Data.scala | 5 ++++- .../main/scala/chisel3/internal/firrtl/IR.scala | 1 + src/test/scala/chiselTests/Clock.scala | 22 ++++++++++++++++++++++ 4 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 src/test/scala/chiselTests/Clock.scala diff --git a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala index 77a31252..d7464efa 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala @@ -699,6 +699,11 @@ sealed class Bool(dir: Direction, lit: Option[ULit] = None) extends UInt(dir, Wi def && (that: Bool): Bool = macro SourceInfoTransform.thatArg def do_&& (that: Bool)(implicit sourceInfo: SourceInfo): Bool = this & that + + /** Reinterprets this Bool as a Clock. */ + def asClock(): Clock = macro SourceInfoTransform.noArg + + def do_asClock(implicit sourceInfo: SourceInfo): Clock = pushOp(DefPrim(sourceInfo, Clock(), AsClockOp, ref)) } object Bool { diff --git a/chiselFrontend/src/main/scala/chisel3/core/Data.scala b/chiselFrontend/src/main/scala/chisel3/core/Data.scala index 573632ab..197b6181 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Data.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Data.scala @@ -5,9 +5,10 @@ package chisel3.core import scala.language.experimental.macros import chisel3.internal._ -import chisel3.internal.Builder.pushCommand +import chisel3.internal.Builder.{pushCommand, pushOp} import chisel3.internal.firrtl._ import chisel3.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, UnlocatableSourceInfo, WireTransform, SourceInfoTransform} +import chisel3.internal.firrtl.PrimOp.AsUIntOp sealed abstract class Direction(name: String) { override def toString: String = name @@ -177,4 +178,6 @@ sealed class Clock(dirArg: Direction) extends Element(dirArg, Width(1)) { /** Not really supported */ def toPrintable: Printable = PString("CLOCK") + + override def do_asUInt(implicit sourceInfo: SourceInfo): UInt = pushOp(DefPrim(sourceInfo, UInt(this.width), AsUIntOp, ref)) } diff --git a/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala b/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala index e39b007e..0641686c 100644 --- a/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala +++ b/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala @@ -42,6 +42,7 @@ object PrimOp { val ConvertOp = PrimOp("cvt") val AsUIntOp = PrimOp("asUInt") val AsSIntOp = PrimOp("asSInt") + val AsClockOp = PrimOp("asClock") } abstract class Arg { diff --git a/src/test/scala/chiselTests/Clock.scala b/src/test/scala/chiselTests/Clock.scala new file mode 100644 index 00000000..79dd2de4 --- /dev/null +++ b/src/test/scala/chiselTests/Clock.scala @@ -0,0 +1,22 @@ +// See LICENSE for license details. + +package chiselTests + +import org.scalatest._ +import org.scalatest.prop._ + +import chisel3._ +import chisel3.testers.BasicTester +import chisel3.util._ + +class ClockAsUIntTester extends BasicTester { + assert(Bool(true).asClock.asUInt === UInt(1)) + stop() +} + + +class ClockSpec extends ChiselPropSpec { + property("Bool.asClock.asUInt should pass a signal through unaltered") { + assertTesterPasses { new ClockAsUIntTester } + } +} -- cgit v1.2.3 From 6eb00023fcc3ad77b98e51971f6e193ea506b9cc Mon Sep 17 00:00:00 2001 From: ducky Date: Wed, 21 Sep 2016 17:59:38 -0700 Subject: Improved scaladoc in utils and friends --- .../src/main/scala/chisel3/core/SeqUtils.scala | 18 ++++++-- src/main/scala/chisel3/util/Cat.scala | 13 +++--- src/main/scala/chisel3/util/CircuitMath.scala | 14 +++--- src/main/scala/chisel3/util/Conditional.scala | 50 ++++++++++++++++------ src/main/scala/chisel3/util/Counter.scala | 25 ++++++++--- src/main/scala/chisel3/util/OneHot.scala | 24 ++++++----- src/main/scala/chisel3/util/Reg.scala | 38 +++++++++------- 7 files changed, 119 insertions(+), 63 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala b/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala index 63bcc87f..0d8604cd 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala @@ -7,7 +7,12 @@ import scala.language.experimental.macros import chisel3.internal.sourceinfo.{SourceInfo, SourceInfoTransform} private[chisel3] object SeqUtils { - /** Equivalent to Cat(r(n-1), ..., r(0)) */ + /** Concatenates the data elements of the input sequence, in sequence order, together. + * The first element of the sequence forms the least significant bits, while the last element + * in the sequence forms the most significant bits. + * + * Equivalent to r(n-1) ## ... ## r(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 = { @@ -20,7 +25,8 @@ private[chisel3] object SeqUtils { } } - /** Counts the number of true Bools in a Seq */ + /** Outputs the number of elements that === Bool(true). + */ def count(in: Seq[Bool]): UInt = macro SourceInfoTransform.inArg def do_count(in: Seq[Bool])(implicit sourceInfo: SourceInfo): UInt = in.size match { @@ -29,7 +35,8 @@ private[chisel3] object SeqUtils { case n => count(in take n/2) +& count(in drop n/2) } - /** Returns data value corresponding to first true predicate */ + /** Returns the data value corresponding to the 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 = { @@ -40,7 +47,10 @@ private[chisel3] object SeqUtils { } } - /** Returns data value corresponding to lone true predicate */ + /** Returns the data value corresponding to the lone true predicate. + * + * @note assumes exactly one true predicate, results undefined otherwise + */ 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 = { diff --git a/src/main/scala/chisel3/util/Cat.scala b/src/main/scala/chisel3/util/Cat.scala index 469bf9ab..ba12a7d4 100644 --- a/src/main/scala/chisel3/util/Cat.scala +++ b/src/main/scala/chisel3/util/Cat.scala @@ -6,16 +6,15 @@ import chisel3._ import chisel3.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 + /** Concatenates the argument data elements, in argument order, 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 + /** Concatenates the data elements of the input sequence, in reverse sequence order, together. + * The first element of the sequence forms the most significant bits, while the last element + * in the sequence forms the least significant bits. + * + * Equivalent to r(0) ## r(1) ## ... ## r(n-1). */ 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 index a64447d9..d478e10e 100644 --- a/src/main/scala/chisel3/util/CircuitMath.scala +++ b/src/main/scala/chisel3/util/CircuitMath.scala @@ -7,13 +7,11 @@ package chisel3.util import chisel3._ -/** Compute the base-2 integer logarithm of a UInt - * @example - * {{{ data_out := Log2(data_in) }}} - * @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 */ + /** Returns the base-2 integer logarithm of the least-significant `width` bits of an UInt. + * + * @note The result is truncated, so e.g. Log2(UInt(13)) === UInt(3) + */ def apply(x: Bits, width: Int): UInt = { if (width < 2) { UInt(0) @@ -30,6 +28,10 @@ object Log2 { } } + /** Returns the base-2 integer logarithm of an UInt. + * + * @note The result is truncated, so e.g. Log2(UInt(13)) === UInt(3) + */ def apply(x: Bits): UInt = apply(x, x.getWidth) private def divideAndConquerThreshold = 4 diff --git a/src/main/scala/chisel3/util/Conditional.scala b/src/main/scala/chisel3/util/Conditional.scala index 6218feb0..461ff765 100644 --- a/src/main/scala/chisel3/util/Conditional.scala +++ b/src/main/scala/chisel3/util/Conditional.scala @@ -12,50 +12,72 @@ import scala.reflect.macros.blackbox._ import chisel3._ -/** This is identical to [[Chisel.when when]] with the condition inverted */ object unless { // scalastyle:ignore object.name + /** Does the same thing as [[when$ when]], but with the condition inverted. + */ def apply(c: Bool)(block: => Unit) { when (!c) { block } } } +/** Implementation details for [[switch]]. See [[switch]] and [[chisel3.util.is is]] for the + * user-facing API. + */ class SwitchContext[T <: Bits](cond: T) { def is(v: Iterable[T])(block: => Unit) { - if (!v.isEmpty) when (v.map(_.asUInt === cond.asUInt).reduce(_||_)) { block } + 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 */ +/** Use to specify cases in a [[switch]] block, equivalent to a [[when$ when]] block comparing to + * the condition variable. + * + * @note illegal outside a [[switch]] block + * @note multiple conditions may fire simultaneously + * @note dummy implementation, a macro inside [[switch]] transforms this into the actual + * implementation + */ object is { // scalastyle:ignore object.name - // Begin deprecation of non-type-parameterized is statements. + // TODO: Begin deprecation of non-type-parameterized is statements. + /** Executes `block` if the switch condition is equal to any of the values in `v`. + */ def apply(v: Iterable[Bits])(block: => Unit) { require(false, "The 'is' keyword may not be used outside of a switch.") } + /** Executes `block` if the switch condition is equal to `v`. + */ def apply(v: Bits)(block: => Unit) { require(false, "The 'is' keyword may not be used outside of a switch.") } + /** Executes `block` if the switch condition is equal to any of the values in the argument list. + */ 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 +/** Conditional logic to form a switch block. See [[is$ is]] for the case API. + * * @example - * {{{ ... // default values here - * switch ( myState ) { - * is( state1 ) { - * ... // some logic here + * {{{ + * switch (myState) { + * is (state1) { + * // some logic here that runs when myState === state1 * } - * is( state2 ) { - * ... // some logic here + * is (state2) { + * // some logic here that runs when myState === state2 * } - * } }}}*/ + * } + * }}} + */ 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._ diff --git a/src/main/scala/chisel3/util/Counter.scala b/src/main/scala/chisel3/util/Counter.scala index 1c95190b..4b20158f 100644 --- a/src/main/scala/chisel3/util/Counter.scala +++ b/src/main/scala/chisel3/util/Counter.scala @@ -5,12 +5,14 @@ package chisel3.util import chisel3._ /** 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. @@ -29,14 +31,27 @@ class Counter(val n: Int) { } } -/** Counter Object - * Example Usage: - * {{{ val countOn = Bool(true) // increment counter every clock cycle - * val (myCounterValue, myCounterWrap) = Counter(countOn, n) - * when ( myCounterValue === UInt(3) ) { ... } }}}*/ object Counter { + /** Instantiate a [[Counter! counter]] with the specified number of counts. + */ def apply(n: Int): Counter = new Counter(n) + + /** Instantiate a [[Counter! counter]] with the specified number of counts and a gate. + * + * @param cond condition that controls whether the counter increments this cycle + * @param n number of counts before the counter resets + * @return tuple of the counter value and whether the counter will wrap (the value is at + * maximum and the condition is true). + * + * @example {{{ + * val countOn = Bool(true) // increment counter every clock cycle + * val (counterValue, counterWrap) = Counter(countOn, 4) + * when (counterValue === UInt(3)) { + * ... + * } + * }}} + */ def apply(cond: Bool, n: Int): (UInt, Bool) = { val c = new Counter(n) var wrap: Bool = null diff --git a/src/main/scala/chisel3/util/OneHot.scala b/src/main/scala/chisel3/util/OneHot.scala index 7e04a8d7..53ba8c3d 100644 --- a/src/main/scala/chisel3/util/OneHot.scala +++ b/src/main/scala/chisel3/util/OneHot.scala @@ -7,8 +7,12 @@ package chisel3.util import chisel3._ -/** Converts from One Hot Encoding to a UInt indicating which bit is active - * This is the inverse of [[Chisel.UIntToOH UIntToOH]]*/ +/** Returns the bit position of the sole high bit of the input bitvector. + * + * Inverse operation of [[UIntToOH]]. + * + * @note assumes exactly one high bit, results undefined otherwise + */ object OHToUInt { def apply(in: Seq[Bool]): UInt = apply(Cat(in.reverse), in.size) def apply(in: Vec[Bool]): UInt = apply(in.asUInt, in.size) @@ -26,9 +30,9 @@ object OHToUInt { } } -/** @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) }}} +/** Returns the bit position of the least-significant high bit of the input bitvector. + * + * Multiple bits may be high in the input. */ object PriorityEncoder { def apply(in: Seq[Bool]): UInt = PriorityMux(in, (0 until in.size).map(UInt(_))) @@ -37,8 +41,7 @@ object PriorityEncoder { /** Returns the one hot encoding of the input UInt. */ -object UIntToOH -{ +object UIntToOH { def apply(in: UInt, width: Int = -1): UInt = if (width == -1) { UInt(1) << in @@ -47,11 +50,10 @@ object UIntToOH } } -/** Returns a bit vector in which only the least-significant 1 bit in - the input vector, if any, is set. +/** Returns a bit vector in which only the least-significant 1 bit in the input vector, if any, + * is set. */ -object PriorityEncoderOH -{ +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)) diff --git a/src/main/scala/chisel3/util/Reg.scala b/src/main/scala/chisel3/util/Reg.scala index 81de4754..80a3f43e 100644 --- a/src/main/scala/chisel3/util/Reg.scala +++ b/src/main/scala/chisel3/util/Reg.scala @@ -1,34 +1,40 @@ // See LICENSE for license details. -/** Variations and helpers for registers. - */ - package chisel3.util import chisel3._ object RegNext { - + /** Returns a register with the specified next and no reset initialization. + * + * Essentially a 1-cycle delayed version of the input signal. + */ def apply[T <: Data](next: T): T = Reg[T](null.asInstanceOf[T], next, null.asInstanceOf[T]) + /** Returns a register with the specified next and reset initialization. + * + * Essentially a 1-cycle delayed version of the input signal. + */ def apply[T <: Data](next: T, init: T): T = Reg[T](null.asInstanceOf[T], next, init) - } object RegInit { - + /** Returns a register pre-initialized (on reset) to the specified value. + */ def apply[T <: Data](init: T): T = Reg[T](null.asInstanceOf[T], null.asInstanceOf[T], init) - } -/** A register with an Enable signal */ -object RegEnable -{ +object RegEnable { + /** Returns a register with the specified next, update enable gate, and no reset initialization. + */ def apply[T <: Data](updateData: T, enable: Bool): T = { val r = Reg(updateData) when (enable) { r := updateData } r } + + /** Returns a register with the specified next, update enable gate, and reset initialization. + */ def apply[T <: Data](updateData: T, resetData: T, enable: Bool): T = { val r = RegInit(resetData) when (enable) { r := updateData } @@ -36,15 +42,15 @@ object RegEnable } } -/** Returns the n-cycle delayed version of the input signal. - */ object ShiftRegister { - /** @param in input to delay + /** Returns the n-cycle delayed version of the input signal. + * + * @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 = - { + * @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) -- cgit v1.2.3 From decb2ee0f0bb8223f0b2b067b88ed90b71473a28 Mon Sep 17 00:00:00 2001 From: ducky Date: Thu, 22 Sep 2016 15:21:48 -0700 Subject: Update rest of docs --- src/main/scala/chisel3/util/Arbiter.scala | 45 ++++++++++++++++----------- src/main/scala/chisel3/util/BitPat.scala | 2 +- src/main/scala/chisel3/util/Bitwise.scala | 26 +++++++++++----- src/main/scala/chisel3/util/Conditional.scala | 5 ++- src/main/scala/chisel3/util/Decoupled.scala | 42 ++++++++++++++----------- src/main/scala/chisel3/util/Enum.scala | 36 +++++++++++++++++++-- src/main/scala/chisel3/util/LFSR.scala | 13 ++++---- src/main/scala/chisel3/util/Mux.scala | 23 +++++++------- 8 files changed, 123 insertions(+), 69 deletions(-) diff --git a/src/main/scala/chisel3/util/Arbiter.scala b/src/main/scala/chisel3/util/Arbiter.scala index eb541977..58ba1188 100644 --- a/src/main/scala/chisel3/util/Arbiter.scala +++ b/src/main/scala/chisel3/util/Arbiter.scala @@ -7,16 +7,21 @@ package chisel3.util import chisel3._ -/** An I/O bundle for the Arbiter */ +/** IO bundle definition for an Arbiter, which takes some number of ready-valid inputs and outputs + * (selects) at most one. + * + * @param gen data type + * @param n number of inputs + */ 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 -{ +/** 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)) @@ -81,25 +86,27 @@ class LockingArbiter[T <: Data](gen: T, n: Int, count: Int, needsLock: Option[T } /** 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 + * Producers are chosen in round robin order. + * + * @example {{{ + * 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 - */ + * Priority is given to lower producer. + * + * @example {{{ + * 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) diff --git a/src/main/scala/chisel3/util/BitPat.scala b/src/main/scala/chisel3/util/BitPat.scala index 26106080..6c012583 100644 --- a/src/main/scala/chisel3/util/BitPat.scala +++ b/src/main/scala/chisel3/util/BitPat.scala @@ -37,7 +37,7 @@ object BitPat { /** 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 + * @note legal characters are '0', '1', and '?', as well as '_' and white * space (which are ignored) */ def apply(n: String): BitPat = { diff --git a/src/main/scala/chisel3/util/Bitwise.scala b/src/main/scala/chisel3/util/Bitwise.scala index 6451ab14..7d5ffe09 100644 --- a/src/main/scala/chisel3/util/Bitwise.scala +++ b/src/main/scala/chisel3/util/Bitwise.scala @@ -8,9 +8,18 @@ package chisel3.util import chisel3._ import chisel3.core.SeqUtils -object FillInterleaved -{ +object FillInterleaved { + /** Creates n repetitions of each bit of x in order. + * + * Output data-equivalent to in(size(in)-1) (n times) ## ... ## in(1) (n times) ## in(0) (n times) + * For example, FillInterleaved(2, "b1000") === UInt("b11 00 00 00") + */ def apply(n: Int, in: UInt): UInt = apply(n, in.toBools) + + /** Creates n repetitions of each bit of x in order. + * + * Output data-equivalent to in(size(in)-1) (n times) ## ... ## in(1) (n times) ## in(0) (n times) + */ def apply(n: Int, in: Seq[Bool]): UInt = Cat(in.map(Fill(n, _)).reverse) } @@ -22,9 +31,11 @@ object PopCount 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 */ + /** Create n repetitions of x using a tree fanout topology. + * + * Output data-equivalent to x ## x ## ... ## x (n repetitions). + */ def apply(n: Int, x: UInt): UInt = { n match { case 0 => UInt(width=0) @@ -42,10 +53,7 @@ object Fill { } } -/** Litte/big bit endian convertion: reverse the order of the bits in a UInt. -*/ -object Reverse -{ +object Reverse { private def doit(in: UInt, length: Int): UInt = { if (length == 1) { in @@ -65,5 +73,7 @@ object Reverse Cat(doit(in(half-1,0), half), doit(in(length-1,half), length-half)) } } + /** Returns the input in bit-reversed order. Useful for little/big-endian conversion. + */ def apply(in: UInt): UInt = doit(in, in.getWidth) } diff --git a/src/main/scala/chisel3/util/Conditional.scala b/src/main/scala/chisel3/util/Conditional.scala index 461ff765..5830e014 100644 --- a/src/main/scala/chisel3/util/Conditional.scala +++ b/src/main/scala/chisel3/util/Conditional.scala @@ -65,9 +65,8 @@ object is { // scalastyle:ignore object.name } /** Conditional logic to form a switch block. See [[is$ is]] for the case API. - * - * @example - * {{{ + * + * @example {{{ * switch (myState) { * is (state1) { * // some logic here that runs when myState === state1 diff --git a/src/main/scala/chisel3/util/Decoupled.scala b/src/main/scala/chisel3/util/Decoupled.scala index 77990777..65558aa9 100644 --- a/src/main/scala/chisel3/util/Decoupled.scala +++ b/src/main/scala/chisel3/util/Decoupled.scala @@ -21,10 +21,10 @@ abstract class ReadyValidIO[+T <: Data](gen: T) extends Bundle def fire(dummy: Int = 0): Bool = ready && valid } -/** A concrete subclass of ReadyValidIO signalling that the user expects a +/** A concrete subclass of ReadyValidIO signaling that the user expects a * "decoupled" interface: 'valid' indicates that the producer has * put valid data in 'bits', and 'ready' indicates that the consumer is ready - * to accept the data this cycle. No requirements are placed on the signalling + * to accept the data this cycle. No requirements are placed on the signaling * of ready or valid. */ class DecoupledIO[+T <: Data](gen: T) extends ReadyValidIO[T](gen) @@ -35,12 +35,12 @@ class DecoupledIO[+T <: Data](gen: T) extends ReadyValidIO[T](gen) /** This factory adds a decoupled handshaking protocol to a data bundle. */ object Decoupled { - /** Take any Data and wrap it in a DecoupledIO interface */ + /** Wraps some Data with a DecoupledIO interface. */ def apply[T <: Data](gen: T): DecoupledIO[T] = new DecoupledIO(gen) - /** Take an IrrevocableIO and cast it to a DecoupledIO. - * This cast is only safe to do in cases where the IrrevocableIO - * is being produced as an output. + /** Downconverts an IrrevocableIO output to a DecoupledIO, dropping guarantees of irrevocability. + * + * @note unsafe (and will error) on the producer (input) side of an IrrevocableIO */ def apply[T <: Data](irr: IrrevocableIO[T]): DecoupledIO[T] = { require(irr.bits.dir == OUTPUT, "Only safe to cast produced Irrevocable bits to Decoupled.") @@ -67,9 +67,10 @@ object Irrevocable { def apply[T <: Data](gen: T): IrrevocableIO[T] = new IrrevocableIO(gen) - /** Take a DecoupledIO and cast it to an IrrevocableIO. - * This cast is only safe to do in cases where the IrrevocableIO - * is being consumed as an input. + /** Upconverts a DecoupledIO input to an IrrevocableIO, allowing an IrrevocableIO to be used + * where a DecoupledIO is expected. + * + * @note unsafe (and will error) on the consumer (output) side of an DecoupledIO */ def apply[T <: Data](dec: DecoupledIO[T]): IrrevocableIO[T] = { require(dec.bits.dir == INPUT, "Only safe to cast consumed Decoupled bits to Irrevocable.") @@ -156,10 +157,11 @@ class QueueIO[T <: Data](gen: T, entries: Int) extends Bundle * @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 }}} + * @example {{{ + * 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, @@ -223,12 +225,16 @@ extends Module(override_reset=override_reset) { } } -/** Factory for a generic hardware queue. Required parameter 'entries' controls - * the depth of the queues. The width of the queue is determined - * from the input 'enq'. +/** Factory for a generic hardware queue. * - * Example usage: - * {{{ consumer.io.in <> Queue(producer.io.out, 16) }}} + * @param enq input (enqueue) interface to the queue, also determines width of queue elements + * @param entries depth (number of elements) of the queue + * + * @returns output (dequeue) interface from the queue + * + * @example {{{ + * consumer.io.in <> Queue(producer.io.out, 16) + * }}} */ object Queue { diff --git a/src/main/scala/chisel3/util/Enum.scala b/src/main/scala/chisel3/util/Enum.scala index 4ecc243b..55b595ee 100644 --- a/src/main/scala/chisel3/util/Enum.scala +++ b/src/main/scala/chisel3/util/Enum.scala @@ -12,12 +12,42 @@ object Enum { 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 */ + /** Returns n unique values of the specified type. Can be used with unpacking to define enums. + * + * @example {{{ + * val state_on :: state_off :: Nil = Enum(UInt(), 2) + * val current_state = UInt() + * switch (current_state) { + * is (state_on) { + * ... + * } + * if (state_off) { + * ... + * } + * } + * }}} + * + */ def apply[T <: Bits](nodeType: T, n: Int): List[T] = createValues(nodeType, n).toList - /** create enum values of given type and names */ + /** Returns a map of the input symbols to unique values of the specified type. + * + * @example {{{ + * val states = Enum(UInt(), 'on, 'off) + * val current_state = UInt() + * switch (current_state) { + * is (states('on)) { + * ... + * } + * if (states('off)) { + * .. + * } + * } + * }}} + */ 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 */ + /** Returns a map of the input symbols to unique values of the specified type. + */ 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/LFSR.scala b/src/main/scala/chisel3/util/LFSR.scala index a30c276f..e4261c20 100644 --- a/src/main/scala/chisel3/util/LFSR.scala +++ b/src/main/scala/chisel3/util/LFSR.scala @@ -8,12 +8,13 @@ package chisel3.util import chisel3._ // scalastyle:off magic.number -/** linear feedback shift register - */ -object LFSR16 -{ - def apply(increment: Bool = Bool(true)): UInt = - { +object LFSR16 { + /** Generates a 16-bit linear feedback shift register, returning the register contents. + * May be useful for generating a pseudorandom sequence. + * + * @param increment optional control to gate when the LFSR updates. + */ + 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)) } diff --git a/src/main/scala/chisel3/util/Mux.scala b/src/main/scala/chisel3/util/Mux.scala index 9956a7e3..245de67e 100644 --- a/src/main/scala/chisel3/util/Mux.scala +++ b/src/main/scala/chisel3/util/Mux.scala @@ -9,10 +9,11 @@ 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. + * select signal. Returns the output of the Mux tree. + * + * @note results undefined if multiple select signals are simultaneously high */ -object Mux1H -{ +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) @@ -22,18 +23,17 @@ object Mux1H } /** 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. + * can be enabled. Priority is given to the first select signal. + * + * Returns the output of the Mux tree. */ -object PriorityMux -{ +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 */ +/** 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 @@ -46,10 +46,11 @@ object MuxLookup { res = Mux(k === key, v, res) res } - } -/** MuxCase returns the first value that is enabled in a map of values */ +/** Given an association of values to enable signals, returns the first value with an associated + * high enable signal. + */ object MuxCase { /** @param default the default value if none are enabled * @param mapping a set of data values with associated enables -- cgit v1.2.3 From bd9276f4f78c712e98b658ad9e0df81abf94c57b Mon Sep 17 00:00:00 2001 From: ducky Date: Mon, 26 Sep 2016 14:12:05 -0700 Subject: Add Strict default for compile options --- .../src/main/scala/chisel3/internal/CompileOptions.scala | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/chiselFrontend/src/main/scala/chisel3/internal/CompileOptions.scala b/chiselFrontend/src/main/scala/chisel3/internal/CompileOptions.scala index 2890f6dc..2b913908 100644 --- a/chiselFrontend/src/main/scala/chisel3/internal/CompileOptions.scala +++ b/chiselFrontend/src/main/scala/chisel3/internal/CompileOptions.scala @@ -2,6 +2,9 @@ package chisel3.internal +import scala.language.experimental.macros +import scala.reflect.macros.blackbox.Context + trait CompileOptions { // Should Bundle connections require a strict match of fields. // If true and the same fields aren't present in both source and sink, a MissingFieldException, @@ -15,6 +18,11 @@ trait CompileOptions { trait ExplicitCompileOptions extends CompileOptions +object ExplicitCompileOptions { + // Provides a low priority Strict default. Can be overridden by importing the NotStrict option. + implicit def materialize: ExplicitCompileOptions = chisel3.Strict.CompileOptions +} + ///** Initialize compilation options from a string map. // * // * @param optionsMap the map from "option" to "value" -- cgit v1.2.3 From 2edfe895e4ff9f751c52904f73fe701502aa926a Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Wed, 28 Sep 2016 08:43:59 -0700 Subject: Don't use firrtlDirection for direction checks - fix #298. firrtlDirection should only be used for emitting firrtl. Any checks on the actual direction should use the bound Direction `dir`. --- chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala | 2 +- chiselFrontend/src/main/scala/chisel3/core/Data.scala | 4 +++- src/main/scala/chisel3/util/Decoupled.scala | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala index 6baf5202..a0eefbfe 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala @@ -63,7 +63,7 @@ object Vec { val maxWidth = elts.map(_.width).reduce(_ max _) val vec = Wire(new Vec(t.cloneTypeWidth(maxWidth), elts.length)) def doConnect(sink: T, source: T) = { - if (elts.head.flatten.exists(_.firrtlDirection != Direction.Unspecified)) { + if (elts.head.flatten.exists(_.dir != Direction.Unspecified)) { sink bulkConnect source } else { sink connect source diff --git a/chiselFrontend/src/main/scala/chisel3/core/Data.scala b/chiselFrontend/src/main/scala/chisel3/core/Data.scala index 4bb58572..52bc8128 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Data.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Data.scala @@ -241,7 +241,9 @@ abstract class Data extends HasId { // firrtlDirection is the direction we report to firrtl. // It maintains the user-specified value (as opposed to the "actual" or applied/propagated value). - var firrtlDirection: Direction = Direction.Unspecified + // NOTE: This should only be used for emitting acceptable firrtl. + // The Element.dir should be used for any tests involving direction. + private var firrtlDirection: Direction = Direction.Unspecified /** Default pretty printing */ def toPrintable: Printable } diff --git a/src/main/scala/chisel3/util/Decoupled.scala b/src/main/scala/chisel3/util/Decoupled.scala index 36502862..70b191bd 100644 --- a/src/main/scala/chisel3/util/Decoupled.scala +++ b/src/main/scala/chisel3/util/Decoupled.scala @@ -84,7 +84,7 @@ object Decoupled * @note unsafe (and will error) on the producer (input) side of an IrrevocableIO */ def apply[T <: Data](irr: IrrevocableIO[T]): DecoupledIO[T] = { - require(getFirrtlDirection(irr.bits) == OUTPUT, "Only safe to cast produced Irrevocable bits to Decoupled.") + require(irr.bits.flatten forall (_.dir == OUTPUT), "Only safe to cast produced Irrevocable bits to Decoupled.") val d = Wire(new DecoupledIO(irr.bits)) d.bits := irr.bits d.valid := irr.valid @@ -117,7 +117,7 @@ object Irrevocable * @note unsafe (and will error) on the consumer (output) side of an DecoupledIO */ def apply[T <: Data](dec: DecoupledIO[T]): IrrevocableIO[T] = { - require(getFirrtlDirection(dec.bits) == INPUT, "Only safe to cast consumed Decoupled bits to Irrevocable.") + require(dec.bits.flatten forall (_.dir == INPUT), "Only safe to cast consumed Decoupled bits to Irrevocable.") val i = Wire(new IrrevocableIO(dec.bits)) dec.bits := i.bits dec.valid := i.valid -- cgit v1.2.3 From c68f1fd9fa27f93bae24bc14575f2d535d10594c Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Wed, 28 Sep 2016 14:48:15 -0700 Subject: Generate scaladoc for all subprojects. Use aggregate to run project tasks in subprojects Use sbt-unidoc to generate combined scaladoc for project and subprojects. --- build.sbt | 18 ++++++++++++------ project/plugins.sbt | 2 ++ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/build.sbt b/build.sbt index 02a0e9f5..5c8461ba 100644 --- a/build.sbt +++ b/build.sbt @@ -6,10 +6,18 @@ site.includeScaladoc() ghpages.settings +import UnidocKeys._ + +lazy val customUnidocSettings = unidocSettings ++ Seq ( + doc in Compile := (doc in ScalaUnidoc).value, + target in unidoc in ScalaUnidoc := crossTarget.value / "api" +) + lazy val commonSettings = Seq ( organization := "edu.berkeley.cs", version := "3.1-SNAPSHOT", git.remoteRepo := "git@github.com:ucb-bar/chisel3.git", + autoAPIMappings := true, scalaVersion := "2.11.7" ) @@ -94,18 +102,16 @@ lazy val chiselFrontend = (project in file("chiselFrontend")). lazy val chisel = (project in file(".")). settings(commonSettings: _*). + settings(customUnidocSettings: _*). settings(chiselSettings: _*). dependsOn(coreMacros). dependsOn(chiselFrontend). settings( + aggregate in doc := false, // Include macro classes, resources, and sources main jar. mappings in (Compile, packageBin) <++= mappings in (coreMacros, Compile, packageBin), mappings in (Compile, packageSrc) <++= mappings in (coreMacros, Compile, packageSrc), mappings in (Compile, packageBin) <++= mappings in (chiselFrontend, Compile, packageBin), mappings in (Compile, packageSrc) <++= mappings in (chiselFrontend, Compile, packageSrc) - ) - -// This is ugly. There must be a better way. -publish <<= (publish) dependsOn (publish in coreMacros, publish in chiselFrontend) - -publishLocal <<= (publishLocal) dependsOn (publishLocal in coreMacros, publishLocal in chiselFrontend) + ). + aggregate(coreMacros, chiselFrontend) diff --git a/project/plugins.sbt b/project/plugins.sbt index 585435a0..58166621 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -13,3 +13,5 @@ addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.3.5") addSbtPlugin("com.typesafe.sbt" % "sbt-ghpages" % "0.5.4") addSbtPlugin("com.typesafe.sbt" % "sbt-site" % "0.8.2") + +addSbtPlugin("com.eed3si9n" % "sbt-unidoc" % "0.3.3") -- cgit v1.2.3 From eb5e5dc30019be342b7a0534b425bf33b7984ce3 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Thu, 29 Sep 2016 11:44:09 -0700 Subject: Massive rename of CompileOptions. Massage CompileOption names in an attempt to preserve default (Strict) CompileOptions in the absence of explicit imports. NOTE: Since the default is now strict, we may encounter errors when we generate connections for clients (i.e., in Vec.do_apply() when we wire up a sequence). We should really thread the CompileOptions through the macro system so the client's implicits are used. --- .../src/main/scala/chisel3/CompileOptions.scala | 53 ++++++++++++++++++++++ .../src/main/scala/chisel3/NotStrict.scala | 16 ------- chiselFrontend/src/main/scala/chisel3/Strict.scala | 16 ------- .../src/main/scala/chisel3/core/Aggregate.scala | 12 ++--- .../src/main/scala/chisel3/core/BiConnect.scala | 6 +-- .../src/main/scala/chisel3/core/Bits.scala | 2 +- .../src/main/scala/chisel3/core/BlackBox.scala | 2 +- .../src/main/scala/chisel3/core/Data.scala | 14 +++--- .../src/main/scala/chisel3/core/Mem.scala | 2 +- .../src/main/scala/chisel3/core/Module.scala | 4 +- .../src/main/scala/chisel3/core/MonoConnect.scala | 6 +-- .../src/main/scala/chisel3/core/Reg.scala | 9 ++-- .../scala/chisel3/internal/CompileOptions.scala | 41 ----------------- src/main/scala/chisel3/compatibility.scala | 2 +- src/main/scala/chisel3/testers/BasicTester.scala | 2 +- src/main/scala/chisel3/util/Arbiter.scala | 2 +- src/main/scala/chisel3/util/Counter.scala | 2 +- src/main/scala/chisel3/util/Decoupled.scala | 2 +- src/main/scala/chisel3/util/LFSR.scala | 2 +- src/main/scala/chisel3/util/Reg.scala | 2 +- src/main/scala/chisel3/util/Valid.scala | 2 +- src/test/scala/chiselTests/AnnotatingExample.scala | 1 - src/test/scala/chiselTests/Assert.scala | 1 - src/test/scala/chiselTests/BetterNamingTests.scala | 2 - src/test/scala/chiselTests/BlackBox.scala | 2 +- src/test/scala/chiselTests/BundleWire.scala | 2 +- .../scala/chiselTests/CompileOptionsTest.scala | 32 ++++++------- src/test/scala/chiselTests/ComplexAssign.scala | 1 - src/test/scala/chiselTests/Counter.scala | 1 - src/test/scala/chiselTests/Decoder.scala | 1 - src/test/scala/chiselTests/DeqIOSpec.scala | 1 - src/test/scala/chiselTests/Direction.scala | 1 - .../scala/chiselTests/EnableShiftRegister.scala | 1 - src/test/scala/chiselTests/GCD.scala | 1 - src/test/scala/chiselTests/IOCompatibility.scala | 17 ++++--- src/test/scala/chiselTests/LFSR16.scala | 1 - src/test/scala/chiselTests/MemorySearch.scala | 1 - src/test/scala/chiselTests/Module.scala | 1 - src/test/scala/chiselTests/MulLookup.scala | 1 - src/test/scala/chiselTests/MultiAssign.scala | 1 - src/test/scala/chiselTests/OptionBundle.scala | 1 - src/test/scala/chiselTests/Padding.scala | 1 - .../scala/chiselTests/ParameterizedModule.scala | 1 - src/test/scala/chiselTests/PrintableSpec.scala | 1 - src/test/scala/chiselTests/Reg.scala | 1 - src/test/scala/chiselTests/Risc.scala | 1 - src/test/scala/chiselTests/SIntOps.scala | 2 +- src/test/scala/chiselTests/Stack.scala | 2 +- src/test/scala/chiselTests/Tbl.scala | 2 +- src/test/scala/chiselTests/TesterDriverSpec.scala | 2 +- src/test/scala/chiselTests/UIntOps.scala | 2 +- src/test/scala/chiselTests/Vec.scala | 2 +- src/test/scala/chiselTests/VectorPacketIO.scala | 2 +- src/test/scala/chiselTests/VendingMachine.scala | 2 +- src/test/scala/chiselTests/When.scala | 2 +- 55 files changed, 125 insertions(+), 167 deletions(-) create mode 100644 chiselFrontend/src/main/scala/chisel3/CompileOptions.scala delete mode 100644 chiselFrontend/src/main/scala/chisel3/NotStrict.scala delete mode 100644 chiselFrontend/src/main/scala/chisel3/Strict.scala delete mode 100644 chiselFrontend/src/main/scala/chisel3/internal/CompileOptions.scala diff --git a/chiselFrontend/src/main/scala/chisel3/CompileOptions.scala b/chiselFrontend/src/main/scala/chisel3/CompileOptions.scala new file mode 100644 index 00000000..2e5c64aa --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel3/CompileOptions.scala @@ -0,0 +1,53 @@ +// See LICENSE for license details. + +package chisel3 + +import scala.language.experimental.macros + +trait CompileOptions { + // Should Bundle connections require a strict match of fields. + // If true and the same fields aren't present in both source and sink, a MissingFieldException, + // MissingLeftFieldException, or MissingRightFieldException will be thrown. + val connectFieldsMustMatch: Boolean + // When creating an object that takes a type argument, the argument must be unbound (a pure type). + val declaredTypeMustBeUnbound: Boolean + // Module IOs should be wrapped in an IO() to define their bindings before the reset of the module is defined. + val requireIOWrap: Boolean + // If a connection operator fails, don't try the connection with the operands (source and sink) reversed. + val dontTryConnectionsSwapped: Boolean + // If connection directionality is not explicit, do not use heuristics to attempt to determine it. + val dontAssumeDirectionality: Boolean +} + +trait ImplicitCompileOptions extends CompileOptions + +object ImplicitCompileOptions { + // Provides a low priority Strict default. Can be overridden by importing the NotStrict option. + implicit def materialize: ImplicitCompileOptions = chisel3.ExplicitCompileOptions.Strict +} + +// Define a more-specific trait which should be perferred if both are available. +trait ExplicitImplicitCompileOptions extends ImplicitCompileOptions + +object ExplicitCompileOptions { + // Collection of "not strict" connection compile options. + // These provide compatibility with existing code. + // import chisel3.ExplicitCompileOptions.NotStrict + implicit object NotStrict extends ExplicitImplicitCompileOptions { + val connectFieldsMustMatch = false + val declaredTypeMustBeUnbound = false + val requireIOWrap = false + val dontTryConnectionsSwapped = false + val dontAssumeDirectionality = false + } + + // Collection of "strict" connection compile options, preferred for new code. + // import chisel3.ExplicitCompileOptions.Strict + implicit object Strict extends ExplicitImplicitCompileOptions { + val connectFieldsMustMatch = true + val declaredTypeMustBeUnbound = true + val requireIOWrap = true + val dontTryConnectionsSwapped = true + val dontAssumeDirectionality = true + } +} diff --git a/chiselFrontend/src/main/scala/chisel3/NotStrict.scala b/chiselFrontend/src/main/scala/chisel3/NotStrict.scala deleted file mode 100644 index bb390e7c..00000000 --- a/chiselFrontend/src/main/scala/chisel3/NotStrict.scala +++ /dev/null @@ -1,16 +0,0 @@ -// See LICENSE for license details. - -package chisel3 - -import chisel3.internal.ExplicitCompileOptions - - -object NotStrict { - implicit object CompileOptions extends ExplicitCompileOptions { - val connectFieldsMustMatch = false - val declaredTypeMustBeUnbound = false - val requireIOWrap = false - val dontTryConnectionsSwapped = false - val dontAssumeDirectionality = false - } -} diff --git a/chiselFrontend/src/main/scala/chisel3/Strict.scala b/chiselFrontend/src/main/scala/chisel3/Strict.scala deleted file mode 100644 index 70240429..00000000 --- a/chiselFrontend/src/main/scala/chisel3/Strict.scala +++ /dev/null @@ -1,16 +0,0 @@ -// See LICENSE for license details. - -package chisel3 - -import chisel3.internal.ExplicitCompileOptions - - -object Strict { - implicit object CompileOptions extends ExplicitCompileOptions { - val connectFieldsMustMatch = true - val declaredTypeMustBeUnbound = true - val requireIOWrap = true - val dontTryConnectionsSwapped = true - val dontAssumeDirectionality = true - } -} diff --git a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala index a0eefbfe..b363c572 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala @@ -10,7 +10,7 @@ import chisel3.internal._ import chisel3.internal.Builder.pushCommand import chisel3.internal.firrtl._ import chisel3.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, VecTransform, SourceInfoTransform} -import chisel3.NotStrict.CompileOptions +import chisel3.ImplicitCompileOptions /** An abstract class for data types that solely consist of (are an aggregate * of) other Data objects. @@ -152,27 +152,27 @@ sealed class Vec[T <: Data] private (gen: T, val length: Int) * * @note the length of this Vec must match the length of the input Seq */ - def <> (that: Seq[T])(implicit sourceInfo: SourceInfo, moduleCompileOptions: ExplicitCompileOptions): Unit = { + def <> (that: Seq[T])(implicit sourceInfo: SourceInfo, moduleCompileOptions: ImplicitCompileOptions): 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, moduleCompileOptions: ExplicitCompileOptions): Unit = this bulkConnect that.asInstanceOf[Data] + def <> (that: Vec[T])(implicit sourceInfo: SourceInfo, moduleCompileOptions: ImplicitCompileOptions): Unit = this bulkConnect that.asInstanceOf[Data] /** 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, moduleCompileOptions: ExplicitCompileOptions): Unit = { + def := (that: Seq[T])(implicit sourceInfo: SourceInfo, moduleCompileOptions: ImplicitCompileOptions): 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, moduleCompileOptions: ExplicitCompileOptions): Unit = this connect that + def := (that: Vec[T])(implicit sourceInfo: SourceInfo, moduleCompileOptions: ImplicitCompileOptions): Unit = this connect that /** Creates a dynamically indexed read or write accessor into the array. */ @@ -199,7 +199,7 @@ sealed class Vec[T <: Data] private (gen: T, val length: Int) @deprecated("Use Vec.apply instead", "chisel3") def write(idx: UInt, data: T): Unit = { - apply(idx).:=(data)(DeprecatedSourceInfo, chisel3.NotStrict.CompileOptions) + apply(idx).:=(data)(DeprecatedSourceInfo, chisel3.ExplicitCompileOptions.NotStrict) } override def cloneType: this.type = { diff --git a/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala b/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala index ce70a19a..a6b9cda3 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala @@ -6,7 +6,7 @@ import chisel3.internal.Builder.pushCommand import chisel3.internal.firrtl.Connect import scala.language.experimental.macros import chisel3.internal.sourceinfo._ -import chisel3.internal.ExplicitCompileOptions +import chisel3.ImplicitCompileOptions /** * BiConnect.connect executes a bidirectional connection element-wise. @@ -50,7 +50,7 @@ object BiConnect { * during the recursive decent and then rethrow them with extra information added. * This gives the user a 'path' to where in the connections things went wrong. */ - def connect(sourceInfo: SourceInfo, connectCompileOptions: ExplicitCompileOptions, left: Data, right: Data, context_mod: Module): Unit = + def connect(sourceInfo: SourceInfo, connectCompileOptions: ImplicitCompileOptions, left: Data, right: Data, context_mod: Module): Unit = (left, right) match { // Handle element case (root case) case (left_e: Element, right_e: Element) => { @@ -110,7 +110,7 @@ object BiConnect { // This function checks if element-level connection operation allowed. // Then it either issues it or throws the appropriate exception. - def elemConnect(implicit sourceInfo: SourceInfo, connectCompileOptions: ExplicitCompileOptions, left: Element, right: Element, context_mod: Module): Unit = { + def elemConnect(implicit sourceInfo: SourceInfo, connectCompileOptions: ImplicitCompileOptions, left: Element, right: Element, context_mod: Module): Unit = { import Direction.{Input, Output} // Using extensively so import these // If left or right have no location, assume in context module // This can occur if one of them is a literal, unbound will error previously diff --git a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala index 938eeb1f..12c99104 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala @@ -10,7 +10,7 @@ import chisel3.internal.firrtl._ import chisel3.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, SourceInfoTransform, SourceInfoWhiteboxTransform, UIntTransform, MuxTransform} import chisel3.internal.firrtl.PrimOp._ -import chisel3.NotStrict.CompileOptions +//import chisel3.ImplicitCompileOptions.NotStrict /** Element is a leaf data type: it cannot contain other Data objects. Example * uses are for representing primitive data types, like integers and bits. diff --git a/chiselFrontend/src/main/scala/chisel3/core/BlackBox.scala b/chiselFrontend/src/main/scala/chisel3/core/BlackBox.scala index 7b0cf3f7..7e61ec72 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/BlackBox.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/BlackBox.scala @@ -5,7 +5,7 @@ package chisel3.core import chisel3.internal.Builder.pushCommand import chisel3.internal.firrtl.{ModuleIO, DefInvalid} import chisel3.internal.sourceinfo.SourceInfo -import chisel3.NotStrict.CompileOptions +//import chisel3.ExplicitCompileOptions.NotStrict /** 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 52bc8128..1b08374a 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Data.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Data.scala @@ -9,7 +9,7 @@ import chisel3.internal.Builder.{pushCommand, pushOp} import chisel3.internal.firrtl._ import chisel3.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, UnlocatableSourceInfo, WireTransform, SourceInfoTransform} import chisel3.internal.firrtl.PrimOp.AsUIntOp -import chisel3.NotStrict.CompileOptions +import chisel3.ImplicitCompileOptions sealed abstract class Direction(name: String) { override def toString: String = name @@ -126,7 +126,7 @@ abstract class Data extends HasId { private[core] def badConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit = throwException(s"cannot connect ${this} and ${that}") - private[chisel3] def connect(that: Data)(implicit sourceInfo: SourceInfo, connectCompileOptions: ExplicitCompileOptions): Unit = { + private[chisel3] def connect(that: Data)(implicit sourceInfo: SourceInfo, connectCompileOptions: ImplicitCompileOptions): Unit = { Binding.checkSynthesizable(this, s"'this' ($this)") Binding.checkSynthesizable(that, s"'that' ($that)") try { @@ -138,7 +138,7 @@ abstract class Data extends HasId { ) } } - private[chisel3] def bulkConnect(that: Data)(implicit sourceInfo: SourceInfo, connectCompileOptions: ExplicitCompileOptions): Unit = { + private[chisel3] def bulkConnect(that: Data)(implicit sourceInfo: SourceInfo, connectCompileOptions: ImplicitCompileOptions): Unit = { Binding.checkSynthesizable(this, s"'this' ($this)") Binding.checkSynthesizable(that, s"'that' ($that)") try { @@ -167,8 +167,8 @@ abstract class Data extends HasId { } clone } - final def := (that: Data)(implicit sourceInfo: SourceInfo, connectionCompileOptions: ExplicitCompileOptions): Unit = this.connect(that)(sourceInfo, connectionCompileOptions) - final def <> (that: Data)(implicit sourceInfo: SourceInfo, connectionCompileOptions: ExplicitCompileOptions): Unit = this.bulkConnect(that)(sourceInfo, connectionCompileOptions) + final def := (that: Data)(implicit sourceInfo: SourceInfo, connectionCompileOptions: ImplicitCompileOptions): Unit = this.connect(that)(sourceInfo, connectionCompileOptions) + final def <> (that: Data)(implicit sourceInfo: SourceInfo, connectionCompileOptions: ImplicitCompileOptions): Unit = this.bulkConnect(that)(sourceInfo, connectionCompileOptions) def litArg(): Option[LitArg] = None def litValue(): BigInt = litArg.get.num def isLit(): Boolean = litArg.isDefined @@ -260,7 +260,7 @@ object Wire { do_apply(t, init)(UnlocatableSourceInfo) def do_apply[T <: Data](t: T, init: T)(implicit sourceInfo: SourceInfo): T = { - val x = Reg.makeType(chisel3.NotStrict.CompileOptions, t, null.asInstanceOf[T], init) + val x = Reg.makeType(chisel3.ExplicitCompileOptions.NotStrict, t, null.asInstanceOf[T], init) // Bind each element of x to being a Wire Binding.bind(x, WireBinder(Builder.forcedModule), "Error: t") @@ -294,7 +294,7 @@ sealed class Clock extends Element(Width(1)) { private[core] def cloneTypeWidth(width: Width): this.type = cloneType private[chisel3] def toType = "Clock" - override def connect (that: Data)(implicit sourceInfo: SourceInfo, connectCompileOptions: ExplicitCompileOptions): Unit = that match { + override def connect (that: Data)(implicit sourceInfo: SourceInfo, connectCompileOptions: ImplicitCompileOptions): Unit = that match { case _: Clock => super.connect(that)(sourceInfo, connectCompileOptions) case _ => super.badConnect(that)(sourceInfo) } diff --git a/chiselFrontend/src/main/scala/chisel3/core/Mem.scala b/chiselFrontend/src/main/scala/chisel3/core/Mem.scala index 5eaaf262..d762ef5e 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Mem.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Mem.scala @@ -8,7 +8,7 @@ import chisel3.internal._ import chisel3.internal.Builder.pushCommand import chisel3.internal.firrtl._ import chisel3.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, UnlocatableSourceInfo, MemTransform} -import chisel3.NotStrict.CompileOptions +//import chisel3.ExplicitCompileOptions.NotStrict 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 03e4f1b7..f4b36888 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Module.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Module.scala @@ -9,7 +9,7 @@ import chisel3.internal.Builder._ import chisel3.internal.firrtl._ import chisel3.internal.firrtl.{Command => _, _} import chisel3.internal.sourceinfo.{InstTransform, SourceInfo, UnlocatableSourceInfo} -import chisel3.NotStrict.CompileOptions +import chisel3.ImplicitCompileOptions object Module { /** A wrapper method that all Module instantiations must be wrapped in @@ -51,7 +51,7 @@ object Module { */ abstract class Module( override_clock: Option[Clock]=None, override_reset: Option[Bool]=None) - (implicit moduleCompileOptions: ExplicitCompileOptions) + (implicit moduleCompileOptions: ImplicitCompileOptions) extends HasId { // _clock and _reset can be clock and reset in these 2ary constructors // once chisel2 compatibility issues are resolved diff --git a/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala b/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala index 1925171b..38030d49 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala @@ -6,7 +6,7 @@ import chisel3.internal.Builder.pushCommand import chisel3.internal.firrtl.Connect import scala.language.experimental.macros import chisel3.internal.sourceinfo.{DeprecatedSourceInfo, SourceInfo, SourceInfoTransform, UnlocatableSourceInfo, WireTransform} -import chisel3.internal.ExplicitCompileOptions +import chisel3.ImplicitCompileOptions /** * MonoConnect.connect executes a mono-directional connection element-wise. @@ -56,7 +56,7 @@ object MonoConnect { * during the recursive decent and then rethrow them with extra information added. * This gives the user a 'path' to where in the connections things went wrong. */ - def connect(sourceInfo: SourceInfo, connectCompileOptions: ExplicitCompileOptions, sink: Data, source: Data, context_mod: Module): Unit = + def connect(sourceInfo: SourceInfo, connectCompileOptions: ImplicitCompileOptions, sink: Data, source: Data, context_mod: Module): Unit = (sink, source) match { // Handle element case (root case) case (sink_e: Element, source_e: Element) => { @@ -103,7 +103,7 @@ object MonoConnect { // This function checks if element-level connection operation allowed. // Then it either issues it or throws the appropriate exception. - def elemConnect(implicit sourceInfo: SourceInfo, connectCompileOptions: ExplicitCompileOptions, sink: Element, source: Element, context_mod: Module): Unit = { + def elemConnect(implicit sourceInfo: SourceInfo, connectCompileOptions: ImplicitCompileOptions, sink: Element, source: Element, context_mod: Module): Unit = { import Direction.{Input, Output} // Using extensively so import these // If source has no location, assume in context module // This can occur if is a literal, unbound will error previously diff --git a/chiselFrontend/src/main/scala/chisel3/core/Reg.scala b/chiselFrontend/src/main/scala/chisel3/core/Reg.scala index 2569e9ea..1bdfb40f 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Reg.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Reg.scala @@ -6,9 +6,10 @@ import chisel3.internal._ import chisel3.internal.Builder.pushCommand import chisel3.internal.firrtl._ import chisel3.internal.sourceinfo.{SourceInfo, UnlocatableSourceInfo} +import chisel3.ImplicitCompileOptions object Reg { - private[core] def makeType[T <: Data](compileOptions: ExplicitCompileOptions, t: T = null, next: T = null, init: T = null): T = { + private[core] def makeType[T <: Data](compileOptions: ImplicitCompileOptions, t: T = null, next: T = null, init: T = null): T = { if (t ne null) { if (compileOptions.declaredTypeMustBeUnbound) { Binding.checkUnbound(t, s"t ($t) must be unbound Type. Try using cloneType?") @@ -40,7 +41,7 @@ object Reg { * 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)(implicit sourceInfo: SourceInfo, compileOptions: ExplicitCompileOptions): T = + def apply[T <: Data](t: T = null, next: T = null, init: T = null)(implicit sourceInfo: SourceInfo, compileOptions: ImplicitCompileOptions): T = // Scala macros can't (yet) handle named or default arguments. do_apply(t, next, init)(sourceInfo, compileOptions) @@ -49,9 +50,9 @@ object Reg { * * @param outType: data type for the register */ - def apply[T <: Data](outType: T)(implicit sourceInfo: SourceInfo, compileOptions: ExplicitCompileOptions): T = Reg[T](outType, null.asInstanceOf[T], null.asInstanceOf[T])(sourceInfo, compileOptions) + def apply[T <: Data](outType: T)(implicit sourceInfo: SourceInfo, compileOptions: ImplicitCompileOptions): T = Reg[T](outType, null.asInstanceOf[T], null.asInstanceOf[T])(sourceInfo, compileOptions) - def do_apply[T <: Data](t: T, next: T, init: T)(implicit sourceInfo: SourceInfo, compileOptions: ExplicitCompileOptions = chisel3.NotStrict.CompileOptions): T = { + def do_apply[T <: Data](t: T, next: T, init: T)(implicit sourceInfo: SourceInfo, compileOptions: ImplicitCompileOptions = chisel3.ExplicitCompileOptions.NotStrict): 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()). diff --git a/chiselFrontend/src/main/scala/chisel3/internal/CompileOptions.scala b/chiselFrontend/src/main/scala/chisel3/internal/CompileOptions.scala deleted file mode 100644 index 2b913908..00000000 --- a/chiselFrontend/src/main/scala/chisel3/internal/CompileOptions.scala +++ /dev/null @@ -1,41 +0,0 @@ -// See LICENSE for license details. - -package chisel3.internal - -import scala.language.experimental.macros -import scala.reflect.macros.blackbox.Context - -trait CompileOptions { - // Should Bundle connections require a strict match of fields. - // If true and the same fields aren't present in both source and sink, a MissingFieldException, - // MissingLeftFieldException, or MissingRightFieldException will be thrown. - val connectFieldsMustMatch: Boolean - val declaredTypeMustBeUnbound: Boolean - val requireIOWrap: Boolean - val dontTryConnectionsSwapped: Boolean - val dontAssumeDirectionality: Boolean -} - -trait ExplicitCompileOptions extends CompileOptions - -object ExplicitCompileOptions { - // Provides a low priority Strict default. Can be overridden by importing the NotStrict option. - implicit def materialize: ExplicitCompileOptions = chisel3.Strict.CompileOptions -} - -///** Initialize compilation options from a string map. -// * -// * @param optionsMap the map from "option" to "value" -// */ -//class CompileOptions(optionsMap: Map[String, String]) { -// // The default for settings related to "strictness". -// val strictDefault: String = optionsMap.getOrElse("strict", "false") -// // Should Bundle connections require a strict match of fields. -// // If true and the same fields aren't present in both source and sink, a MissingFieldException, -// // MissingLeftFieldException, or MissingRightFieldException will be thrown. -// val connectFieldsMustMatch: Boolean = optionsMap.getOrElse("connectFieldsMustMatch", strictDefault).toBoolean -// val declaredTypeMustBeUnbound: Boolean = optionsMap.getOrElse("declaredTypeMustBeUnbound", strictDefault).toBoolean -// val requireIOWrap: Boolean = optionsMap.getOrElse("requireIOWrap", strictDefault).toBoolean -// val dontTryConnectionsSwapped: Boolean = optionsMap.getOrElse("dontTryConnectionsSwapped", strictDefault).toBoolean -// val dontAssumeDirectionality: Boolean = optionsMap.getOrElse("dontAssumeDirectionality", strictDefault).toBoolean -//} diff --git a/src/main/scala/chisel3/compatibility.scala b/src/main/scala/chisel3/compatibility.scala index 3b1b5b0a..646fc84e 100644 --- a/src/main/scala/chisel3/compatibility.scala +++ b/src/main/scala/chisel3/compatibility.scala @@ -4,7 +4,7 @@ // moving to the more standard package naming convention chisel3 (lowercase c). package object Chisel { // scalastyle:ignore package.object.name - implicit val defaultCompileOptions = chisel3.NotStrict.CompileOptions + implicit val defaultCompileOptions = chisel3.ExplicitCompileOptions.NotStrict type Direction = chisel3.core.Direction val INPUT = chisel3.core.Direction.Input val OUTPUT = chisel3.core.Direction.Output diff --git a/src/main/scala/chisel3/testers/BasicTester.scala b/src/main/scala/chisel3/testers/BasicTester.scala index edb32853..93bb4c33 100644 --- a/src/main/scala/chisel3/testers/BasicTester.scala +++ b/src/main/scala/chisel3/testers/BasicTester.scala @@ -9,7 +9,7 @@ import internal._ import internal.Builder.pushCommand import internal.firrtl._ import internal.sourceinfo.SourceInfo -import chisel3.NotStrict.CompileOptions +//import chisel3.ExplicitCompileOptions.NotStrict class BasicTester extends Module() { // The testbench has no IOs, rather it should communicate using printf, assert, and stop. diff --git a/src/main/scala/chisel3/util/Arbiter.scala b/src/main/scala/chisel3/util/Arbiter.scala index 67e28617..adeb1b34 100644 --- a/src/main/scala/chisel3/util/Arbiter.scala +++ b/src/main/scala/chisel3/util/Arbiter.scala @@ -6,7 +6,7 @@ package chisel3.util import chisel3._ -import chisel3.NotStrict.CompileOptions +//import chisel3.ExplicitCompileOptions.NotStrict /** IO bundle definition for an Arbiter, which takes some number of ready-valid inputs and outputs * (selects) at most one. diff --git a/src/main/scala/chisel3/util/Counter.scala b/src/main/scala/chisel3/util/Counter.scala index 5d9b8c3c..b22cfa7b 100644 --- a/src/main/scala/chisel3/util/Counter.scala +++ b/src/main/scala/chisel3/util/Counter.scala @@ -3,7 +3,7 @@ package chisel3.util import chisel3._ -import chisel3.Strict.CompileOptions +//import chisel3.ExplicitCompileOptions.Strict /** A counter module * diff --git a/src/main/scala/chisel3/util/Decoupled.scala b/src/main/scala/chisel3/util/Decoupled.scala index 70b191bd..947d02f8 100644 --- a/src/main/scala/chisel3/util/Decoupled.scala +++ b/src/main/scala/chisel3/util/Decoupled.scala @@ -6,7 +6,7 @@ package chisel3.util import chisel3._ -import chisel3.NotStrict.CompileOptions +//import chisel3.ExplicitCompileOptions.NotStrict /** An I/O Bundle containing 'valid' and 'ready' signals that handshake * the transfer of data stored in the 'bits' subfield. diff --git a/src/main/scala/chisel3/util/LFSR.scala b/src/main/scala/chisel3/util/LFSR.scala index e3c29e79..95b4da81 100644 --- a/src/main/scala/chisel3/util/LFSR.scala +++ b/src/main/scala/chisel3/util/LFSR.scala @@ -6,7 +6,7 @@ package chisel3.util import chisel3._ -import chisel3.Strict.CompileOptions +//import chisel3.ExplicitCompileOptions.Strict // scalastyle:off magic.number object LFSR16 { diff --git a/src/main/scala/chisel3/util/Reg.scala b/src/main/scala/chisel3/util/Reg.scala index 307812f8..fcfc9ac5 100644 --- a/src/main/scala/chisel3/util/Reg.scala +++ b/src/main/scala/chisel3/util/Reg.scala @@ -3,7 +3,7 @@ package chisel3.util import chisel3._ -import chisel3.NotStrict.CompileOptions +//import chisel3.ExplicitCompileOptions.NotStrict object RegNext { /** Returns a register with the specified next and no reset initialization. diff --git a/src/main/scala/chisel3/util/Valid.scala b/src/main/scala/chisel3/util/Valid.scala index ed4c3721..67be7648 100644 --- a/src/main/scala/chisel3/util/Valid.scala +++ b/src/main/scala/chisel3/util/Valid.scala @@ -6,7 +6,7 @@ package chisel3.util import chisel3._ -import chisel3.NotStrict.CompileOptions +//import chisel3.ExplicitCompileOptions.NotStrict /** An Bundle containing data and a signal determining if it is valid */ class Valid[+T <: Data](gen: T) extends Bundle diff --git a/src/test/scala/chiselTests/AnnotatingExample.scala b/src/test/scala/chiselTests/AnnotatingExample.scala index 85b4b039..c84edf86 100644 --- a/src/test/scala/chiselTests/AnnotatingExample.scala +++ b/src/test/scala/chiselTests/AnnotatingExample.scala @@ -6,7 +6,6 @@ import chisel3._ import chisel3.core.Module import chisel3.internal.InstanceId import chisel3.testers.BasicTester -import chisel3.NotStrict.CompileOptions import org.scalatest._ import scala.util.DynamicVariable diff --git a/src/test/scala/chiselTests/Assert.scala b/src/test/scala/chiselTests/Assert.scala index 509dedbd..efc2e1e7 100644 --- a/src/test/scala/chiselTests/Assert.scala +++ b/src/test/scala/chiselTests/Assert.scala @@ -6,7 +6,6 @@ import org.scalatest._ import chisel3._ import chisel3.testers.BasicTester import chisel3.util._ -import chisel3.NotStrict.CompileOptions class FailingAssertTester() extends BasicTester { assert(Bool(false)) diff --git a/src/test/scala/chiselTests/BetterNamingTests.scala b/src/test/scala/chiselTests/BetterNamingTests.scala index 98ca0306..f5872adb 100644 --- a/src/test/scala/chiselTests/BetterNamingTests.scala +++ b/src/test/scala/chiselTests/BetterNamingTests.scala @@ -5,8 +5,6 @@ import collection.mutable import chisel3._ import chisel3.util._ -import chisel3.NotStrict.CompileOptions - // Defined outside of the class so we don't get $ in name class Other(w: Int) extends Module { diff --git a/src/test/scala/chiselTests/BlackBox.scala b/src/test/scala/chiselTests/BlackBox.scala index b26b7d77..465dec4e 100644 --- a/src/test/scala/chiselTests/BlackBox.scala +++ b/src/test/scala/chiselTests/BlackBox.scala @@ -8,7 +8,7 @@ import org.scalatest._ import chisel3._ import chisel3.testers.BasicTester import chisel3.util._ -import chisel3.Strict.CompileOptions +//import chisel3.ExplicitCompileOptions.Strict class BlackBoxInverter extends BlackBox { val io = IO(new Bundle() { diff --git a/src/test/scala/chiselTests/BundleWire.scala b/src/test/scala/chiselTests/BundleWire.scala index 15c5d5f8..07360c34 100644 --- a/src/test/scala/chiselTests/BundleWire.scala +++ b/src/test/scala/chiselTests/BundleWire.scala @@ -5,7 +5,7 @@ import chisel3._ import org.scalatest._ import org.scalatest.prop._ import chisel3.testers.BasicTester -import chisel3.Strict.CompileOptions +//import chisel3.ExplicitCompileOptions.Strict class Coord extends Bundle { val x = UInt.width( 32) diff --git a/src/test/scala/chiselTests/CompileOptionsTest.scala b/src/test/scala/chiselTests/CompileOptionsTest.scala index de75d07b..508c0849 100644 --- a/src/test/scala/chiselTests/CompileOptionsTest.scala +++ b/src/test/scala/chiselTests/CompileOptionsTest.scala @@ -5,17 +5,17 @@ package chiselTests import org.scalatest._ import chisel3._ import chisel3.core.Binding.BindingException -import chisel3.internal.ExplicitCompileOptions +import chisel3.ExplicitImplicitCompileOptions import chisel3.testers.BasicTester class CompileOptionsSpec extends ChiselFlatSpec { - abstract class StrictModule extends Module()(chisel3.Strict.CompileOptions) - abstract class NotStrictModule extends Module()(chisel3.NotStrict.CompileOptions) + abstract class StrictModule extends Module()(chisel3.ExplicitCompileOptions.Strict) + abstract class NotStrictModule extends Module()(chisel3.ExplicitCompileOptions.NotStrict) // Generate a set of options that do not have requireIOWrap enabled, in order to // ensure its definition comes from the implicit options passed to the Module constructor. - object StrictWithoutIOWrap extends ExplicitCompileOptions { + object StrictWithoutIOWrap extends ExplicitImplicitCompileOptions { val connectFieldsMustMatch = true val declaredTypeMustBeUnbound = true val requireIOWrap = false @@ -35,7 +35,7 @@ class CompileOptionsSpec extends ChiselFlatSpec { "A Module with missing bundle fields when compiled with implicit Strict.CompileOption " should "throw an exception" in { a [ChiselException] should be thrownBy { - import chisel3.Strict.CompileOptions + import chisel3.ExplicitCompileOptions.Strict class ConnectFieldMismatchModule extends Module { val io = IO(new Bundle { @@ -49,7 +49,7 @@ class CompileOptionsSpec extends ChiselFlatSpec { } "A Module with missing bundle fields when compiled with implicit NotStrict.CompileOption " should "not throw an exception" in { - import chisel3.NotStrict.CompileOptions + import chisel3.ExplicitCompileOptions.NotStrict class ConnectFieldMismatchModule extends Module { val io = IO(new Bundle { @@ -63,7 +63,7 @@ class CompileOptionsSpec extends ChiselFlatSpec { "A Module in which a Reg is created with a bound type when compiled with implicit Strict.CompileOption " should "throw an exception" in { a [BindingException] should be thrownBy { - import chisel3.Strict.CompileOptions + import chisel3.ExplicitCompileOptions.Strict class CreateRegFromBoundTypeModule extends Module { val io = IO(new Bundle { @@ -77,7 +77,7 @@ class CompileOptionsSpec extends ChiselFlatSpec { } "A Module in which a Reg is created with a bound type when compiled with implicit NotStrict.CompileOption " should "not throw an exception" in { - import chisel3.NotStrict.CompileOptions + import chisel3.ExplicitCompileOptions.NotStrict class CreateRegFromBoundTypeModule extends Module { val io = IO(new Bundle { @@ -90,7 +90,7 @@ class CompileOptionsSpec extends ChiselFlatSpec { } "A Module with wrapped IO when compiled with implicit Strict.CompileOption " should "not throw an exception" in { - import chisel3.Strict.CompileOptions + import chisel3.ExplicitCompileOptions.Strict class RequireIOWrapModule extends Module { val io = IO(new Bundle { @@ -103,7 +103,7 @@ class CompileOptionsSpec extends ChiselFlatSpec { } "A Module with unwrapped IO when compiled with implicit NotStrict.CompileOption " should "not throw an exception" in { - import chisel3.NotStrict.CompileOptions + import chisel3.ExplicitCompileOptions.NotStrict class RequireIOWrapModule extends Module { val io = new Bundle { @@ -117,7 +117,7 @@ class CompileOptionsSpec extends ChiselFlatSpec { "A Module with unwrapped IO when compiled with implicit Strict.CompileOption " should "throw an exception" in { a [BindingException] should be thrownBy { - import chisel3.Strict.CompileOptions + import chisel3.ExplicitCompileOptions.Strict class RequireIOWrapModule extends Module { val io = new Bundle { @@ -134,7 +134,7 @@ class CompileOptionsSpec extends ChiselFlatSpec { "A Module connecting output as source to input as sink when compiled with implicit Strict.CompileOption " should "throw an exception" in { a [ChiselException] should be thrownBy { - import chisel3.Strict.CompileOptions + import chisel3.ExplicitCompileOptions.Strict class SimpleModule extends Module { val io = IO(new Bundle { @@ -151,7 +151,7 @@ class CompileOptionsSpec extends ChiselFlatSpec { } "A Module connecting output as source to input as sink when compiled with implicit NotStrict.CompileOption " should "not throw an exception" in { - import chisel3.NotStrict.CompileOptions + import chisel3.ExplicitCompileOptions.NotStrict class SimpleModule extends Module { val io = IO(new Bundle { @@ -170,7 +170,7 @@ class CompileOptionsSpec extends ChiselFlatSpec { a [ChiselException] should be thrownBy { // Verify we can suppress the inclusion of default compileOptions import Chisel.{defaultCompileOptions => _, _} - import chisel3.Strict.CompileOptions + import chisel3.ExplicitCompileOptions.Strict class SimpleModule extends Module { val io = IO(new Bundle { @@ -191,7 +191,7 @@ class CompileOptionsSpec extends ChiselFlatSpec { } "A Module with directionless connections when compiled with implicit NotStrict.CompileOption " should "not throw an exception" in { - import chisel3.NotStrict.CompileOptions + import chisel3.ExplicitCompileOptions.NotStrict class SimpleModule extends Module { val io = IO(new Bundle { @@ -258,7 +258,7 @@ class CompileOptionsSpec extends ChiselFlatSpec { object StrictNotIOWrap { - implicit object CompileOptions extends ExplicitCompileOptions { + implicit object CompileOptions extends ExplicitImplicitCompileOptions { val connectFieldsMustMatch = true val declaredTypeMustBeUnbound = true val requireIOWrap = false diff --git a/src/test/scala/chiselTests/ComplexAssign.scala b/src/test/scala/chiselTests/ComplexAssign.scala index 48a673cf..0a1f31cc 100644 --- a/src/test/scala/chiselTests/ComplexAssign.scala +++ b/src/test/scala/chiselTests/ComplexAssign.scala @@ -8,7 +8,6 @@ import org.scalatest.prop._ import chisel3._ import chisel3.testers.BasicTester import chisel3.util._ -import chisel3.NotStrict.CompileOptions 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 46ab6dfc..69d8a44a 100644 --- a/src/test/scala/chiselTests/Counter.scala +++ b/src/test/scala/chiselTests/Counter.scala @@ -8,7 +8,6 @@ import org.scalatest.prop._ import chisel3._ import chisel3.testers.BasicTester import chisel3.util._ -import chisel3.Strict.CompileOptions 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 35c83a8a..b50a80c0 100644 --- a/src/test/scala/chiselTests/Decoder.scala +++ b/src/test/scala/chiselTests/Decoder.scala @@ -9,7 +9,6 @@ import org.scalacheck._ import chisel3._ import chisel3.testers.BasicTester import chisel3.util._ -import chisel3.NotStrict.CompileOptions class Decoder(bitpats: List[String]) extends Module { val io = IO(new Bundle { diff --git a/src/test/scala/chiselTests/DeqIOSpec.scala b/src/test/scala/chiselTests/DeqIOSpec.scala index 31508149..d41c50e5 100644 --- a/src/test/scala/chiselTests/DeqIOSpec.scala +++ b/src/test/scala/chiselTests/DeqIOSpec.scala @@ -5,7 +5,6 @@ package chiselTests import chisel3._ import chisel3.testers.BasicTester import chisel3.util._ -import chisel3.NotStrict.CompileOptions /** * Created by chick on 2/8/16. diff --git a/src/test/scala/chiselTests/Direction.scala b/src/test/scala/chiselTests/Direction.scala index 7cfe8268..949b92ed 100644 --- a/src/test/scala/chiselTests/Direction.scala +++ b/src/test/scala/chiselTests/Direction.scala @@ -6,7 +6,6 @@ import chisel3._ import org.scalatest._ import org.scalatest.prop._ import chisel3.testers.BasicTester -import chisel3.NotStrict.CompileOptions class DirectionHaver extends Module { val io = IO(new Bundle { diff --git a/src/test/scala/chiselTests/EnableShiftRegister.scala b/src/test/scala/chiselTests/EnableShiftRegister.scala index 15173e0f..5f3e0dd1 100644 --- a/src/test/scala/chiselTests/EnableShiftRegister.scala +++ b/src/test/scala/chiselTests/EnableShiftRegister.scala @@ -3,7 +3,6 @@ package chiselTests import chisel3._ import chisel3.testers.BasicTester -import chisel3.NotStrict.CompileOptions class EnableShiftRegister extends Module { val io = IO(new Bundle { diff --git a/src/test/scala/chiselTests/GCD.scala b/src/test/scala/chiselTests/GCD.scala index 21082fc9..d683ce34 100644 --- a/src/test/scala/chiselTests/GCD.scala +++ b/src/test/scala/chiselTests/GCD.scala @@ -6,7 +6,6 @@ import chisel3._ import chisel3.testers.BasicTester import org.scalatest._ import org.scalatest.prop._ -import chisel3.NotStrict.CompileOptions class GCD extends Module { val io = IO(new Bundle { diff --git a/src/test/scala/chiselTests/IOCompatibility.scala b/src/test/scala/chiselTests/IOCompatibility.scala index d100df2b..7bf3dded 100644 --- a/src/test/scala/chiselTests/IOCompatibility.scala +++ b/src/test/scala/chiselTests/IOCompatibility.scala @@ -3,23 +3,22 @@ package chiselTests import chisel3._ -import chisel3.NotStrict.CompileOptions class IOCSimpleIO extends Bundle { - val in = UInt(INPUT, 32) - val out = UInt(OUTPUT, 32) + val in = Input(UInt(width=32)) + val out = Output(UInt(width=32)) } class IOCPlusOne extends Module { - val io = new IOCSimpleIO + val io = IO(new IOCSimpleIO) io.out := io.in + UInt(1) } class IOCModuleVec(val n: Int) extends Module { - val io = new Bundle { - val ins = Vec(n, UInt(INPUT, 32)) - val outs = Vec(n, UInt(OUTPUT, 32)) - } + val io = IO(new Bundle { + val ins = Vec(n, Input(UInt(width=32))) + val outs = Vec(n, Output(UInt(width=32))) + }) val pluses = Vec.fill(n){ Module(new IOCPlusOne).io } for (i <- 0 until n) { pluses(i).in := io.ins(i) @@ -28,7 +27,7 @@ class IOCModuleVec(val n: Int) extends Module { } class IOCModuleWire extends Module { - val io = new IOCSimpleIO + val io = IO(new IOCSimpleIO) val inc = Wire(Module(new IOCPlusOne).io.chiselCloneType) inc.in := io.in io.out := inc.out diff --git a/src/test/scala/chiselTests/LFSR16.scala b/src/test/scala/chiselTests/LFSR16.scala index 3b2b28f6..b13b67e3 100644 --- a/src/test/scala/chiselTests/LFSR16.scala +++ b/src/test/scala/chiselTests/LFSR16.scala @@ -5,7 +5,6 @@ package chiselTests import chisel3._ import chisel3.testers.BasicTester import chisel3.util._ -import chisel3.NotStrict.CompileOptions class LFSR16 extends Module { val io = IO(new Bundle { diff --git a/src/test/scala/chiselTests/MemorySearch.scala b/src/test/scala/chiselTests/MemorySearch.scala index a2a8eb8b..1d09f3c5 100644 --- a/src/test/scala/chiselTests/MemorySearch.scala +++ b/src/test/scala/chiselTests/MemorySearch.scala @@ -4,7 +4,6 @@ package chiselTests import chisel3._ import chisel3.testers.BasicTester -import chisel3.NotStrict.CompileOptions class MemorySearch extends Module { val io = IO(new Bundle { diff --git a/src/test/scala/chiselTests/Module.scala b/src/test/scala/chiselTests/Module.scala index 1f0ab084..7a4050db 100644 --- a/src/test/scala/chiselTests/Module.scala +++ b/src/test/scala/chiselTests/Module.scala @@ -3,7 +3,6 @@ package chiselTests import chisel3._ -import chisel3.NotStrict.CompileOptions class SimpleIO extends Bundle { val in = Input(UInt.width(32)) diff --git a/src/test/scala/chiselTests/MulLookup.scala b/src/test/scala/chiselTests/MulLookup.scala index 4548ae40..26ee4e03 100644 --- a/src/test/scala/chiselTests/MulLookup.scala +++ b/src/test/scala/chiselTests/MulLookup.scala @@ -6,7 +6,6 @@ import chisel3._ import org.scalatest._ import org.scalatest.prop._ import chisel3.testers.BasicTester -import chisel3.NotStrict.CompileOptions class MulLookup(val w: Int) extends Module { val io = IO(new Bundle { diff --git a/src/test/scala/chiselTests/MultiAssign.scala b/src/test/scala/chiselTests/MultiAssign.scala index 8fc1d0cb..fa4c4898 100644 --- a/src/test/scala/chiselTests/MultiAssign.scala +++ b/src/test/scala/chiselTests/MultiAssign.scala @@ -7,7 +7,6 @@ import org.scalatest._ import chisel3._ import chisel3.testers.BasicTester import chisel3.util._ -import chisel3.Strict.CompileOptions 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 d2165f62..8e4c7579 100644 --- a/src/test/scala/chiselTests/OptionBundle.scala +++ b/src/test/scala/chiselTests/OptionBundle.scala @@ -5,7 +5,6 @@ package chiselTests import org.scalatest._ import chisel3._ import chisel3.testers.BasicTester -import chisel3.NotStrict.CompileOptions 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 c7265c6c..42df6802 100644 --- a/src/test/scala/chiselTests/Padding.scala +++ b/src/test/scala/chiselTests/Padding.scala @@ -3,7 +3,6 @@ package chiselTests import chisel3._ -import chisel3.NotStrict.CompileOptions class Padder extends Module { val io = IO(new Bundle { diff --git a/src/test/scala/chiselTests/ParameterizedModule.scala b/src/test/scala/chiselTests/ParameterizedModule.scala index b75d898b..14b21631 100644 --- a/src/test/scala/chiselTests/ParameterizedModule.scala +++ b/src/test/scala/chiselTests/ParameterizedModule.scala @@ -5,7 +5,6 @@ package chiselTests import org.scalatest._ import chisel3._ import chisel3.testers.BasicTester -import chisel3.NotStrict.CompileOptions class ParameterizedModule(invert: Boolean) extends Module { val io = IO(new Bundle { diff --git a/src/test/scala/chiselTests/PrintableSpec.scala b/src/test/scala/chiselTests/PrintableSpec.scala index afef3c54..12564a40 100644 --- a/src/test/scala/chiselTests/PrintableSpec.scala +++ b/src/test/scala/chiselTests/PrintableSpec.scala @@ -5,7 +5,6 @@ import scala.collection.mutable import chisel3._ import chisel3.testers.BasicTester -import chisel3.Strict.CompileOptions /* Printable Tests */ class PrintableSpec extends FlatSpec with Matchers { diff --git a/src/test/scala/chiselTests/Reg.scala b/src/test/scala/chiselTests/Reg.scala index 741393b0..a9086223 100644 --- a/src/test/scala/chiselTests/Reg.scala +++ b/src/test/scala/chiselTests/Reg.scala @@ -6,7 +6,6 @@ import org.scalatest._ import chisel3._ import chisel3.core.DataMirror import chisel3.testers.BasicTester -import chisel3.Strict.CompileOptions 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 e27cbdca..6d5a0a76 100644 --- a/src/test/scala/chiselTests/Risc.scala +++ b/src/test/scala/chiselTests/Risc.scala @@ -4,7 +4,6 @@ package chiselTests import chisel3._ import chisel3.util._ -import chisel3.NotStrict.CompileOptions class Risc extends Module { val io = IO(new Bundle { diff --git a/src/test/scala/chiselTests/SIntOps.scala b/src/test/scala/chiselTests/SIntOps.scala index d070295c..418318fb 100644 --- a/src/test/scala/chiselTests/SIntOps.scala +++ b/src/test/scala/chiselTests/SIntOps.scala @@ -4,7 +4,7 @@ package chiselTests import chisel3._ import chisel3.testers.BasicTester -import chisel3.NotStrict.CompileOptions +//import chisel3.ExplicitCompileOptions.NotStrict class SIntOps extends Module { val io = IO(new Bundle { diff --git a/src/test/scala/chiselTests/Stack.scala b/src/test/scala/chiselTests/Stack.scala index f1210260..937f1978 100644 --- a/src/test/scala/chiselTests/Stack.scala +++ b/src/test/scala/chiselTests/Stack.scala @@ -6,7 +6,7 @@ import scala.collection.mutable.Stack import chisel3._ import chisel3.util._ -import chisel3.NotStrict.CompileOptions +//import chisel3.ExplicitCompileOptions.NotStrict class ChiselStack(val depth: Int) extends Module { val io = IO(new Bundle { diff --git a/src/test/scala/chiselTests/Tbl.scala b/src/test/scala/chiselTests/Tbl.scala index df8ce02c..5ff1aa31 100644 --- a/src/test/scala/chiselTests/Tbl.scala +++ b/src/test/scala/chiselTests/Tbl.scala @@ -8,7 +8,7 @@ import org.scalatest.prop._ import chisel3._ import chisel3.testers.BasicTester import chisel3.util._ -import chisel3.NotStrict.CompileOptions +//import chisel3.ExplicitCompileOptions.NotStrict class Tbl(w: Int, n: Int) extends Module { val io = IO(new Bundle { diff --git a/src/test/scala/chiselTests/TesterDriverSpec.scala b/src/test/scala/chiselTests/TesterDriverSpec.scala index 6dc075d7..a5351763 100644 --- a/src/test/scala/chiselTests/TesterDriverSpec.scala +++ b/src/test/scala/chiselTests/TesterDriverSpec.scala @@ -5,7 +5,7 @@ package chiselTests import chisel3._ import chisel3.testers.BasicTester import chisel3.util._ -import chisel3.Strict.CompileOptions +//import chisel3.ExplicitCompileOptions.Strict /** 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 237cea16..d80d6f17 100644 --- a/src/test/scala/chiselTests/UIntOps.scala +++ b/src/test/scala/chiselTests/UIntOps.scala @@ -5,7 +5,7 @@ package chiselTests import chisel3._ import org.scalatest._ import chisel3.testers.BasicTester -import chisel3.NotStrict.CompileOptions +//import chisel3.ExplicitCompileOptions.NotStrict class UIntOps extends Module { val io = IO(new Bundle { diff --git a/src/test/scala/chiselTests/Vec.scala b/src/test/scala/chiselTests/Vec.scala index abe483a4..a7dd975f 100644 --- a/src/test/scala/chiselTests/Vec.scala +++ b/src/test/scala/chiselTests/Vec.scala @@ -8,7 +8,7 @@ import org.scalatest.prop._ import chisel3._ import chisel3.testers.BasicTester import chisel3.util._ -import chisel3.Strict.CompileOptions +//import chisel3.ExplicitCompileOptions.Strict 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 588e1ce2..221fd6d8 100644 --- a/src/test/scala/chiselTests/VectorPacketIO.scala +++ b/src/test/scala/chiselTests/VectorPacketIO.scala @@ -5,7 +5,7 @@ package chiselTests import chisel3._ import chisel3.testers.BasicTester import chisel3.util._ -import chisel3.NotStrict.CompileOptions +//import chisel3.ExplicitCompileOptions.NotStrict /** * 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 2a0ac824..5f65659b 100644 --- a/src/test/scala/chiselTests/VendingMachine.scala +++ b/src/test/scala/chiselTests/VendingMachine.scala @@ -4,7 +4,7 @@ package chiselTests import chisel3._ import chisel3.util._ -import chisel3.NotStrict.CompileOptions +//import chisel3.ExplicitCompileOptions.NotStrict class VendingMachine extends Module { val io = IO(new Bundle { diff --git a/src/test/scala/chiselTests/When.scala b/src/test/scala/chiselTests/When.scala index 1920b30e..0183c29b 100644 --- a/src/test/scala/chiselTests/When.scala +++ b/src/test/scala/chiselTests/When.scala @@ -7,7 +7,7 @@ import org.scalatest._ import chisel3._ import chisel3.testers.BasicTester import chisel3.util._ -import chisel3.Strict.CompileOptions +//import chisel3.ExplicitCompileOptions.Strict class WhenTester() extends BasicTester { val cnt = Counter(4) -- cgit v1.2.3 From 96fb6a5e2c781b20470d02eac186b1b129c20bdf Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Thu, 29 Sep 2016 14:57:42 -0700 Subject: Consolidate CompileOptions and re-enable NotStrict pending macro work. --- .../src/main/scala/chisel3/CompileOptions.scala | 53 ---------------------- .../src/main/scala/chisel3/core/Aggregate.scala | 12 ++--- .../src/main/scala/chisel3/core/BiConnect.scala | 6 +-- .../src/main/scala/chisel3/core/Bits.scala | 3 +- .../src/main/scala/chisel3/core/BlackBox.scala | 3 +- .../main/scala/chisel3/core/CompileOptions.scala | 48 ++++++++++++++++++++ .../src/main/scala/chisel3/core/Data.scala | 14 +++--- .../src/main/scala/chisel3/core/Mem.scala | 3 +- .../src/main/scala/chisel3/core/Module.scala | 4 +- .../src/main/scala/chisel3/core/MonoConnect.scala | 6 +-- .../src/main/scala/chisel3/core/Reg.scala | 10 ++-- src/main/scala/chisel3/compatibility.scala | 2 +- src/main/scala/chisel3/testers/BasicTester.scala | 2 +- src/main/scala/chisel3/util/Arbiter.scala | 3 +- src/main/scala/chisel3/util/Counter.scala | 2 +- src/main/scala/chisel3/util/Decoupled.scala | 3 +- src/main/scala/chisel3/util/LFSR.scala | 2 +- src/main/scala/chisel3/util/Reg.scala | 3 +- src/main/scala/chisel3/util/Valid.scala | 3 +- src/test/scala/chiselTests/BlackBox.scala | 2 +- src/test/scala/chiselTests/BundleWire.scala | 2 +- .../scala/chiselTests/CompileOptionsTest.scala | 33 +++++++------- src/test/scala/chiselTests/SIntOps.scala | 1 - src/test/scala/chiselTests/Stack.scala | 1 - src/test/scala/chiselTests/Tbl.scala | 1 - src/test/scala/chiselTests/TesterDriverSpec.scala | 2 +- src/test/scala/chiselTests/UIntOps.scala | 1 - src/test/scala/chiselTests/Vec.scala | 2 +- src/test/scala/chiselTests/VectorPacketIO.scala | 1 - src/test/scala/chiselTests/VendingMachine.scala | 1 - src/test/scala/chiselTests/When.scala | 2 +- 31 files changed, 114 insertions(+), 117 deletions(-) delete mode 100644 chiselFrontend/src/main/scala/chisel3/CompileOptions.scala create mode 100644 chiselFrontend/src/main/scala/chisel3/core/CompileOptions.scala diff --git a/chiselFrontend/src/main/scala/chisel3/CompileOptions.scala b/chiselFrontend/src/main/scala/chisel3/CompileOptions.scala deleted file mode 100644 index 2e5c64aa..00000000 --- a/chiselFrontend/src/main/scala/chisel3/CompileOptions.scala +++ /dev/null @@ -1,53 +0,0 @@ -// See LICENSE for license details. - -package chisel3 - -import scala.language.experimental.macros - -trait CompileOptions { - // Should Bundle connections require a strict match of fields. - // If true and the same fields aren't present in both source and sink, a MissingFieldException, - // MissingLeftFieldException, or MissingRightFieldException will be thrown. - val connectFieldsMustMatch: Boolean - // When creating an object that takes a type argument, the argument must be unbound (a pure type). - val declaredTypeMustBeUnbound: Boolean - // Module IOs should be wrapped in an IO() to define their bindings before the reset of the module is defined. - val requireIOWrap: Boolean - // If a connection operator fails, don't try the connection with the operands (source and sink) reversed. - val dontTryConnectionsSwapped: Boolean - // If connection directionality is not explicit, do not use heuristics to attempt to determine it. - val dontAssumeDirectionality: Boolean -} - -trait ImplicitCompileOptions extends CompileOptions - -object ImplicitCompileOptions { - // Provides a low priority Strict default. Can be overridden by importing the NotStrict option. - implicit def materialize: ImplicitCompileOptions = chisel3.ExplicitCompileOptions.Strict -} - -// Define a more-specific trait which should be perferred if both are available. -trait ExplicitImplicitCompileOptions extends ImplicitCompileOptions - -object ExplicitCompileOptions { - // Collection of "not strict" connection compile options. - // These provide compatibility with existing code. - // import chisel3.ExplicitCompileOptions.NotStrict - implicit object NotStrict extends ExplicitImplicitCompileOptions { - val connectFieldsMustMatch = false - val declaredTypeMustBeUnbound = false - val requireIOWrap = false - val dontTryConnectionsSwapped = false - val dontAssumeDirectionality = false - } - - // Collection of "strict" connection compile options, preferred for new code. - // import chisel3.ExplicitCompileOptions.Strict - implicit object Strict extends ExplicitImplicitCompileOptions { - val connectFieldsMustMatch = true - val declaredTypeMustBeUnbound = true - val requireIOWrap = true - val dontTryConnectionsSwapped = true - val dontAssumeDirectionality = true - } -} diff --git a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala index b363c572..a28c4bec 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala @@ -10,7 +10,7 @@ import chisel3.internal._ import chisel3.internal.Builder.pushCommand import chisel3.internal.firrtl._ import chisel3.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, VecTransform, SourceInfoTransform} -import chisel3.ImplicitCompileOptions +//import chisel3.CompileOptions /** An abstract class for data types that solely consist of (are an aggregate * of) other Data objects. @@ -152,27 +152,27 @@ sealed class Vec[T <: Data] private (gen: T, val length: Int) * * @note the length of this Vec must match the length of the input Seq */ - def <> (that: Seq[T])(implicit sourceInfo: SourceInfo, moduleCompileOptions: ImplicitCompileOptions): Unit = { + def <> (that: Seq[T])(implicit sourceInfo: SourceInfo, moduleCompileOptions: CompileOptions): 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, moduleCompileOptions: ImplicitCompileOptions): Unit = this bulkConnect that.asInstanceOf[Data] + def <> (that: Vec[T])(implicit sourceInfo: SourceInfo, moduleCompileOptions: CompileOptions): Unit = this bulkConnect that.asInstanceOf[Data] /** 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, moduleCompileOptions: ImplicitCompileOptions): Unit = { + def := (that: Seq[T])(implicit sourceInfo: SourceInfo, moduleCompileOptions: CompileOptions): 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, moduleCompileOptions: ImplicitCompileOptions): Unit = this connect that + def := (that: Vec[T])(implicit sourceInfo: SourceInfo, moduleCompileOptions: CompileOptions): Unit = this connect that /** Creates a dynamically indexed read or write accessor into the array. */ @@ -199,7 +199,7 @@ sealed class Vec[T <: Data] private (gen: T, val length: Int) @deprecated("Use Vec.apply instead", "chisel3") def write(idx: UInt, data: T): Unit = { - apply(idx).:=(data)(DeprecatedSourceInfo, chisel3.ExplicitCompileOptions.NotStrict) + apply(idx).:=(data)(DeprecatedSourceInfo, chisel3.core.ExplicitCompileOptions.NotStrict) } override def cloneType: this.type = { diff --git a/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala b/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala index a6b9cda3..16bde731 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala @@ -6,7 +6,7 @@ import chisel3.internal.Builder.pushCommand import chisel3.internal.firrtl.Connect import scala.language.experimental.macros import chisel3.internal.sourceinfo._ -import chisel3.ImplicitCompileOptions +//import chisel3.CompileOptions /** * BiConnect.connect executes a bidirectional connection element-wise. @@ -50,7 +50,7 @@ object BiConnect { * during the recursive decent and then rethrow them with extra information added. * This gives the user a 'path' to where in the connections things went wrong. */ - def connect(sourceInfo: SourceInfo, connectCompileOptions: ImplicitCompileOptions, left: Data, right: Data, context_mod: Module): Unit = + def connect(sourceInfo: SourceInfo, connectCompileOptions: CompileOptions, left: Data, right: Data, context_mod: Module): Unit = (left, right) match { // Handle element case (root case) case (left_e: Element, right_e: Element) => { @@ -110,7 +110,7 @@ object BiConnect { // This function checks if element-level connection operation allowed. // Then it either issues it or throws the appropriate exception. - def elemConnect(implicit sourceInfo: SourceInfo, connectCompileOptions: ImplicitCompileOptions, left: Element, right: Element, context_mod: Module): Unit = { + def elemConnect(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions, left: Element, right: Element, context_mod: Module): Unit = { import Direction.{Input, Output} // Using extensively so import these // If left or right have no location, assume in context module // This can occur if one of them is a literal, unbound will error previously diff --git a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala index 12c99104..24abbdba 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala @@ -10,7 +10,8 @@ import chisel3.internal.firrtl._ import chisel3.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, SourceInfoTransform, SourceInfoWhiteboxTransform, UIntTransform, MuxTransform} import chisel3.internal.firrtl.PrimOp._ -//import chisel3.ImplicitCompileOptions.NotStrict +// TODO: remove this once we have CompileOptions threaded through the macro system. +import chisel3.core.ExplicitCompileOptions.NotStrict /** Element is a leaf data type: it cannot contain other Data objects. Example * uses are for representing primitive data types, like integers and bits. diff --git a/chiselFrontend/src/main/scala/chisel3/core/BlackBox.scala b/chiselFrontend/src/main/scala/chisel3/core/BlackBox.scala index 7e61ec72..c1352566 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/BlackBox.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/BlackBox.scala @@ -5,7 +5,8 @@ package chisel3.core import chisel3.internal.Builder.pushCommand import chisel3.internal.firrtl.{ModuleIO, DefInvalid} import chisel3.internal.sourceinfo.SourceInfo -//import chisel3.ExplicitCompileOptions.NotStrict +// TODO: remove this once we have CompileOptions threaded through the macro system. +import chisel3.core.ExplicitCompileOptions.NotStrict /** 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/CompileOptions.scala b/chiselFrontend/src/main/scala/chisel3/core/CompileOptions.scala new file mode 100644 index 00000000..0e66a241 --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel3/core/CompileOptions.scala @@ -0,0 +1,48 @@ +// See LICENSE for license details. + +package chisel3.core + +import scala.language.experimental.macros + +trait CompileOptions { + // Should Bundle connections require a strict match of fields. + // If true and the same fields aren't present in both source and sink, a MissingFieldException, + // MissingLeftFieldException, or MissingRightFieldException will be thrown. + val connectFieldsMustMatch: Boolean + // When creating an object that takes a type argument, the argument must be unbound (a pure type). + val declaredTypeMustBeUnbound: Boolean + // Module IOs should be wrapped in an IO() to define their bindings before the reset of the module is defined. + val requireIOWrap: Boolean + // If a connection operator fails, don't try the connection with the operands (source and sink) reversed. + val dontTryConnectionsSwapped: Boolean + // If connection directionality is not explicit, do not use heuristics to attempt to determine it. + val dontAssumeDirectionality: Boolean +} + +object CompileOptions { + // Provides a low priority Strict default. Can be overridden by importing the NotStrict option. + implicit def materialize: CompileOptions = chisel3.core.ExplicitCompileOptions.Strict +} + +object ExplicitCompileOptions { + // Collection of "not strict" connection compile options. + // These provide compatibility with existing code. + // import chisel3.core.ExplicitCompileOptions.NotStrict + implicit object NotStrict extends CompileOptions { + val connectFieldsMustMatch = false + val declaredTypeMustBeUnbound = false + val requireIOWrap = false + val dontTryConnectionsSwapped = false + val dontAssumeDirectionality = false + } + + // Collection of "strict" connection compile options, preferred for new code. + // import chisel3.core.ExplicitCompileOptions.Strict + implicit object Strict extends CompileOptions { + val connectFieldsMustMatch = true + val declaredTypeMustBeUnbound = true + val requireIOWrap = true + val dontTryConnectionsSwapped = true + val dontAssumeDirectionality = true + } +} diff --git a/chiselFrontend/src/main/scala/chisel3/core/Data.scala b/chiselFrontend/src/main/scala/chisel3/core/Data.scala index 1b08374a..83619fc8 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Data.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Data.scala @@ -9,7 +9,7 @@ import chisel3.internal.Builder.{pushCommand, pushOp} import chisel3.internal.firrtl._ import chisel3.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, UnlocatableSourceInfo, WireTransform, SourceInfoTransform} import chisel3.internal.firrtl.PrimOp.AsUIntOp -import chisel3.ImplicitCompileOptions +//import chisel3.CompileOptions sealed abstract class Direction(name: String) { override def toString: String = name @@ -126,7 +126,7 @@ abstract class Data extends HasId { private[core] def badConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit = throwException(s"cannot connect ${this} and ${that}") - private[chisel3] def connect(that: Data)(implicit sourceInfo: SourceInfo, connectCompileOptions: ImplicitCompileOptions): Unit = { + private[chisel3] def connect(that: Data)(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions): Unit = { Binding.checkSynthesizable(this, s"'this' ($this)") Binding.checkSynthesizable(that, s"'that' ($that)") try { @@ -138,7 +138,7 @@ abstract class Data extends HasId { ) } } - private[chisel3] def bulkConnect(that: Data)(implicit sourceInfo: SourceInfo, connectCompileOptions: ImplicitCompileOptions): Unit = { + private[chisel3] def bulkConnect(that: Data)(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions): Unit = { Binding.checkSynthesizable(this, s"'this' ($this)") Binding.checkSynthesizable(that, s"'that' ($that)") try { @@ -167,8 +167,8 @@ abstract class Data extends HasId { } clone } - final def := (that: Data)(implicit sourceInfo: SourceInfo, connectionCompileOptions: ImplicitCompileOptions): Unit = this.connect(that)(sourceInfo, connectionCompileOptions) - final def <> (that: Data)(implicit sourceInfo: SourceInfo, connectionCompileOptions: ImplicitCompileOptions): Unit = this.bulkConnect(that)(sourceInfo, connectionCompileOptions) + final def := (that: Data)(implicit sourceInfo: SourceInfo, connectionCompileOptions: CompileOptions): Unit = this.connect(that)(sourceInfo, connectionCompileOptions) + final def <> (that: Data)(implicit sourceInfo: SourceInfo, connectionCompileOptions: CompileOptions): Unit = this.bulkConnect(that)(sourceInfo, connectionCompileOptions) def litArg(): Option[LitArg] = None def litValue(): BigInt = litArg.get.num def isLit(): Boolean = litArg.isDefined @@ -260,7 +260,7 @@ object Wire { do_apply(t, init)(UnlocatableSourceInfo) def do_apply[T <: Data](t: T, init: T)(implicit sourceInfo: SourceInfo): T = { - val x = Reg.makeType(chisel3.ExplicitCompileOptions.NotStrict, t, null.asInstanceOf[T], init) + val x = Reg.makeType(chisel3.core.ExplicitCompileOptions.NotStrict, t, null.asInstanceOf[T], init) // Bind each element of x to being a Wire Binding.bind(x, WireBinder(Builder.forcedModule), "Error: t") @@ -294,7 +294,7 @@ sealed class Clock extends Element(Width(1)) { private[core] def cloneTypeWidth(width: Width): this.type = cloneType private[chisel3] def toType = "Clock" - override def connect (that: Data)(implicit sourceInfo: SourceInfo, connectCompileOptions: ImplicitCompileOptions): Unit = that match { + override def connect (that: Data)(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions): Unit = that match { case _: Clock => super.connect(that)(sourceInfo, connectCompileOptions) case _ => super.badConnect(that)(sourceInfo) } diff --git a/chiselFrontend/src/main/scala/chisel3/core/Mem.scala b/chiselFrontend/src/main/scala/chisel3/core/Mem.scala index d762ef5e..b24d463a 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Mem.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Mem.scala @@ -8,7 +8,8 @@ import chisel3.internal._ import chisel3.internal.Builder.pushCommand import chisel3.internal.firrtl._ import chisel3.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, UnlocatableSourceInfo, MemTransform} -//import chisel3.ExplicitCompileOptions.NotStrict +// TODO: remove this once we have CompileOptions threaded through the macro system. +import chisel3.core.ExplicitCompileOptions.NotStrict 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 f4b36888..55ef7491 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Module.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Module.scala @@ -9,7 +9,7 @@ import chisel3.internal.Builder._ import chisel3.internal.firrtl._ import chisel3.internal.firrtl.{Command => _, _} import chisel3.internal.sourceinfo.{InstTransform, SourceInfo, UnlocatableSourceInfo} -import chisel3.ImplicitCompileOptions +//import chisel3.CompileOptions object Module { /** A wrapper method that all Module instantiations must be wrapped in @@ -51,7 +51,7 @@ object Module { */ abstract class Module( override_clock: Option[Clock]=None, override_reset: Option[Bool]=None) - (implicit moduleCompileOptions: ImplicitCompileOptions) + (implicit moduleCompileOptions: CompileOptions) extends HasId { // _clock and _reset can be clock and reset in these 2ary constructors // once chisel2 compatibility issues are resolved diff --git a/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala b/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala index 38030d49..48efda4d 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala @@ -6,7 +6,7 @@ import chisel3.internal.Builder.pushCommand import chisel3.internal.firrtl.Connect import scala.language.experimental.macros import chisel3.internal.sourceinfo.{DeprecatedSourceInfo, SourceInfo, SourceInfoTransform, UnlocatableSourceInfo, WireTransform} -import chisel3.ImplicitCompileOptions +//import chisel3.CompileOptions /** * MonoConnect.connect executes a mono-directional connection element-wise. @@ -56,7 +56,7 @@ object MonoConnect { * during the recursive decent and then rethrow them with extra information added. * This gives the user a 'path' to where in the connections things went wrong. */ - def connect(sourceInfo: SourceInfo, connectCompileOptions: ImplicitCompileOptions, sink: Data, source: Data, context_mod: Module): Unit = + def connect(sourceInfo: SourceInfo, connectCompileOptions: CompileOptions, sink: Data, source: Data, context_mod: Module): Unit = (sink, source) match { // Handle element case (root case) case (sink_e: Element, source_e: Element) => { @@ -103,7 +103,7 @@ object MonoConnect { // This function checks if element-level connection operation allowed. // Then it either issues it or throws the appropriate exception. - def elemConnect(implicit sourceInfo: SourceInfo, connectCompileOptions: ImplicitCompileOptions, sink: Element, source: Element, context_mod: Module): Unit = { + def elemConnect(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions, sink: Element, source: Element, context_mod: Module): Unit = { import Direction.{Input, Output} // Using extensively so import these // If source has no location, assume in context module // This can occur if is a literal, unbound will error previously diff --git a/chiselFrontend/src/main/scala/chisel3/core/Reg.scala b/chiselFrontend/src/main/scala/chisel3/core/Reg.scala index 1bdfb40f..30c2b3cd 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Reg.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Reg.scala @@ -6,10 +6,10 @@ import chisel3.internal._ import chisel3.internal.Builder.pushCommand import chisel3.internal.firrtl._ import chisel3.internal.sourceinfo.{SourceInfo, UnlocatableSourceInfo} -import chisel3.ImplicitCompileOptions +//import chisel3.CompileOptions object Reg { - private[core] def makeType[T <: Data](compileOptions: ImplicitCompileOptions, t: T = null, next: T = null, init: T = null): T = { + private[core] def makeType[T <: Data](compileOptions: CompileOptions, t: T = null, next: T = null, init: T = null): T = { if (t ne null) { if (compileOptions.declaredTypeMustBeUnbound) { Binding.checkUnbound(t, s"t ($t) must be unbound Type. Try using cloneType?") @@ -41,7 +41,7 @@ object Reg { * 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)(implicit sourceInfo: SourceInfo, compileOptions: ImplicitCompileOptions): T = + def apply[T <: Data](t: T = null, next: T = null, init: T = null)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T = // Scala macros can't (yet) handle named or default arguments. do_apply(t, next, init)(sourceInfo, compileOptions) @@ -50,9 +50,9 @@ object Reg { * * @param outType: data type for the register */ - def apply[T <: Data](outType: T)(implicit sourceInfo: SourceInfo, compileOptions: ImplicitCompileOptions): T = Reg[T](outType, null.asInstanceOf[T], null.asInstanceOf[T])(sourceInfo, compileOptions) + def apply[T <: Data](outType: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T = Reg[T](outType, null.asInstanceOf[T], null.asInstanceOf[T])(sourceInfo, compileOptions) - def do_apply[T <: Data](t: T, next: T, init: T)(implicit sourceInfo: SourceInfo, compileOptions: ImplicitCompileOptions = chisel3.ExplicitCompileOptions.NotStrict): T = { + def do_apply[T <: Data](t: T, next: T, init: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions = chisel3.core.ExplicitCompileOptions.NotStrict): 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()). diff --git a/src/main/scala/chisel3/compatibility.scala b/src/main/scala/chisel3/compatibility.scala index 646fc84e..aad15f60 100644 --- a/src/main/scala/chisel3/compatibility.scala +++ b/src/main/scala/chisel3/compatibility.scala @@ -4,7 +4,7 @@ // moving to the more standard package naming convention chisel3 (lowercase c). package object Chisel { // scalastyle:ignore package.object.name - implicit val defaultCompileOptions = chisel3.ExplicitCompileOptions.NotStrict + implicit val defaultCompileOptions = chisel3.core.ExplicitCompileOptions.NotStrict type Direction = chisel3.core.Direction val INPUT = chisel3.core.Direction.Input val OUTPUT = chisel3.core.Direction.Output diff --git a/src/main/scala/chisel3/testers/BasicTester.scala b/src/main/scala/chisel3/testers/BasicTester.scala index 93bb4c33..bd7d4027 100644 --- a/src/main/scala/chisel3/testers/BasicTester.scala +++ b/src/main/scala/chisel3/testers/BasicTester.scala @@ -9,7 +9,7 @@ import internal._ import internal.Builder.pushCommand import internal.firrtl._ import internal.sourceinfo.SourceInfo -//import chisel3.ExplicitCompileOptions.NotStrict +//import chisel3.core.ExplicitCompileOptions.NotStrict class BasicTester extends Module() { // The testbench has no IOs, rather it should communicate using printf, assert, and stop. diff --git a/src/main/scala/chisel3/util/Arbiter.scala b/src/main/scala/chisel3/util/Arbiter.scala index adeb1b34..89bb644a 100644 --- a/src/main/scala/chisel3/util/Arbiter.scala +++ b/src/main/scala/chisel3/util/Arbiter.scala @@ -6,7 +6,8 @@ package chisel3.util import chisel3._ -//import chisel3.ExplicitCompileOptions.NotStrict +// TODO: remove this once we have CompileOptions threaded through the macro system. +import chisel3.core.ExplicitCompileOptions.NotStrict /** IO bundle definition for an Arbiter, which takes some number of ready-valid inputs and outputs * (selects) at most one. diff --git a/src/main/scala/chisel3/util/Counter.scala b/src/main/scala/chisel3/util/Counter.scala index b22cfa7b..ba66d667 100644 --- a/src/main/scala/chisel3/util/Counter.scala +++ b/src/main/scala/chisel3/util/Counter.scala @@ -3,7 +3,7 @@ package chisel3.util import chisel3._ -//import chisel3.ExplicitCompileOptions.Strict +//import chisel3.core.ExplicitCompileOptions.Strict /** A counter module * diff --git a/src/main/scala/chisel3/util/Decoupled.scala b/src/main/scala/chisel3/util/Decoupled.scala index 947d02f8..a0cbf4f7 100644 --- a/src/main/scala/chisel3/util/Decoupled.scala +++ b/src/main/scala/chisel3/util/Decoupled.scala @@ -6,7 +6,8 @@ package chisel3.util import chisel3._ -//import chisel3.ExplicitCompileOptions.NotStrict +// TODO: remove this once we have CompileOptions threaded through the macro system. +import chisel3.core.ExplicitCompileOptions.NotStrict /** An I/O Bundle containing 'valid' and 'ready' signals that handshake * the transfer of data stored in the 'bits' subfield. diff --git a/src/main/scala/chisel3/util/LFSR.scala b/src/main/scala/chisel3/util/LFSR.scala index 95b4da81..fedbf194 100644 --- a/src/main/scala/chisel3/util/LFSR.scala +++ b/src/main/scala/chisel3/util/LFSR.scala @@ -6,7 +6,7 @@ package chisel3.util import chisel3._ -//import chisel3.ExplicitCompileOptions.Strict +//import chisel3.core.ExplicitCompileOptions.Strict // scalastyle:off magic.number object LFSR16 { diff --git a/src/main/scala/chisel3/util/Reg.scala b/src/main/scala/chisel3/util/Reg.scala index fcfc9ac5..713a3b2e 100644 --- a/src/main/scala/chisel3/util/Reg.scala +++ b/src/main/scala/chisel3/util/Reg.scala @@ -3,7 +3,8 @@ package chisel3.util import chisel3._ -//import chisel3.ExplicitCompileOptions.NotStrict +// TODO: remove this once we have CompileOptions threaded through the macro system. +import chisel3.core.ExplicitCompileOptions.NotStrict object RegNext { /** Returns a register with the specified next and no reset initialization. diff --git a/src/main/scala/chisel3/util/Valid.scala b/src/main/scala/chisel3/util/Valid.scala index 67be7648..3d153a2a 100644 --- a/src/main/scala/chisel3/util/Valid.scala +++ b/src/main/scala/chisel3/util/Valid.scala @@ -6,7 +6,8 @@ package chisel3.util import chisel3._ -//import chisel3.ExplicitCompileOptions.NotStrict +// TODO: remove this once we have CompileOptions threaded through the macro system. +import chisel3.core.ExplicitCompileOptions.NotStrict /** An Bundle containing data and a signal determining if it is valid */ class Valid[+T <: Data](gen: T) extends Bundle diff --git a/src/test/scala/chiselTests/BlackBox.scala b/src/test/scala/chiselTests/BlackBox.scala index 465dec4e..344754e1 100644 --- a/src/test/scala/chiselTests/BlackBox.scala +++ b/src/test/scala/chiselTests/BlackBox.scala @@ -8,7 +8,7 @@ import org.scalatest._ import chisel3._ import chisel3.testers.BasicTester import chisel3.util._ -//import chisel3.ExplicitCompileOptions.Strict +//import chisel3.core.ExplicitCompileOptions.Strict class BlackBoxInverter extends BlackBox { val io = IO(new Bundle() { diff --git a/src/test/scala/chiselTests/BundleWire.scala b/src/test/scala/chiselTests/BundleWire.scala index 07360c34..53d46e93 100644 --- a/src/test/scala/chiselTests/BundleWire.scala +++ b/src/test/scala/chiselTests/BundleWire.scala @@ -5,7 +5,7 @@ import chisel3._ import org.scalatest._ import org.scalatest.prop._ import chisel3.testers.BasicTester -//import chisel3.ExplicitCompileOptions.Strict +//import chisel3.core.ExplicitCompileOptions.Strict class Coord extends Bundle { val x = UInt.width( 32) diff --git a/src/test/scala/chiselTests/CompileOptionsTest.scala b/src/test/scala/chiselTests/CompileOptionsTest.scala index 508c0849..83077544 100644 --- a/src/test/scala/chiselTests/CompileOptionsTest.scala +++ b/src/test/scala/chiselTests/CompileOptionsTest.scala @@ -5,17 +5,18 @@ package chiselTests import org.scalatest._ import chisel3._ import chisel3.core.Binding.BindingException -import chisel3.ExplicitImplicitCompileOptions +import chisel3.core.ExplicitCompileOptions import chisel3.testers.BasicTester +import chisel3.core.CompileOptions class CompileOptionsSpec extends ChiselFlatSpec { - abstract class StrictModule extends Module()(chisel3.ExplicitCompileOptions.Strict) - abstract class NotStrictModule extends Module()(chisel3.ExplicitCompileOptions.NotStrict) + abstract class StrictModule extends Module()(chisel3.core.ExplicitCompileOptions.Strict) + abstract class NotStrictModule extends Module()(chisel3.core.ExplicitCompileOptions.NotStrict) // Generate a set of options that do not have requireIOWrap enabled, in order to // ensure its definition comes from the implicit options passed to the Module constructor. - object StrictWithoutIOWrap extends ExplicitImplicitCompileOptions { + object StrictWithoutIOWrap extends CompileOptions { val connectFieldsMustMatch = true val declaredTypeMustBeUnbound = true val requireIOWrap = false @@ -35,7 +36,7 @@ class CompileOptionsSpec extends ChiselFlatSpec { "A Module with missing bundle fields when compiled with implicit Strict.CompileOption " should "throw an exception" in { a [ChiselException] should be thrownBy { - import chisel3.ExplicitCompileOptions.Strict + import chisel3.core.ExplicitCompileOptions.Strict class ConnectFieldMismatchModule extends Module { val io = IO(new Bundle { @@ -49,7 +50,7 @@ class CompileOptionsSpec extends ChiselFlatSpec { } "A Module with missing bundle fields when compiled with implicit NotStrict.CompileOption " should "not throw an exception" in { - import chisel3.ExplicitCompileOptions.NotStrict + import chisel3.core.ExplicitCompileOptions.NotStrict class ConnectFieldMismatchModule extends Module { val io = IO(new Bundle { @@ -63,7 +64,7 @@ class CompileOptionsSpec extends ChiselFlatSpec { "A Module in which a Reg is created with a bound type when compiled with implicit Strict.CompileOption " should "throw an exception" in { a [BindingException] should be thrownBy { - import chisel3.ExplicitCompileOptions.Strict + import chisel3.core.ExplicitCompileOptions.Strict class CreateRegFromBoundTypeModule extends Module { val io = IO(new Bundle { @@ -77,7 +78,7 @@ class CompileOptionsSpec extends ChiselFlatSpec { } "A Module in which a Reg is created with a bound type when compiled with implicit NotStrict.CompileOption " should "not throw an exception" in { - import chisel3.ExplicitCompileOptions.NotStrict + import chisel3.core.ExplicitCompileOptions.NotStrict class CreateRegFromBoundTypeModule extends Module { val io = IO(new Bundle { @@ -90,7 +91,7 @@ class CompileOptionsSpec extends ChiselFlatSpec { } "A Module with wrapped IO when compiled with implicit Strict.CompileOption " should "not throw an exception" in { - import chisel3.ExplicitCompileOptions.Strict + import chisel3.core.ExplicitCompileOptions.Strict class RequireIOWrapModule extends Module { val io = IO(new Bundle { @@ -103,7 +104,7 @@ class CompileOptionsSpec extends ChiselFlatSpec { } "A Module with unwrapped IO when compiled with implicit NotStrict.CompileOption " should "not throw an exception" in { - import chisel3.ExplicitCompileOptions.NotStrict + import chisel3.core.ExplicitCompileOptions.NotStrict class RequireIOWrapModule extends Module { val io = new Bundle { @@ -117,7 +118,7 @@ class CompileOptionsSpec extends ChiselFlatSpec { "A Module with unwrapped IO when compiled with implicit Strict.CompileOption " should "throw an exception" in { a [BindingException] should be thrownBy { - import chisel3.ExplicitCompileOptions.Strict + import chisel3.core.ExplicitCompileOptions.Strict class RequireIOWrapModule extends Module { val io = new Bundle { @@ -134,7 +135,7 @@ class CompileOptionsSpec extends ChiselFlatSpec { "A Module connecting output as source to input as sink when compiled with implicit Strict.CompileOption " should "throw an exception" in { a [ChiselException] should be thrownBy { - import chisel3.ExplicitCompileOptions.Strict + import chisel3.core.ExplicitCompileOptions.Strict class SimpleModule extends Module { val io = IO(new Bundle { @@ -151,7 +152,7 @@ class CompileOptionsSpec extends ChiselFlatSpec { } "A Module connecting output as source to input as sink when compiled with implicit NotStrict.CompileOption " should "not throw an exception" in { - import chisel3.ExplicitCompileOptions.NotStrict + import chisel3.core.ExplicitCompileOptions.NotStrict class SimpleModule extends Module { val io = IO(new Bundle { @@ -170,7 +171,7 @@ class CompileOptionsSpec extends ChiselFlatSpec { a [ChiselException] should be thrownBy { // Verify we can suppress the inclusion of default compileOptions import Chisel.{defaultCompileOptions => _, _} - import chisel3.ExplicitCompileOptions.Strict + import chisel3.core.ExplicitCompileOptions.Strict class SimpleModule extends Module { val io = IO(new Bundle { @@ -191,7 +192,7 @@ class CompileOptionsSpec extends ChiselFlatSpec { } "A Module with directionless connections when compiled with implicit NotStrict.CompileOption " should "not throw an exception" in { - import chisel3.ExplicitCompileOptions.NotStrict + import chisel3.core.ExplicitCompileOptions.NotStrict class SimpleModule extends Module { val io = IO(new Bundle { @@ -258,7 +259,7 @@ class CompileOptionsSpec extends ChiselFlatSpec { object StrictNotIOWrap { - implicit object CompileOptions extends ExplicitImplicitCompileOptions { + implicit object CompileOptions extends CompileOptions { val connectFieldsMustMatch = true val declaredTypeMustBeUnbound = true val requireIOWrap = false diff --git a/src/test/scala/chiselTests/SIntOps.scala b/src/test/scala/chiselTests/SIntOps.scala index 418318fb..392c4803 100644 --- a/src/test/scala/chiselTests/SIntOps.scala +++ b/src/test/scala/chiselTests/SIntOps.scala @@ -4,7 +4,6 @@ package chiselTests import chisel3._ import chisel3.testers.BasicTester -//import chisel3.ExplicitCompileOptions.NotStrict class SIntOps extends Module { val io = IO(new Bundle { diff --git a/src/test/scala/chiselTests/Stack.scala b/src/test/scala/chiselTests/Stack.scala index 937f1978..a72af928 100644 --- a/src/test/scala/chiselTests/Stack.scala +++ b/src/test/scala/chiselTests/Stack.scala @@ -6,7 +6,6 @@ import scala.collection.mutable.Stack import chisel3._ import chisel3.util._ -//import chisel3.ExplicitCompileOptions.NotStrict class ChiselStack(val depth: Int) extends Module { val io = IO(new Bundle { diff --git a/src/test/scala/chiselTests/Tbl.scala b/src/test/scala/chiselTests/Tbl.scala index 5ff1aa31..66a06435 100644 --- a/src/test/scala/chiselTests/Tbl.scala +++ b/src/test/scala/chiselTests/Tbl.scala @@ -8,7 +8,6 @@ import org.scalatest.prop._ import chisel3._ import chisel3.testers.BasicTester import chisel3.util._ -//import chisel3.ExplicitCompileOptions.NotStrict class Tbl(w: Int, n: Int) extends Module { val io = IO(new Bundle { diff --git a/src/test/scala/chiselTests/TesterDriverSpec.scala b/src/test/scala/chiselTests/TesterDriverSpec.scala index a5351763..b2e811d9 100644 --- a/src/test/scala/chiselTests/TesterDriverSpec.scala +++ b/src/test/scala/chiselTests/TesterDriverSpec.scala @@ -5,7 +5,7 @@ package chiselTests import chisel3._ import chisel3.testers.BasicTester import chisel3.util._ -//import chisel3.ExplicitCompileOptions.Strict +//import chisel3.core.ExplicitCompileOptions.Strict /** 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 d80d6f17..ad5aecd8 100644 --- a/src/test/scala/chiselTests/UIntOps.scala +++ b/src/test/scala/chiselTests/UIntOps.scala @@ -5,7 +5,6 @@ package chiselTests import chisel3._ import org.scalatest._ import chisel3.testers.BasicTester -//import chisel3.ExplicitCompileOptions.NotStrict class UIntOps extends Module { val io = IO(new Bundle { diff --git a/src/test/scala/chiselTests/Vec.scala b/src/test/scala/chiselTests/Vec.scala index a7dd975f..c5447610 100644 --- a/src/test/scala/chiselTests/Vec.scala +++ b/src/test/scala/chiselTests/Vec.scala @@ -8,7 +8,7 @@ import org.scalatest.prop._ import chisel3._ import chisel3.testers.BasicTester import chisel3.util._ -//import chisel3.ExplicitCompileOptions.Strict +//import chisel3.core.ExplicitCompileOptions.Strict 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 221fd6d8..b8e3a154 100644 --- a/src/test/scala/chiselTests/VectorPacketIO.scala +++ b/src/test/scala/chiselTests/VectorPacketIO.scala @@ -5,7 +5,6 @@ package chiselTests import chisel3._ import chisel3.testers.BasicTester import chisel3.util._ -//import chisel3.ExplicitCompileOptions.NotStrict /** * 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 5f65659b..00b1e7de 100644 --- a/src/test/scala/chiselTests/VendingMachine.scala +++ b/src/test/scala/chiselTests/VendingMachine.scala @@ -4,7 +4,6 @@ package chiselTests import chisel3._ import chisel3.util._ -//import chisel3.ExplicitCompileOptions.NotStrict class VendingMachine extends Module { val io = IO(new Bundle { diff --git a/src/test/scala/chiselTests/When.scala b/src/test/scala/chiselTests/When.scala index 0183c29b..6dc2dbac 100644 --- a/src/test/scala/chiselTests/When.scala +++ b/src/test/scala/chiselTests/When.scala @@ -7,7 +7,7 @@ import org.scalatest._ import chisel3._ import chisel3.testers.BasicTester import chisel3.util._ -//import chisel3.ExplicitCompileOptions.Strict +//import chisel3.core.ExplicitCompileOptions.Strict class WhenTester() extends BasicTester { val cnt = Counter(4) -- cgit v1.2.3 From 398edafd809c3abda751432c51a07b6b1158ecbd Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Thu, 29 Sep 2016 15:43:34 -0700 Subject: Manual dead code elimination. --- chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala | 1 - chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala | 1 - chiselFrontend/src/main/scala/chisel3/core/Data.scala | 1 - chiselFrontend/src/main/scala/chisel3/core/Module.scala | 1 - chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala | 1 - chiselFrontend/src/main/scala/chisel3/core/Reg.scala | 1 - 6 files changed, 6 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala index a28c4bec..5cec54c2 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala @@ -10,7 +10,6 @@ import chisel3.internal._ import chisel3.internal.Builder.pushCommand import chisel3.internal.firrtl._ import chisel3.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, VecTransform, SourceInfoTransform} -//import chisel3.CompileOptions /** An abstract class for data types that solely consist of (are an aggregate * of) other Data objects. diff --git a/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala b/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala index 16bde731..efecf343 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala @@ -6,7 +6,6 @@ import chisel3.internal.Builder.pushCommand import chisel3.internal.firrtl.Connect import scala.language.experimental.macros import chisel3.internal.sourceinfo._ -//import chisel3.CompileOptions /** * BiConnect.connect executes a bidirectional connection element-wise. diff --git a/chiselFrontend/src/main/scala/chisel3/core/Data.scala b/chiselFrontend/src/main/scala/chisel3/core/Data.scala index 83619fc8..3f21a34c 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Data.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Data.scala @@ -9,7 +9,6 @@ import chisel3.internal.Builder.{pushCommand, pushOp} import chisel3.internal.firrtl._ import chisel3.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, UnlocatableSourceInfo, WireTransform, SourceInfoTransform} import chisel3.internal.firrtl.PrimOp.AsUIntOp -//import chisel3.CompileOptions sealed abstract class Direction(name: String) { override def toString: String = name diff --git a/chiselFrontend/src/main/scala/chisel3/core/Module.scala b/chiselFrontend/src/main/scala/chisel3/core/Module.scala index 55ef7491..6fb6d036 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Module.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Module.scala @@ -9,7 +9,6 @@ import chisel3.internal.Builder._ import chisel3.internal.firrtl._ import chisel3.internal.firrtl.{Command => _, _} import chisel3.internal.sourceinfo.{InstTransform, SourceInfo, UnlocatableSourceInfo} -//import chisel3.CompileOptions object Module { /** A wrapper method that all Module instantiations must be wrapped in diff --git a/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala b/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala index 48efda4d..ef48709b 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala @@ -6,7 +6,6 @@ import chisel3.internal.Builder.pushCommand import chisel3.internal.firrtl.Connect import scala.language.experimental.macros import chisel3.internal.sourceinfo.{DeprecatedSourceInfo, SourceInfo, SourceInfoTransform, UnlocatableSourceInfo, WireTransform} -//import chisel3.CompileOptions /** * MonoConnect.connect executes a mono-directional connection element-wise. diff --git a/chiselFrontend/src/main/scala/chisel3/core/Reg.scala b/chiselFrontend/src/main/scala/chisel3/core/Reg.scala index 30c2b3cd..9d380695 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Reg.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Reg.scala @@ -6,7 +6,6 @@ import chisel3.internal._ import chisel3.internal.Builder.pushCommand import chisel3.internal.firrtl._ import chisel3.internal.sourceinfo.{SourceInfo, UnlocatableSourceInfo} -//import chisel3.CompileOptions object Reg { private[core] def makeType[T <: Data](compileOptions: CompileOptions, t: T = null, next: T = null, init: T = null): T = { -- cgit v1.2.3 From 058711230d2d9976ce35edc2587b17d2d6d58cff Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Fri, 30 Sep 2016 11:28:34 -0700 Subject: Add Data dir method to Chisel compatibility layer. --- src/main/scala/chisel3/compatibility.scala | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/scala/chisel3/compatibility.scala b/src/main/scala/chisel3/compatibility.scala index aad15f60..d13fcb06 100644 --- a/src/main/scala/chisel3/compatibility.scala +++ b/src/main/scala/chisel3/compatibility.scala @@ -12,6 +12,16 @@ package object Chisel { // scalastyle:ignore package.object.name object Flipped { def apply[T<:Data](target: T): T = chisel3.core.Flipped[T](target) } + // TODO: Possibly move the AddDirectionToData class here? + implicit class AddDirMethodToData[T<:Data](val target: T) extends AnyVal { + def dir: Direction = { + target match { + case e: Element => e.dir + case _ => chisel3.core.Direction.Unspecified + } + } + } + type ChiselException = chisel3.internal.ChiselException type Data = chisel3.core.Data -- cgit v1.2.3 From 095fd80cc1250f5ec242fde6ccc9271665f784b2 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Tue, 4 Oct 2016 11:46:13 -0700 Subject: Add CompileOptions implicits to all Module constructors - fix #310. (#311) --- .../src/main/scala/chisel3/core/Module.scala | 6 ++-- .../chiselTests/ModuleExplicitResetSpec.scala | 38 ++++++++++++++++++++++ 2 files changed, 41 insertions(+), 3 deletions(-) create mode 100644 src/test/scala/chiselTests/ModuleExplicitResetSpec.scala diff --git a/chiselFrontend/src/main/scala/chisel3/core/Module.scala b/chiselFrontend/src/main/scala/chisel3/core/Module.scala index 6fb6d036..55522b4a 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Module.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Module.scala @@ -54,9 +54,9 @@ abstract class Module( 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)) + def this(_clock: Clock)(implicit moduleCompileOptions: CompileOptions) = this(Option(_clock), None)(moduleCompileOptions) + def this(_reset: Bool)(implicit moduleCompileOptions: CompileOptions) = this(None, Option(_reset))(moduleCompileOptions) + def this(_clock: Clock, _reset: Bool)(implicit moduleCompileOptions: CompileOptions) = this(Option(_clock), Option(_reset))(moduleCompileOptions) // This function binds the iodef as a port in the hardware graph private[chisel3] def Port[T<:Data](iodef: T): iodef.type = { diff --git a/src/test/scala/chiselTests/ModuleExplicitResetSpec.scala b/src/test/scala/chiselTests/ModuleExplicitResetSpec.scala new file mode 100644 index 00000000..f8206b9c --- /dev/null +++ b/src/test/scala/chiselTests/ModuleExplicitResetSpec.scala @@ -0,0 +1,38 @@ +// See LICENSE for license details. + +package chiselTests + +class ModuleExplicitResetSpec extends ChiselFlatSpec { + + "A Module with an explicit reset in compatibility mode" should "elaborate" in { + import Chisel._ + val myReset = Bool(true) + class ModuleExplicitReset(reset: Bool) extends Module(_reset = reset) { + val io = new Bundle { + val done = Bool(OUTPUT) + } + + io.done := Bool(false) + } + + elaborate { + new ModuleExplicitReset(myReset) + } + } + + "A Module with an explicit reset in non-compatibility mode" should "elaborate" in { + import chisel3._ + val myReset = Bool(true) + class ModuleExplicitReset(reset: Bool) extends Module(_reset = reset) { + val io = IO(new Bundle { + val done = Bool(OUTPUT) + }) + + io.done := Bool(false) + } + + elaborate { + new ModuleExplicitReset(myReset) + } + } +} -- cgit v1.2.3 From c24fc9b93d440cd5604b5c83e5b79b80d9c7604c Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Tue, 4 Oct 2016 17:30:46 -0700 Subject: Suppress some scala compiler warnings @unchecked is better than matching on _ in this case, because we want to fail on an unexpected case, rather than silently proceed. --- chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala | 8 ++++---- chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala b/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala index efecf343..2599a20a 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala @@ -124,7 +124,7 @@ object BiConnect { if( (left_mod == context_mod) && (right_mod._parent.map(_ == context_mod).getOrElse(false)) ) { // Thus, right node better be a port node and thus have a direction hint - (left_direction, right_direction) match { + ((left_direction, right_direction): @unchecked) match { // CURRENT MOD CHILD MOD case (Some(Input), Some(Input)) => issueConnectL2R(left, right) case (None, Some(Input)) => issueConnectL2R(left, right) @@ -142,7 +142,7 @@ object BiConnect { else if( (right_mod == context_mod) && (left_mod._parent.map(_ == context_mod).getOrElse(false)) ) { // Thus, left node better be a port node and thus have a direction hint - (left_direction, right_direction) match { + ((left_direction, right_direction): @unchecked) match { // CHILD MOD CURRENT MOD case (Some(Input), Some(Input)) => issueConnectR2L(left, right) case (Some(Input), None) => issueConnectR2L(left, right) @@ -158,7 +158,7 @@ object BiConnect { // CASE: Context is same module that both left node and right node are in else if( (context_mod == left_mod) && (context_mod == right_mod) ) { - (left_direction, right_direction) match { + ((left_direction, right_direction): @unchecked) match { // CURRENT MOD CURRENT MOD case (Some(Input), Some(Output)) => issueConnectL2R(left, right) case (Some(Input), None) => issueConnectL2R(left, right) @@ -209,7 +209,7 @@ object BiConnect { (right_mod._parent.map(_ == context_mod).getOrElse(false)) ) { // Thus both nodes must be ports and have a direction hint - (left_direction, right_direction) match { + ((left_direction, right_direction): @unchecked) match { // CHILD MOD CHILD MOD case (Some(Input), Some(Output)) => issueConnectR2L(left, right) case (Some(Output), Some(Input)) => issueConnectL2R(left, right) diff --git a/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala b/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala index ef48709b..fcb14e6f 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala @@ -115,7 +115,7 @@ object MonoConnect { // CASE: Context is same module that both left node and right node are in if( (context_mod == sink_mod) && (context_mod == source_mod) ) { - (sink_direction, source_direction) match { + ((sink_direction, source_direction): @unchecked) match { // SINK SOURCE // CURRENT MOD CURRENT MOD case (Some(Output), _) => issueConnect(sink, source) @@ -128,7 +128,7 @@ object MonoConnect { else if( (sink_mod == context_mod) && (source_mod._parent.map(_ == context_mod).getOrElse(false)) ) { // Thus, right node better be a port node and thus have a direction - (sink_direction, source_direction) match { + ((sink_direction, source_direction): @unchecked) match { // SINK SOURCE // CURRENT MOD CHILD MOD case (None, Some(Output)) => issueConnect(sink, source) @@ -151,7 +151,7 @@ object MonoConnect { else if( (source_mod == context_mod) && (sink_mod._parent.map(_ == context_mod).getOrElse(false)) ) { // Thus, left node better be a port node and thus have a direction - (sink_direction, source_direction) match { + ((sink_direction, source_direction): @unchecked) match { // SINK SOURCE // CHILD MOD CURRENT MOD case (Some(Input), _) => issueConnect(sink, source) @@ -167,7 +167,7 @@ object MonoConnect { (source_mod._parent.map(_ == context_mod).getOrElse(false)) ) { // Thus both nodes must be ports and have a direction - (sink_direction, source_direction) match { + ((sink_direction, source_direction): @unchecked) match { // SINK SOURCE // CHILD MOD CHILD MOD case (Some(Input), Some(Input)) => issueConnect(sink, source) -- cgit v1.2.3 From b2373ebda5e63fa850de21585307013f8419320a Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Wed, 5 Oct 2016 15:18:25 -0700 Subject: Make asInput/asOutput/flip deprecation warnings dynamic Code that imports Chisel._ shouldn't see them. Not sure if requireIOWrap is the right condition... or if cyan is a good choice of color for deprecation warnings. --- .../main/scala/chisel3/core/CompileOptions.scala | 5 +++++ .../src/main/scala/chisel3/core/Data.scala | 21 +++++++++++++++------ .../src/main/scala/chisel3/internal/Builder.scala | 2 ++ .../src/main/scala/chisel3/internal/Error.scala | 8 ++++++++ src/test/scala/chiselTests/CompileOptionsTest.scala | 2 ++ 5 files changed, 32 insertions(+), 6 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/CompileOptions.scala b/chiselFrontend/src/main/scala/chisel3/core/CompileOptions.scala index 0e66a241..85aa8cdc 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/CompileOptions.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/CompileOptions.scala @@ -17,6 +17,9 @@ trait CompileOptions { val dontTryConnectionsSwapped: Boolean // If connection directionality is not explicit, do not use heuristics to attempt to determine it. val dontAssumeDirectionality: Boolean + // Issue a deprecation warning if Data.{flip, asInput,asOutput} is used + // instead of Flipped, Input, or Output. + val deprecateOldDirectionMethods: Boolean } object CompileOptions { @@ -34,6 +37,7 @@ object ExplicitCompileOptions { val requireIOWrap = false val dontTryConnectionsSwapped = false val dontAssumeDirectionality = false + val deprecateOldDirectionMethods = false } // Collection of "strict" connection compile options, preferred for new code. @@ -44,5 +48,6 @@ object ExplicitCompileOptions { val requireIOWrap = true val dontTryConnectionsSwapped = true val dontAssumeDirectionality = true + val deprecateOldDirectionMethods = true } } diff --git a/chiselFrontend/src/main/scala/chisel3/core/Data.scala b/chiselFrontend/src/main/scala/chisel3/core/Data.scala index 3f21a34c..922b33a9 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Data.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Data.scala @@ -104,12 +104,21 @@ object Data { } implicit class AddDirectionToData[T<:Data](val target: T) extends AnyVal { - @deprecated("Input(Data) should be used over Data.asInput", "gchisel") - def asInput: T = Input(target) - @deprecated("Output(Data) should be used over Data.asOutput", "gchisel") - def asOutput: T = Output(target) - @deprecated("Flipped(Data) should be used over Data.flip", "gchisel") - def flip(): T = Flipped(target) + def asInput(implicit opts: CompileOptions): T = { + if (opts.deprecateOldDirectionMethods) + Builder.deprecated("Input(Data) should be used over Data.asInput") + Input(target) + } + def asOutput(implicit opts: CompileOptions): T = { + if (opts.deprecateOldDirectionMethods) + Builder.deprecated("Output(Data) should be used over Data.asOutput") + Output(target) + } + def flip()(implicit opts: CompileOptions): T = { + if (opts.deprecateOldDirectionMethods) + Builder.deprecated("Flipped(Data) should be used over Data.flip") + Flipped(target) + } } } diff --git a/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala b/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala index 8d376810..12cc840e 100644 --- a/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala +++ b/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala @@ -173,6 +173,8 @@ private[chisel3] object Builder { def errors: ErrorLog = dynamicContext.errors def error(m: => String): Unit = errors.error(m) + def warning(m: => String): Unit = errors.warning(m) + def deprecated(m: => String): Unit = errors.deprecated(m) def build[T <: Module](f: => T): Circuit = { dynamicContextVar.withValue(Some(new DynamicContext())) { diff --git a/chiselFrontend/src/main/scala/chisel3/internal/Error.scala b/chiselFrontend/src/main/scala/chisel3/internal/Error.scala index 7ae0580f..c5c67da4 100644 --- a/chiselFrontend/src/main/scala/chisel3/internal/Error.scala +++ b/chiselFrontend/src/main/scala/chisel3/internal/Error.scala @@ -25,6 +25,10 @@ private[chisel3] class ErrorLog { def warning(m: => String): Unit = errors += new Warning(m, getUserLineNumber) + /** Log a deprecation warning message */ + def deprecated(m: => String): Unit = + errors += new DeprecationWarning(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 @@ -86,6 +90,10 @@ private class Warning(msg: => String, line: Option[StackTraceElement]) extends L def format: String = tag("warn", Console.YELLOW) } +private class DeprecationWarning(msg: => String, line: Option[StackTraceElement]) extends LogEntry(msg, line) { + def format: String = tag("warn", Console.CYAN) +} + private class Info(msg: => String, line: Option[StackTraceElement]) extends LogEntry(msg, line) { def format: String = tag("info", Console.MAGENTA) } diff --git a/src/test/scala/chiselTests/CompileOptionsTest.scala b/src/test/scala/chiselTests/CompileOptionsTest.scala index 83077544..66a9dcc0 100644 --- a/src/test/scala/chiselTests/CompileOptionsTest.scala +++ b/src/test/scala/chiselTests/CompileOptionsTest.scala @@ -22,6 +22,7 @@ class CompileOptionsSpec extends ChiselFlatSpec { val requireIOWrap = false val dontTryConnectionsSwapped = true val dontAssumeDirectionality = true + val deprecateOldDirectionMethods = true } class SmallBundle extends Bundle { @@ -265,6 +266,7 @@ class CompileOptionsSpec extends ChiselFlatSpec { val requireIOWrap = false val dontTryConnectionsSwapped = true val dontAssumeDirectionality = true + val deprecateOldDirectionMethods = false } } -- cgit v1.2.3 From a18002c879d14b6c51cd49311a3b2a99a6a204fc Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Wed, 5 Oct 2016 14:16:13 -0700 Subject: Give <> and := legacy behavior in compatibility mode --- .../src/main/scala/chisel3/core/Aggregate.scala | 2 + .../src/main/scala/chisel3/core/Bits.scala | 5 ++- .../main/scala/chisel3/core/CompileOptions.scala | 4 ++ .../src/main/scala/chisel3/core/Data.scala | 45 +++++++++++++--------- .../scala/chiselTests/CompileOptionsTest.scala | 2 + 5 files changed, 39 insertions(+), 19 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala index 5cec54c2..98455f4d 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala @@ -17,6 +17,8 @@ import chisel3.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, VecTransfo sealed abstract class Aggregate extends Data { private[core] def cloneTypeWidth(width: Width): this.type = cloneType private[core] def width: Width = flatten.map(_.width).reduce(_ + _) + private[core] def legacyConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit = + pushCommand(BulkConnect(sourceInfo, this.lref, that.lref)) } object Vec { diff --git a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala index 24abbdba..741f6aee 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala @@ -5,7 +5,7 @@ package chisel3.core import scala.language.experimental.macros import chisel3.internal._ -import chisel3.internal.Builder.pushOp +import chisel3.internal.Builder.{pushCommand, pushOp} import chisel3.internal.firrtl._ import chisel3.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, SourceInfoTransform, SourceInfoWhiteboxTransform, UIntTransform, MuxTransform} @@ -40,6 +40,9 @@ abstract class Element(private[core] val width: Width) extends Data { private[chisel3] final def allElements: Seq[Element] = Seq(this) def widthKnown: Boolean = width.known def name: String = getRef.name + + private[core] def legacyConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit = + pushCommand(Connect(sourceInfo, this.lref, that.ref)) } /** A data type for values represented by a single bitvector. Provides basic diff --git a/chiselFrontend/src/main/scala/chisel3/core/CompileOptions.scala b/chiselFrontend/src/main/scala/chisel3/core/CompileOptions.scala index 85aa8cdc..4dea39b5 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/CompileOptions.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/CompileOptions.scala @@ -20,6 +20,8 @@ trait CompileOptions { // Issue a deprecation warning if Data.{flip, asInput,asOutput} is used // instead of Flipped, Input, or Output. val deprecateOldDirectionMethods: Boolean + // Check that referenced Data have actually been declared. + val checkSynthesizable: Boolean } object CompileOptions { @@ -38,6 +40,7 @@ object ExplicitCompileOptions { val dontTryConnectionsSwapped = false val dontAssumeDirectionality = false val deprecateOldDirectionMethods = false + val checkSynthesizable = false } // Collection of "strict" connection compile options, preferred for new code. @@ -49,5 +52,6 @@ object ExplicitCompileOptions { val dontTryConnectionsSwapped = true val dontAssumeDirectionality = true val deprecateOldDirectionMethods = true + val checkSynthesizable = true } } diff --git a/chiselFrontend/src/main/scala/chisel3/core/Data.scala b/chiselFrontend/src/main/scala/chisel3/core/Data.scala index 922b33a9..4167be98 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Data.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Data.scala @@ -135,27 +135,35 @@ abstract class Data extends HasId { private[core] def badConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit = throwException(s"cannot connect ${this} and ${that}") private[chisel3] def connect(that: Data)(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions): Unit = { - Binding.checkSynthesizable(this, s"'this' ($this)") - Binding.checkSynthesizable(that, s"'that' ($that)") - try { - MonoConnect.connect(sourceInfo, connectCompileOptions, this, that, Builder.forcedModule) - } catch { - case MonoConnect.MonoConnectException(message) => - throwException( - s"Connection between sink ($this) and source ($that) failed @$message" - ) + if (connectCompileOptions.checkSynthesizable) { + Binding.checkSynthesizable(this, s"'this' ($this)") + Binding.checkSynthesizable(that, s"'that' ($that)") + try { + MonoConnect.connect(sourceInfo, connectCompileOptions, this, that, Builder.forcedModule) + } catch { + case MonoConnect.MonoConnectException(message) => + throwException( + s"Connection between sink ($this) and source ($that) failed @$message" + ) + } + } else { + this legacyConnect that } } private[chisel3] def bulkConnect(that: Data)(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions): Unit = { - Binding.checkSynthesizable(this, s"'this' ($this)") - Binding.checkSynthesizable(that, s"'that' ($that)") - try { - BiConnect.connect(sourceInfo, connectCompileOptions, this, that, Builder.forcedModule) - } catch { - case BiConnect.BiConnectException(message) => - throwException( - s"Connection between left ($this) and source ($that) failed @$message" - ) + if (connectCompileOptions.checkSynthesizable) { + Binding.checkSynthesizable(this, s"'this' ($this)") + Binding.checkSynthesizable(that, s"'that' ($that)") + try { + BiConnect.connect(sourceInfo, connectCompileOptions, this, that, Builder.forcedModule) + } catch { + case BiConnect.BiConnectException(message) => + throwException( + s"Connection between left ($this) and source ($that) failed @$message" + ) + } + } else { + this legacyConnect that } } private[chisel3] def lref: Node = Node(this) @@ -163,6 +171,7 @@ abstract class Data extends HasId { private[core] def cloneTypeWidth(width: Width): this.type private[chisel3] def toType: String private[core] def width: Width + private[core] def legacyConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit def cloneType: this.type def chiselCloneType: this.type = { diff --git a/src/test/scala/chiselTests/CompileOptionsTest.scala b/src/test/scala/chiselTests/CompileOptionsTest.scala index 66a9dcc0..57ceff3f 100644 --- a/src/test/scala/chiselTests/CompileOptionsTest.scala +++ b/src/test/scala/chiselTests/CompileOptionsTest.scala @@ -23,6 +23,7 @@ class CompileOptionsSpec extends ChiselFlatSpec { val dontTryConnectionsSwapped = true val dontAssumeDirectionality = true val deprecateOldDirectionMethods = true + val checkSynthesizable = true } class SmallBundle extends Bundle { @@ -267,6 +268,7 @@ class CompileOptionsSpec extends ChiselFlatSpec { val dontTryConnectionsSwapped = true val dontAssumeDirectionality = true val deprecateOldDirectionMethods = false + val checkSynthesizable = true } } -- cgit v1.2.3 From 7981c6d9e6d25fb27b25e1427794775c9f934a09 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Wed, 5 Oct 2016 15:32:23 -0700 Subject: Use modulo addressing for dynamic Vec/Mem accesses Static accesses are strictly checked. --- chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala | 14 ++++++++++++-- chiselFrontend/src/main/scala/chisel3/core/Mem.scala | 8 ++++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala index 5cec54c2..7b759493 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala @@ -9,7 +9,7 @@ import scala.language.experimental.macros import chisel3.internal._ import chisel3.internal.Builder.pushCommand import chisel3.internal.firrtl._ -import chisel3.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, VecTransform, SourceInfoTransform} +import chisel3.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, VecTransform, SourceInfoTransform, UnlocatableSourceInfo} /** An abstract class for data types that solely consist of (are an aggregate * of) other Data objects. @@ -113,6 +113,15 @@ object Vec { def do_fill[T <: Data](n: Int)(gen: => T)(implicit sourceInfo: SourceInfo): Vec[T] = apply(Seq.fill(n)(gen)) + + /** Truncate an index to implement modulo-power-of-2 addressing. */ + private[core] def truncateIndex(idx: UInt, n: Int)(implicit sourceInfo: SourceInfo): UInt = { + val w = BigInt(n-1).bitLength + if (n <= 1) UInt(0) + else if (idx.width.known && idx.width.get <= w) idx + else if (idx.width.known) idx(w-1,0) + else Wire(UInt(width = w), init = idx) + } } /** A vector (array) of [[Data]] elements. Provides hardware versions of various @@ -178,7 +187,8 @@ sealed class Vec[T <: Data] private (gen: T, val length: Int) def apply(idx: UInt): T = { Binding.checkSynthesizable(idx ,s"'idx' ($idx)") val port = sample_element.chiselCloneType - port.setRef(this, idx) //TODO(twigg): This is a bit too magical + val i = Vec.truncateIndex(idx, length)(UnlocatableSourceInfo) + port.setRef(this, i) // Bind each element of port to being whatever the base type is // Using the head element as the sample_element diff --git a/chiselFrontend/src/main/scala/chisel3/core/Mem.scala b/chiselFrontend/src/main/scala/chisel3/core/Mem.scala index b24d463a..9cd5a4d8 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Mem.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Mem.scala @@ -38,7 +38,10 @@ sealed abstract class MemBase[T <: Data](t: T, val length: Int) extends HasId wi /** 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)) + def apply(idx: Int): T = { + require(idx >= 0 && idx < length) + 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. @@ -85,10 +88,11 @@ sealed abstract class MemBase[T <: Data](t: T, val length: Int) extends HasId wi private def makePort(sourceInfo: SourceInfo, idx: UInt, dir: MemPortDirection): T = { Binding.checkSynthesizable(idx, s"'idx' ($idx)") + val i = Vec.truncateIndex(idx, length)(sourceInfo) val port = pushCommand( DefMemPort(sourceInfo, - t.chiselCloneType, Node(this), dir, idx.ref, Node(idx._parent.get.clock)) + t.chiselCloneType, Node(this), dir, i.ref, Node(i._parent.get.clock)) ).id // Bind each element of port to being a MemoryPort Binding.bind(port, MemoryPortBinder(Builder.forcedModule), "Error: Fresh t") -- cgit v1.2.3 From 36f42c8dff2413f76d9672e92c4457e3a724f4bd Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Wed, 5 Oct 2016 17:02:53 -0700 Subject: Update @sdtwigg's PR #199 - Add Assert Data. --- chiselFrontend/src/main/scala/chisel3/core/Assert.scala | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/chiselFrontend/src/main/scala/chisel3/core/Assert.scala b/chiselFrontend/src/main/scala/chisel3/core/Assert.scala index db62f4a8..4782a845 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Assert.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Assert.scala @@ -24,21 +24,22 @@ object assert { // scalastyle:ignore object.name * * @param cond condition, assertion fires (simulation fails) when false * @param message optional message to print when the assertion fires + * @param data optional bits to print in the message formatting * * @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, message: String, data: Bits*)(implicit sourceInfo: SourceInfo): Unit = macro apply_impl_msg_data 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 = { + def apply_impl_msg_data(c: Context)(cond: c.Tree, message: c.Tree, data: 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)" + q"$apply_impl_do($cond, $condStr, _root_.scala.Some($message), ..$data)($sourceInfo)" } def apply_impl(c: Context)(cond: c.Tree)(sourceInfo: c.Tree): c.Tree = { @@ -49,11 +50,11 @@ object assert { // scalastyle:ignore object.name q"$apply_impl_do($cond, $condStr, _root_.scala.None)($sourceInfo)" } - def apply_impl_do(cond: Bool, line: String, message: Option[String])(implicit sourceInfo: SourceInfo) { + def apply_impl_do(cond: Bool, line: String, message: Option[String], data: Bits*)(implicit sourceInfo: SourceInfo) { when (!(cond || Builder.forcedModule.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") + case Some(str) => printf.printfWithoutReset(s"Assertion failed: $str\n at $line\n", data:_*) + case None => printf.printfWithoutReset(s"Assertion failed\n at $line\n", data:_*) } pushCommand(Stop(sourceInfo, Node(Builder.forcedModule.clock), 1)) } -- cgit v1.2.3 From bae8e4a4d2d0ffe52fe209ccc7dc19418eee8cab Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Wed, 5 Oct 2016 17:07:45 -0700 Subject: TransitName comment change. This was originally mixed in with #199, Add Assert Data. --- src/main/scala/chisel3/util/TransitName.scala | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/main/scala/chisel3/util/TransitName.scala b/src/main/scala/chisel3/util/TransitName.scala index ce6cb60f..a3220a13 100644 --- a/src/main/scala/chisel3/util/TransitName.scala +++ b/src/main/scala/chisel3/util/TransitName.scala @@ -5,14 +5,16 @@ package chisel3.util import chisel3._ import internal.HasId +/** + * The purpose of TransitName 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 + */ 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 -- cgit v1.2.3