summaryrefslogtreecommitdiff
path: root/chiselFrontend/src/main/scala/chisel3/core
diff options
context:
space:
mode:
authorJim Lawson2019-05-20 10:07:33 -0700
committerGitHub2019-05-20 10:07:33 -0700
commit387274784115bee2bf7167547a7ee459219e1413 (patch)
tree037b0fde46d4bd216067063fc3af2ce470fe9a2b /chiselFrontend/src/main/scala/chisel3/core
parent89ef4d78e8f44f31df6530a6a4dee20d0ad0399f (diff)
Repackagecore rebase (#1078)
* Move Bits, Data, and BitPat to chiselFrontend/src/main/scala/chisel3 and deal with the subsequent fallout. * Move Aggregate, Clock, Mem, Printf, Reg * Move almost all chisel3.core definitions to chisel3 or chisel3.experimental * Revive core package object to provide aliases for moved definitions. * Cleanup package definitions; eliminate ambiguous implicits * Move more definitions to experimental. Extract BaseModule, DataMirror, ExtModule, IO into their own files. * Put BitPat back in chisel3.util * More experimental motion - avoid multiple import definitions. * Add experimental.FixedPoint alias * Add EnumType definition to core package. Update deprecated messages to refer to correct object * Move FixedPoint into the experimental package (but keep it in Bits.scala). * Add missing implicits to core/package - compatibility * Cleanup: update ScalaDoc references; remove unused imports * Add Reset alias to core/package * Use common 3.2 version in deprecation warning * Move Binding from core to internal. * Optimize imports. * Repair IntelliJ's overly cleanliness. * Move Bits, Data, and BitPat to chiselFrontend/src/main/scala/chisel3 and deal with the subsequent fallout. Move Aggregate, Clock, Mem, Printf, Reg Move almost all chisel3.core definitions to chisel3 or chisel3.experimental Revive core package object to provide aliases for moved definitions. Cleanup package definitions; eliminate ambiguous implicits Move more definitions to experimental. Extract BaseModule, DataMirror, ExtModule, IO into their own files. Add EnumType definition to core package. Update deprecated messages to refer to correct object Move FixedPoint into the experimental package (but keep it in Bits.scala). Add missing implicits to core/package - compatibility Cleanup: update ScalaDoc references; remove unused imports Use common 3.2 version in deprecation warning Move Binding from core to internal. * Change == to reference equality (eq) in Data print (#1044) * Remove @chiselName from MixedVec (#1045) * Fix enum annotations (#936) * Turned off strong enum annotations because they weren't working with Vec indexes * Add new EnumVecAnnotation for vecs of enums and vecs of bundles with enum fields * Changed Clock's width parameter back to a fixed constant value of 1 * Fixed enum annotations for Vecs of Bundles which contain enum elements * Fixed usage of "when/otherwise" to use consistent style * Add Record to type hierarchy documentation * Undeprecate isLit (#1048) * move doNotDedup to experimental (#1008) * Aggregate coverage - aggregate tests but not publishing (#1040) Discover a working combination of aggregate usage to enable coverage of subproject testing but publish a single Jar. Use "scalastyle-test-config.xml" for scalastyle config in tests. Enable "_" in method names and accept method names ending in "_=". Re-sync scalastyle-test-config.xml with scalastyle-config.xml This should finally fix #772. * Check field referential equality in autoclonetype (#1047) * Allow naming annotation to work outside builder context (#1051) * Try to eliminate JVM hang due to static initialization deadlock (#1053) * Make core.DontCare private to chisel3 (#1054) Force clients to access 'DontCare' through the chisel3 package to ensure it's created as a chisel3 object and not a client object. * Ignore empty aggregates elements when binding aggregate direction (#946) Previously, including an empty aggregate in a Bundle would cause a MixedDirectionAggregateException because it has no elements and thus doesn't have a direction * Add SampleElementBinding for Vec sample elements * Add ActualDirection.Empty for bound empty aggregates * Detect bundle aliasing (#1050) * Implement connectFromBits in ChiselEnum (#1052) This is necessary to use ChiselEnum in aggregates where things are casted using .asTypeOf * Optimize imports. * Move Analog to experimental. * More repackage cleanup - reduce differences with master. * Cleanup chisel3 references. * More chisel3 reference cleanup. * Merge cleanup. * Remove unused import * Bump core deprecation to 3.3 * Move DontCare back into Data.scala inside package internal * Re-indent experimental/internal package code * Move code back to original files - facilitate comparison with other branches * Some code motion, update imports, minimize master differences Move exceptions up to chisel3 package object - they're part of the interface. * More master diff minimization. * Try to eliminate JVM hang due to static initialization deadlock (#1053) * Ignore empty aggregates elements when binding aggregate direction (#946) Previously, including an empty aggregate in a Bundle would cause a MixedDirectionAggregateException because it has no elements and thus doesn't have a direction * Add SampleElementBinding for Vec sample elements * Add ActualDirection.Empty for bound empty aggregates * Implement connectFromBits in ChiselEnum (#1052) This is necessary to use ChiselEnum in aggregates where things are casted using .asTypeOf * Move Analog to experimental. More repackage cleanup - reduce differences with master. Cleanup chisel3 references. More chisel3 reference cleanup. * Fix wrong directionality for Vec(Flipped()) Create Chisel IR Port() in a way that Converter is happy with. Also add more extensive test suite for future-proofing. Close #1063 * Move Bits, Data, and BitPat to chiselFrontend/src/main/scala/chisel3 and deal with the subsequent fallout. Move Aggregate, Clock, Mem, Printf, Reg Move almost all chisel3.core definitions to chisel3 or chisel3.experimental Revive core package object to provide aliases for moved definitions. Cleanup package definitions; eliminate ambiguous implicits Move more definitions to experimental. Extract BaseModule, DataMirror, ExtModule, IO into their own files. Put BitPat back in chisel3.util More experimental motion - avoid multiple import definitions. Add experimental.FixedPoint alias Add EnumType definition to core package. Update deprecated messages to refer to correct object Move FixedPoint into the experimental package (but keep it in Bits.scala). Add missing implicits to core/package - compatibility Cleanup: update ScalaDoc references; remove unused imports Add Reset alias to core/package Use common 3.2 version in deprecation warning Move Binding from core to internal. Optimize imports. Repair IntelliJ's overly cleanliness. Move Bits, Data, and BitPat to chiselFrontend/src/main/scala/chisel3 and deal with the subsequent fallout. Move Aggregate, Clock, Mem, Printf, Reg Move almost all chisel3.core definitions to chisel3 or chisel3.experimental Revive core package object to provide aliases for moved definitions. Cleanup package definitions; eliminate ambiguous implicits Move more definitions to experimental. Extract BaseModule, DataMirror, ExtModule, IO into their own files. Add EnumType definition to core package. Update deprecated messages to refer to correct object Move FixedPoint into the experimental package (but keep it in Bits.scala). Add missing implicits to core/package - compatibility Cleanup: update ScalaDoc references; remove unused imports Use common 3.2 version in deprecation warning Move Binding from core to internal. Optimize imports. Merge cleanup. Remove unused import Bump core deprecation to 3.3 Move DontCare back into Data.scala inside package internal Re-indent experimental/internal package code Move code back to original files - facilitate comparison with other branches Some code motion, update imports, minimize master differences Move exceptions up to chisel3 package object - they're part of the interface. More master diff minimization. Fix minor discrepancies with repackagecore-testbed * Remove redundant imports As part of its import updating process, IntelliJ converted some import statements to `import package.{object, _}`. Is this intended to show an explicit dependency on `package.object` and a further dependency on `package` implicits? Unsure. Replace these with `import package._` * Move the BaseModule object into the internal package.
Diffstat (limited to 'chiselFrontend/src/main/scala/chisel3/core')
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala974
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Annotation.scala138
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Assert.scala92
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Attach.scala45
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala332
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Binding.scala122
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Bits.scala1808
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/BlackBox.scala172
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Clock.scala38
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/CompileOptions.scala76
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Data.scala742
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Mem.scala216
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Module.scala355
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala246
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/MultiClock.scala70
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Mux.scala51
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Printable.scala179
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Printf.scala100
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/RawModule.scala255
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Reg.scala175
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala127
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/StrongEnum.scala344
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/When.scala85
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/package.scala420
24 files changed, 290 insertions, 6872 deletions
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala
deleted file mode 100644
index 7e3920eb..00000000
--- a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala
+++ /dev/null
@@ -1,974 +0,0 @@
-// See LICENSE for license details.
-
-package chisel3.core
-
-import scala.collection.immutable.ListMap
-import scala.collection.mutable.{ArrayBuffer, HashSet, LinkedHashMap}
-import scala.language.experimental.macros
-
-import chisel3.internal._
-import chisel3.internal.Builder.pushCommand
-import chisel3.internal.firrtl._
-import chisel3.internal.sourceinfo._
-import chisel3.SourceInfoDoc
-
-class AliasedAggregateFieldException(message: String) extends ChiselException(message)
-
-/** An abstract class for data types that solely consist of (are an aggregate
- * of) other Data objects.
- */
-sealed abstract class Aggregate extends Data {
- private[chisel3] override def bind(target: Binding, parentDirection: SpecifiedDirection) {
- binding = target
-
- val resolvedDirection = SpecifiedDirection.fromParent(parentDirection, specifiedDirection)
- val duplicates = getElements.groupBy(identity).collect { case (x, elts) if elts.size > 1 => x }
- if (!duplicates.isEmpty) {
- throw new AliasedAggregateFieldException(s"Aggregate $this contains aliased fields $duplicates")
- }
- for (child <- getElements) {
- child.bind(ChildBinding(this), resolvedDirection)
- }
-
- // Check that children obey the directionality rules.
- val childDirections = getElements.map(_.direction).toSet - ActualDirection.Empty
- direction = ActualDirection.fromChildren(childDirections, resolvedDirection) match {
- case Some(dir) => dir
- case None =>
- val childWithDirections = getElements zip getElements.map(_.direction)
- throw Binding.MixedDirectionAggregateException(
- s"Aggregate '$this' can't have elements that are both directioned and undirectioned: $childWithDirections")
- }
- }
-
- override def litOption: Option[BigInt] = ??? // TODO implement me
-
- /** Returns a Seq of the immediate contents of this Aggregate, in order.
- */
- def getElements: Seq[Data]
-
- private[chisel3] def width: Width = getElements.map(_.width).foldLeft(0.W)(_ + _)
- private[core] def legacyConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit = {
- // If the source is a DontCare, generate a DefInvalid for the sink,
- // otherwise, issue a Connect.
- if (that == DontCare) {
- pushCommand(DefInvalid(sourceInfo, Node(this)))
- } else {
- pushCommand(BulkConnect(sourceInfo, Node(this), Node(that)))
- }
- }
-
- override def do_asUInt(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = {
- SeqUtils.do_asUInt(flatten.map(_.asUInt()))
- }
- private[core] override def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo,
- compileOptions: CompileOptions): Unit = {
- var i = 0
- val bits = WireDefault(UInt(this.width), that) // handles width padding
- for (x <- flatten) {
- val fieldWidth = x.getWidth
- if (fieldWidth > 0) {
- x.connectFromBits(bits(i + fieldWidth - 1, i))
- i += fieldWidth
- } else {
- // There's a zero-width field in this bundle.
- // Zero-width fields can't really be assigned to, but the frontend complains if there are uninitialized fields,
- // so we assign it to DontCare. We can't use connectFromBits() on DontCare, so use := instead.
- x := DontCare
- }
- }
- }
-}
-
-trait VecFactory extends SourceInfoDoc {
- /** 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)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Vec[T] = {
- if (compileOptions.declaredTypeMustBeUnbound) {
- requireIsChiselType(gen, "vec type")
- }
- new Vec(gen.cloneTypeFull, n)
- }
-
- /** Truncate an index to implement modulo-power-of-2 addressing. */
- private[core] def truncateIndex(idx: UInt, n: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = { // scalastyle:ignore line.size.limit
- // scalastyle:off if.brace
- val w = (n-1).bitLength
- if (n <= 1) 0.U
- else if (idx.width.known && idx.width.get <= w) idx
- else if (idx.width.known) idx(w-1,0)
- else (idx | 0.U(w.W))(w-1,0)
- // scalastyle:on if.brace
- }
-}
-
-object Vec extends VecFactory
-// scalastyle:off line.size.limit
-/** A vector (array) of [[Data]] elements. Provides hardware versions of various
- * collection transformation functions found in software array implementations.
- *
- * Careful consideration should be given over the use of [[Vec]] vs
- * [[scala.collection.immutable.Seq Seq]] or some other Scala collection. In general [[Vec]] only
- * needs to be used when there is a need to express the hardware collection in a [[Reg]] or IO
- * [[Bundle]] or when access to elements of the array is indexed via a hardware signal.
- *
- * Example of indexing into a [[Vec]] using a hardware address and where the [[Vec]] is defined in
- * an IO [[Bundle]]
- *
- * {{{
- * val io = IO(new Bundle {
- * val in = Input(Vec(20, UInt(16.W)))
- * val addr = UInt(5.W)
- * val out = Output(UInt(16.W))
- * })
- * io.out := io.in(io.addr)
- * }}}
- *
- * @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)
- * - Vecs, unlike classes in Scala's collection library, are propagated intact to FIRRTL as a vector type, which may make debugging easier
- */
-// scalastyle:on line.size.limit
-sealed class Vec[T <: Data] private[core] (gen: => T, val length: Int)
- extends Aggregate with VecLike[T] {
- override def toString: String = {
- val elementType = sample_element.cloneType
- s"$elementType[$length]$bindingToString"
- }
-
- private[core] override def typeEquivalent(that: Data): Boolean = that match {
- case that: Vec[T] =>
- this.length == that.length &&
- (this.sample_element typeEquivalent that.sample_element)
- case _ => false
- }
-
- private[chisel3] override def bind(target: Binding, parentDirection: SpecifiedDirection) {
- binding = target
-
- val resolvedDirection = SpecifiedDirection.fromParent(parentDirection, specifiedDirection)
- sample_element.bind(SampleElementBinding(this), resolvedDirection)
- for (child <- getElements) { // assume that all children are the same
- child.bind(ChildBinding(this), resolvedDirection)
- }
-
- direction = sample_element.direction
- }
-
- // 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: Seq[T] = Vector.fill(length)(gen)
- for ((elt, i) <- self.zipWithIndex)
- elt.setRef(this, i)
-
- /**
- * sample_element 'tracks' all changes to the elements.
- * 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[chisel3] 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 override 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, moduleCompileOptions: CompileOptions): Unit = {
- if (this.length != that.length) {
- Builder.error("Vec and Seq being bulk connected have different lengths!")
- }
- 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: CompileOptions): Unit = this bulkConnect that.asInstanceOf[Data] // scalastyle:ignore line.size.limit
-
- /** 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: 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: CompileOptions): Unit = this connect that
-
- /** Creates a dynamically indexed read or write accessor into the array.
- */
- override def apply(p: UInt): T = macro CompileOptionsTransform.pArg
-
- /** @group SourceInfoTransformMacro */
- def do_apply(p: UInt)(implicit compileOptions: CompileOptions): T = {
- requireIsHardware(p, "vec index")
- val port = gen
-
- // Reconstruct the resolvedDirection (in Aggregate.bind), since it's not stored.
- // It may not be exactly equal to that value, but the results are the same.
- val reconstructedResolvedDirection = direction match {
- case ActualDirection.Input => SpecifiedDirection.Input
- case ActualDirection.Output => SpecifiedDirection.Output
- case ActualDirection.Bidirectional(ActualDirection.Default) | ActualDirection.Unspecified =>
- SpecifiedDirection.Unspecified
- case ActualDirection.Bidirectional(ActualDirection.Flipped) => SpecifiedDirection.Flip
- }
- // TODO port technically isn't directly child of this data structure, but the result of some
- // muxes / demuxes. However, this does make access consistent with the top-level bindings.
- // Perhaps there's a cleaner way of accomplishing this...
- port.bind(ChildBinding(this), reconstructedResolvedDirection)
-
- val i = Vec.truncateIndex(p, length)(UnlocatableSourceInfo, compileOptions)
- port.setRef(this, i)
-
- port
- }
-
- /** Creates a statically indexed read or write accessor into the array.
- */
- def apply(idx: Int): T = self(idx)
-
- override def cloneType: this.type = {
- new Vec(gen.cloneTypeFull, length).asInstanceOf[this.type]
- }
-
- override def getElements: Seq[Data] =
- (0 until length).map(apply(_))
-
- /** Default "pretty-print" implementation
- * Analogous to printing a Seq
- * Results in "Vec(elt0, elt1, ...)"
- */
- def toPrintable: Printable = {
- // scalastyle:off if.brace
- val elts =
- if (length == 0) List.empty[Printable]
- else self flatMap (e => List(e.toPrintable, PString(", "))) dropRight 1
- // scalastyle:on if.brace
- PString("Vec(") + Printables(elts) + PString(")")
- }
-}
-
-object VecInit extends SourceInfoDoc {
- /** 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
-
- /** @group SourceInfoTransformMacro */
- def do_apply[T <: Data](elts: Seq[T])(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): 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.
-
- // Check that types are homogeneous. Width mismatch for Elements is safe.
- require(!elts.isEmpty)
- elts.foreach(requireIsHardware(_, "vec element"))
-
- val vec = Wire(Vec(elts.length, cloneSupertype(elts, "Vec")))
-
- // TODO: try to remove the logic for this mess
- elts.head.direction match {
- case ActualDirection.Input | ActualDirection.Output | ActualDirection.Unspecified =>
- // When internal wires are involved, driver / sink must be specified explicitly, otherwise
- // the system is unable to infer which is driver / sink
- (vec zip elts).foreach(x => x._1 := x._2)
- case ActualDirection.Bidirectional(_) =>
- // For bidirectional, must issue a bulk connect so subelements are resolved correctly.
- // Bulk connecting two wires may not succeed because Chisel frontend does not infer
- // directions.
- (vec zip elts).foreach(x => x._1 <> x._2)
- }
- 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
-
- /** @group SourceInfoTransformMacro */
- def do_apply[T <: Data](elt0: T, elts: T*)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): 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
-
- /** @group SourceInfoTransformMacro */
- def do_tabulate[T <: Data](n: Int)(gen: (Int) => T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Vec[T] = // scalastyle:ignore line.size.limit
- apply((0 until n).map(i => gen(i)))
-}
-
-/** A trait for [[Vec]]s containing common hardware generators for collection
- * operations.
- */
-trait VecLike[T <: Data] extends collection.IndexedSeq[T] with HasId with SourceInfoDoc {
- def apply(p: UInt): T = macro CompileOptionsTransform.pArg
-
- /** @group SourceInfoTransformMacro */
- def do_apply(p: UInt)(implicit compileOptions: CompileOptions): 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)
-
- @chiselRuntimeDeprecated
- @deprecated("Use Vec.apply instead", "chisel3")
- def read(idx: UInt)(implicit compileOptions: CompileOptions): T = do_apply(idx)(compileOptions)
-
- @chiselRuntimeDeprecated
- @deprecated("Use Vec.apply instead", "chisel3")
- def write(idx: UInt, data: T)(implicit compileOptions: CompileOptions): Unit = {
- do_apply(idx)(compileOptions).:=(data)(DeprecatedSourceInfo, compileOptions)
- }
-
- /** Outputs true if p outputs true for every element.
- */
- def forall(p: T => Bool): Bool = macro SourceInfoTransform.pArg
-
- /** @group SourceInfoTransformMacro */
- def do_forall(p: T => Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool =
- (this map p).fold(true.B)(_ && _)
-
- /** Outputs true if p outputs true for at least one element.
- */
- def exists(p: T => Bool): Bool = macro SourceInfoTransform.pArg
-
- /** @group SourceInfoTransformMacro */
- def do_exists(p: T => Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool =
- (this map p).fold(false.B)(_ || _)
-
- /** 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
-
- /** @group SourceInfoTransformMacro */
- def do_contains(x: T)(implicit sourceInfo: SourceInfo, ev: T <:< UInt, compileOptions: CompileOptions): Bool =
- this.exists(_ === x)
-
- /** Outputs the number of elements for which p is true.
- */
- def count(p: T => Bool): UInt = macro SourceInfoTransform.pArg
-
- /** @group SourceInfoTransformMacro */
- def do_count(p: T => Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): 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 => i.asUInt)
-
- /** Outputs the index of the first element for which p outputs true.
- */
- def indexWhere(p: T => Bool): UInt = macro SourceInfoTransform.pArg
-
- /** @group SourceInfoTransformMacro */
- def do_indexWhere(p: T => Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): 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
-
- /** @group SourceInfoTransformMacro */
- def do_lastIndexWhere(p: T => Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): 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
-
- /** @group SourceInfoTransformMacro */
- def do_onlyIndexWhere(p: T => Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt =
- SeqUtils.oneHotMux(indexWhereHelper(p))
-}
-
-/** Base class for Aggregates based on key values pairs of String and Data
- *
- * Record should only be extended by libraries and fairly sophisticated generators.
- * RTL writers should use [[Bundle]]. See [[Record#elements]] for an example.
- */
-abstract class Record(private[chisel3] implicit val compileOptions: CompileOptions) extends Aggregate {
- private[chisel3] override def bind(target: Binding, parentDirection: SpecifiedDirection): Unit = {
- try {
- super.bind(target, parentDirection)
- } catch { // nasty compatibility mode shim, where anything flies
- case e: Binding.MixedDirectionAggregateException if !compileOptions.dontAssumeDirectionality =>
- val resolvedDirection = SpecifiedDirection.fromParent(parentDirection, specifiedDirection)
- direction = resolvedDirection match {
- case SpecifiedDirection.Unspecified => ActualDirection.Bidirectional(ActualDirection.Default)
- case SpecifiedDirection.Flip => ActualDirection.Bidirectional(ActualDirection.Flipped)
- case _ => ActualDirection.Bidirectional(ActualDirection.Default)
- }
- }
- }
-
- /** Creates a Bundle literal of this type with specified values. this must be a chisel type.
- *
- * @param elems literal values, specified as a pair of the Bundle field to the literal value.
- * The Bundle field is specified as a function from an object of this type to the field.
- * Fields that aren't initialized to DontCare, and assignment to a wire will overwrite any
- * existing value with DontCare.
- * @return a Bundle literal of this type with subelement values specified
- *
- * @example {{{
- * class MyBundle extends Bundle {
- * val a = UInt(8.W)
- * val b = Bool()
- * }
- *
- * (mew MyBundle).Lit(
- * _.a -> 42.U,
- * _.b -> true.B
- * )
- * }}}
- */
- private[chisel3] def _makeLit(elems: (this.type => (Data, Data))*): this.type = { // scalastyle:ignore line.size.limit method.length method.name cyclomatic.complexity
- // Returns pairs of all fields, element-level and containers, in a Record and their path names
- def getRecursiveFields(data: Data, path: String): Seq[(Data, String)] = data match {
- case data: Record => data.elements.map { case (fieldName, fieldData) =>
- getRecursiveFields(fieldData, s"$path.$fieldName")
- }.fold(Seq(data -> path)) { _ ++ _ }
- case data => Seq(data -> path) // we don't support or recurse into other Aggregate types here
- }
-
- // Returns pairs of corresponding fields between two Records of the same type
- def getMatchedFields(x: Data, y: Data): Seq[(Data, Data)] = (x, y) match {
- case (x: Element, y: Element) =>
- require(x typeEquivalent y)
- Seq(x -> y)
- case (x: Record, y: Record) =>
- (x.elements zip y.elements).map { case ((xName, xElt), (yName, yElt)) =>
- require(xName == yName) // assume fields returned in same, deterministic order
- getMatchedFields(xElt, yElt)
- }.fold(Seq(x -> y)) { _ ++ _ }
- }
-
- requireIsChiselType(this, "bundle literal constructor model")
- val clone = cloneType
- val cloneFields = getRecursiveFields(clone, "(bundle root)").toMap
-
- // Create the Bundle literal binding from litargs of arguments
- val bundleLitMap = elems.map { fn => fn(clone) }.flatMap { case (field, value) =>
- val fieldName = cloneFields.getOrElse(field,
- throw new BundleLiteralException(s"field $field (with value $value) is not a field," +
- s" ensure the field is specified as a function returning a field on an object of class ${this.getClass}," +
- s" eg '_.a' to select hypothetical bundle field 'a'")
- )
- val valueBinding = value.topBindingOpt match {
- case Some(litBinding: LitBinding) => litBinding
- case _ => throw new BundleLiteralException(s"field $fieldName specified with non-literal value $value")
- }
-
- field match { // Get the litArg(s) for this field
- case field: Bits =>
- if (field.getClass != value.getClass) { // TODO typeEquivalent is too strict because it checks width
- throw new BundleLiteralException(s"Field $fieldName $field specified with non-type-equivalent value $value")
- }
- val litArg = valueBinding match {
- case ElementLitBinding(litArg) => litArg
- case BundleLitBinding(litMap) => litMap.getOrElse(value,
- throw new BundleLiteralException(s"Field $fieldName specified with unspecified value"))
- }
- Seq(field -> litArg)
- case field: Record =>
- if (!(field typeEquivalent value)) {
- throw new BundleLiteralException(s"field $fieldName $field specified with non-type-equivalent value $value")
- }
- // Copy the source BundleLitBinding with fields (keys) remapped to the clone
- val remap = getMatchedFields(value, field).toMap
- value.topBinding.asInstanceOf[BundleLitBinding].litMap.map { case (valueField, valueValue) =>
- remap(valueField) -> valueValue
- }
- case _ => throw new BundleLiteralException(s"unsupported field $fieldName of type $field")
- }
- } // don't convert to a Map yet to preserve duplicate keys
- val duplicates = bundleLitMap.map(_._1).groupBy(identity).collect { case (x, elts) if elts.size > 1 => x }
- if (!duplicates.isEmpty) {
- val duplicateNames = duplicates.map(cloneFields(_)).mkString(", ")
- throw new BundleLiteralException(s"duplicate fields $duplicateNames in Bundle literal constructor")
- }
- clone.bind(BundleLitBinding(bundleLitMap.toMap))
- clone
- }
-
- /** The collection of [[Data]]
- *
- * This underlying datastructure is a ListMap because the elements must
- * remain ordered for serialization/deserialization. Elements added later
- * are higher order when serialized (this is similar to [[Vec]]). For example:
- * {{{
- * // Assume we have some type MyRecord that creates a Record from the ListMap
- * val record = MyRecord(ListMap("fizz" -> UInt(16.W), "buzz" -> UInt(16.W)))
- * // "buzz" is higher order because it was added later than "fizz"
- * record("fizz") := "hdead".U
- * record("buzz") := "hbeef".U
- * val uint = record.asUInt
- * assert(uint === "hbeefdead".U) // This will pass
- * }}}
- */
- override def toString: String = {
- val bindingString = topBindingOpt match {
- case Some(BundleLitBinding(_)) =>
- val contents = elements.toList.reverse.map { case (name, data) =>
- s"$name=$data"
- }.mkString(", ")
- s"($contents)"
- case _ => bindingToString
- }
- s"$className$bindingString"
- }
-
- val elements: ListMap[String, Data]
-
- /** Name for Pretty Printing */
- def className: String = this.getClass.getSimpleName
-
- private[core] override def typeEquivalent(that: Data): Boolean = that match {
- case that: Record =>
- this.getClass == that.getClass &&
- this.elements.size == that.elements.size &&
- this.elements.forall{case (name, model) =>
- that.elements.contains(name) &&
- (that.elements(name) typeEquivalent model)}
- case _ => false
- }
-
- // NOTE: This sets up dependent references, it can be done before closing the Module
- private[chisel3] override def _onModuleClose: Unit = { // scalastyle:ignore method.name
- // Since Bundle names this via reflection, it is impossible for two elements to have the same
- // identifier; however, Namespace sanitizes identifiers to make them legal for Firrtl/Verilog
- // which can cause collisions
- val _namespace = Namespace.empty
- for ((name, elt) <- elements) { elt.setRef(this, _namespace.name(name, leadingDigitOk=true)) }
- }
-
- private[chisel3] final def allElements: Seq[Element] = elements.toIndexedSeq.flatMap(_._2.allElements)
-
- override def getElements: Seq[Data] = elements.toIndexedSeq.map(_._2)
-
- // Helper because Bundle elements are reversed before printing
- private[chisel3] def toPrintableHelper(elts: Seq[(String, Data)]): Printable = {
- // scalastyle:off if.brace
- val xs =
- if (elts.isEmpty) List.empty[Printable] // special case because of dropRight below
- else elts flatMap { case (name, data) =>
- List(PString(s"$name -> "), data.toPrintable, PString(", "))
- } dropRight 1 // Remove trailing ", "
- // scalastyle:on if.brace
- PString(s"$className(") + Printables(xs) + PString(")")
- }
- /** Default "pretty-print" implementation
- * Analogous to printing a Map
- * Results in "`\$className(elt0.name -> elt0.value, ...)`"
- */
- def toPrintable: Printable = toPrintableHelper(elements.toList)
-}
-
-/**
- * Mix-in for Bundles that have arbitrary Seqs of Chisel types that aren't
- * involved in hardware construction.
- *
- * Used to avoid raising an error/exception when a Seq is a public member of the
- * bundle.
- * This is useful if we those public Seq fields in the Bundle are unrelated to
- * hardware construction.
- */
-trait IgnoreSeqInBundle {
- this: Bundle =>
-
- override def ignoreSeq: Boolean = true
-}
-
-class AutoClonetypeException(message: String) extends ChiselException(message)
-class BundleLiteralException(message: String) extends ChiselException(message)
-
-/** 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.
- *
- * Example of an anonymous IO bundle
- * {{{
- * class MyModule extends Module {
- * val io = IO(new Bundle {
- * val in = Input(UInt(64.W))
- * val out = Output(SInt(128.W))
- * })
- * }
- * }}}
- *
- * Or as a named class
- * {{{
- * class Packet extends Bundle {
- * val header = UInt(16.W)
- * val addr = UInt(16.W)
- * val data = UInt(32.W)
- * }
- * class MyModule extends Module {
- * val io = IO(new Bundle {
- * val inPacket = Input(new Packet)
- * val outPacket = Output(new Packet)
- * })
- * val reg = Reg(new Packet)
- * reg <> inPacket
- * outPacket <> reg
- * }
- * }}}
- */
-abstract class Bundle(implicit compileOptions: CompileOptions) extends Record {
- override def className: String = this.getClass.getSimpleName match {
- case name if name.startsWith("$anon$") => "AnonymousBundle" // fallback for anonymous Bundle case
- case "" => "AnonymousBundle" // ditto, but on other platforms
- case name => name
- }
- /** The collection of [[Data]]
- *
- * Elements defined earlier in the Bundle are higher order upon
- * serialization. For example:
- * @example
- * {{{
- * class MyBundle extends Bundle {
- * val foo = UInt(16.W)
- * val bar = UInt(16.W)
- * }
- * // Note that foo is higher order because its defined earlier in the Bundle
- * val bundle = Wire(new MyBundle)
- * bundle.foo := 0x1234.U
- * bundle.bar := 0x5678.U
- * val uint = bundle.asUInt
- * assert(uint === "h12345678".U) // This will pass
- * }}}
- */
- final lazy val elements: ListMap[String, Data] = {
- val nameMap = LinkedHashMap[String, Data]()
- for (m <- getPublicFields(classOf[Bundle])) {
- getBundleField(m) match {
- case Some(d: Data) =>
- if (nameMap contains m.getName) {
- require(nameMap(m.getName) eq d)
- } else {
- nameMap(m.getName) = d
- }
- case None =>
- if (!ignoreSeq) {
- m.invoke(this) match {
- case s: scala.collection.Seq[Any] if s.nonEmpty => s.head match {
- // Ignore empty Seq()
- case d: Data => throwException("Public Seq members cannot be used to define Bundle elements " +
- s"(found public Seq member '${m.getName}'). " +
- "Either use a Vec if all elements are of the same type, or MixedVec if the elements " +
- "are of different types. If this Seq member is not intended to construct RTL, mix in the trait " +
- "IgnoreSeqInBundle.")
- case _ => // don't care about non-Data Seq
- }
- case _ => // not a Seq
- }
- }
- }
- }
- ListMap(nameMap.toSeq sortWith { case ((an, a), (bn, b)) => (a._id > b._id) || ((a eq b) && (an > bn)) }: _*)
- // scalastyle:ignore method.length
- }
-
- /**
- * Overridden by [[IgnoreSeqInBundle]] to allow arbitrary Seqs of Chisel elements.
- */
- def ignoreSeq: Boolean = false
-
- /** 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] = m.invoke(this) match {
- case d: Data => Some(d)
- case Some(d: Data) => Some(d)
- case _ => None
- }
-
- // Memoize the outer instance for autoclonetype, especially where this is context-dependent
- // (like the outer module or enclosing Bundles).
- private var _outerInst: Option[Object] = None
-
- // For autoclonetype, record possible candidates for outer instance.
- // _outerInst should always take precedence, since it should be propagated from the original
- // object which has the most accurate context.
- private val _containingModule: Option[BaseModule] = Builder.currentModule
- private val _containingBundles: Seq[Bundle] = Builder.updateBundleStack(this)
-
- override def cloneType : this.type = { // scalastyle:ignore cyclomatic.complexity method.length
- // This attempts to infer constructor and arguments to clone this Bundle subtype without
- // requiring the user explicitly overriding cloneType.
- import scala.language.existentials
- import scala.reflect.runtime.universe._
-
- val clazz = this.getClass
-
- def autoClonetypeError(desc: String): Nothing = {
- throw new AutoClonetypeException(s"Unable to automatically infer cloneType on $clazz: $desc")
- }
-
- def validateClone(clone: Bundle, equivDiagnostic: String): Unit = {
- if (!clone.typeEquivalent(this)) {
- autoClonetypeError(s"Automatically cloned $clone not type-equivalent to base $this. " + equivDiagnostic)
- }
-
- for ((name, field) <- elements) {
- if (clone.elements(name) eq field) {
- autoClonetypeError(s"Automatically cloned $clone has field $name aliased with base $this." +
- " In the future, this can be solved by wrapping the field in Field(...)," +
- " see https://github.com/freechipsproject/chisel3/pull/909." +
- " For now, ensure Chisel types used in the Bundle definition are passed through constructor arguments," +
- " or wrapped in Input(...), Output(...), or Flipped(...) if appropriate.")
- }
- }
- }
-
- val mirror = runtimeMirror(clazz.getClassLoader)
- val classSymbolOption = try {
- Some(mirror.reflect(this).symbol)
- } catch {
- case e: scala.reflect.internal.Symbols#CyclicReference => None // Workaround for a scala bug
- }
-
- val enclosingClassOption = (clazz.getEnclosingClass, classSymbolOption) match {
- case (null, _) => None
- case (_, Some(classSymbol)) if classSymbol.isStatic => None // allows support for members of companion objects
- case (outerClass, _) => Some(outerClass)
- }
-
- // For compatibility with pre-3.1, where null is tried as an argument to the constructor.
- // This stores potential error messages which may be used later.
- var outerClassError: Option[String] = None
-
- // Check if this is an inner class, and if so, try to get the outer instance
- val outerClassInstance = enclosingClassOption.map { outerClass =>
- def canAssignOuterClass(x: Object) = outerClass.isAssignableFrom(x.getClass)
-
- val outerInstance = _outerInst match {
- case Some(outerInstance) => outerInstance // use _outerInst if defined
- case None => // determine outer instance if not already recorded
- try {
- // Prefer this if it works, but doesn't work in all cases, namely anonymous inner Bundles
- val outer = clazz.getDeclaredField("$outer").get(this)
- _outerInst = Some(outer)
- outer
- } catch {
- case (_: NoSuchFieldException | _: IllegalAccessException) =>
- // Fallback using guesses based on common patterns
- val allOuterCandidates = Seq(
- _containingModule.toSeq,
- _containingBundles
- ).flatten.distinct
- allOuterCandidates.filter(canAssignOuterClass(_)) match {
- case outer :: Nil =>
- _outerInst = Some(outer) // record the guess for future use
- outer
- case Nil => // TODO: replace with fatal autoClonetypeError once compatibility period is dropped
- outerClassError = Some(s"Unable to determine instance of outer class $outerClass," +
- s" no candidates assignable to outer class types; examined $allOuterCandidates")
- null
- case candidates => // TODO: replace with fatal autoClonetypeError once compatibility period is dropped
- outerClassError = Some(s"Unable to determine instance of outer class $outerClass," +
- s" multiple possible candidates $candidates assignable to outer class type")
- null
- }
- }
- }
- (outerClass, outerInstance)
- }
-
- // If possible (constructor with no arguments), try Java reflection first
- // This handles two cases that Scala reflection doesn't:
- // 1. getting the ClassSymbol of a class with an anonymous outer class fails with a
- // CyclicReference exception
- // 2. invoking the constructor of an anonymous inner class seems broken (it expects the outer
- // class as an argument, but fails because the number of arguments passed in is incorrect)
- if (clazz.getConstructors.size == 1) {
- var ctor = clazz.getConstructors.head
- val argTypes = ctor.getParameterTypes.toList
- val clone = (argTypes, outerClassInstance) match {
- case (Nil, None) => // no arguments, no outer class, invoke constructor directly
- Some(ctor.newInstance().asInstanceOf[this.type])
- case (argType :: Nil, Some((_, outerInstance))) =>
- if (outerInstance == null) {
- Builder.deprecated(s"chisel3.1 autoclonetype failed, falling back to 3.0 behavior using null as the outer instance." + // scalastyle:ignore line.size.limit
- s" Autoclonetype failure reason: ${outerClassError.get}",
- Some(s"$clazz"))
- Some(ctor.newInstance(outerInstance).asInstanceOf[this.type])
- } else if (argType isAssignableFrom outerInstance.getClass) {
- Some(ctor.newInstance(outerInstance).asInstanceOf[this.type])
- } else {
- None
- }
- case _ => None
-
- }
- clone match {
- case Some(clone) =>
- clone._outerInst = this._outerInst
- validateClone(clone, "Constructor argument values were not inferred, ensure constructor is deterministic.")
- return clone.asInstanceOf[this.type]
- case None =>
- }
- }
-
- // Get constructor parameters and accessible fields
- val classSymbol = classSymbolOption.getOrElse(autoClonetypeError(s"scala reflection failed." +
- " This is known to occur with inner classes on anonymous outer classes." +
- " In those cases, autoclonetype only works with no-argument constructors, or you can define a custom cloneType.")) // scalastyle:ignore line.size.limit
-
- val decls = classSymbol.typeSignature.decls
- val ctors = decls.collect { case meth: MethodSymbol if meth.isConstructor => meth }
- if (ctors.size != 1) {
- autoClonetypeError(s"found multiple constructors ($ctors)." +
- " Either remove all but the default constructor, or define a custom cloneType method.")
- }
- val ctor = ctors.head
- val ctorParamss = ctor.paramLists
- val ctorParams = ctorParamss match {
- case Nil => List()
- case ctorParams :: Nil => ctorParams
- case ctorParams :: ctorImplicits :: Nil => ctorParams ++ ctorImplicits
- case _ => autoClonetypeError(s"internal error, unexpected ctorParamss = $ctorParamss")
- }
- val ctorParamsNames = ctorParams.map(_.name.toString)
-
- // Special case for anonymous inner classes: their constructor consists of just the outer class reference
- // Scala reflection on anonymous inner class constructors seems broken
- if (ctorParams.size == 1 && outerClassInstance.isDefined &&
- ctorParams.head.typeSignature == mirror.classSymbol(outerClassInstance.get._1).toType) {
- // Fall back onto Java reflection
- val ctors = clazz.getConstructors
- require(ctors.size == 1) // should be consistent with Scala constructors
- try {
- val clone = ctors.head.newInstance(outerClassInstance.get._2).asInstanceOf[this.type]
- clone._outerInst = this._outerInst
-
- validateClone(clone, "Outer class instance was inferred, ensure constructor is deterministic.")
- return clone
- } catch {
- case e @ (_: java.lang.reflect.InvocationTargetException | _: IllegalArgumentException) =>
- autoClonetypeError(s"unexpected failure at constructor invocation, got $e.")
- }
- }
-
- // Get all the class symbols up to (but not including) Bundle and get all the accessors.
- // (each ClassSymbol's decls only includes those declared in the class itself)
- val bundleClassSymbol = mirror.classSymbol(classOf[Bundle])
- val superClassSymbols = classSymbol.baseClasses.takeWhile(_ != bundleClassSymbol)
- val superClassDecls = superClassSymbols.map(_.typeSignature.decls).flatten
- val accessors = superClassDecls.collect { case meth: MethodSymbol if meth.isParamAccessor => meth }
-
- // Get constructor argument values
- // Check that all ctor params are immutable and accessible. Immutability is required to avoid
- // potential subtle bugs (like values changing after cloning).
- // This also generates better error messages (all missing elements shown at once) instead of
- // failing at the use site one at a time.
- val accessorsName = accessors.filter(_.isStable).map(_.name.toString)
- val paramsDiff = ctorParamsNames.toSet -- accessorsName.toSet
- if (!paramsDiff.isEmpty) {
- // scalastyle:off line.size.limit
- autoClonetypeError(s"constructor has parameters (${paramsDiff.toList.sorted.mkString(", ")}) that are not both immutable and accessible." +
- " Either make all parameters immutable and accessible (vals) so cloneType can be inferred, or define a custom cloneType method.")
- // scalastyle:on line.size.limit
- }
-
- // Get all the argument values
- val accessorsMap = accessors.map(accessor => accessor.name.toString -> accessor).toMap
- val instanceReflect = mirror.reflect(this)
- val ctorParamsNameVals = ctorParamsNames.map {
- paramName => paramName -> instanceReflect.reflectMethod(accessorsMap(paramName)).apply()
- }
-
- // Opportunistic sanity check: ensure any arguments of type Data is not bound
- // (which could lead to data conflicts, since it's likely the user didn't know to re-bind them).
- // This is not guaranteed to catch all cases (for example, Data in Tuples or Iterables).
- val boundDataParamNames = ctorParamsNameVals.collect {
- case (paramName, paramVal: Data) if paramVal.topBindingOpt.isDefined => paramName
- }
- if (boundDataParamNames.nonEmpty) {
- // scalastyle:off line.size.limit
- autoClonetypeError(s"constructor parameters (${boundDataParamNames.sorted.mkString(", ")}) have values that are hardware types, which is likely to cause subtle errors." +
- " Use chisel types instead: use the value before it is turned to a hardware type (with Wire(...), Reg(...), etc) or use chiselTypeOf(...) to extract the chisel type.")
- // scalastyle:on line.size.limit
- }
-
- // Clone unbound parameters in case they are being used as bundle fields.
- val ctorParamsVals = ctorParamsNameVals.map {
- case (_, paramVal: Data) => paramVal.cloneTypeFull
- case (_, paramVal) => paramVal
- }
-
- // Invoke ctor
- val classMirror = outerClassInstance match {
- case Some((_, null)) => autoClonetypeError(outerClassError.get) // deals with the null hack for 3.0 compatibility
- case Some((_, outerInstance)) => mirror.reflect(outerInstance).reflectClass(classSymbol)
- case _ => mirror.reflectClass(classSymbol)
- }
- val clone = classMirror.reflectConstructor(ctor).apply(ctorParamsVals:_*).asInstanceOf[this.type]
- clone._outerInst = this._outerInst
-
- validateClone(clone,
- "Constructor argument values were inferred:" +
- " ensure that variable names are consistent and have the same value throughout the constructor chain," +
- " and that the constructor is deterministic."
- )
- clone
- }
-
- /** Default "pretty-print" implementation
- * Analogous to printing a Map
- * Results in "`Bundle(elt0.name -> elt0.value, ...)`"
- * @note The order is reversed from the order of elements in order to print
- * the fields in the order they were defined
- */
- override def toPrintable: Printable = toPrintableHelper(elements.toList.reverse)
- // scalastyle:off method.length
-}
-// scalastyle:off file.size.limit
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Annotation.scala b/chiselFrontend/src/main/scala/chisel3/core/Annotation.scala
deleted file mode 100644
index b7e82f63..00000000
--- a/chiselFrontend/src/main/scala/chisel3/core/Annotation.scala
+++ /dev/null
@@ -1,138 +0,0 @@
-// See LICENSE for license details.
-
-package chisel3.core
-
-import scala.language.existentials
-
-import chisel3.internal.{Builder, InstanceId}
-import firrtl.Transform
-import firrtl.annotations.{Annotation, CircuitName, ComponentName, ModuleName}
-import firrtl.transforms.{DontTouchAnnotation, NoDedupAnnotation}
-
-/** Interface for Annotations in Chisel
- *
- * Defines a conversion to a corresponding FIRRTL Annotation
- */
-trait ChiselAnnotation {
- /** Conversion to FIRRTL Annotation */
- def toFirrtl: Annotation
-}
-object ChiselAnnotation {
- @deprecated("Write a custom ChiselAnnotation subclass instead", "3.1")
- def apply(component: InstanceId, transformClass: Class[_ <: Transform], value: String): ChiselLegacyAnnotation =
- ChiselLegacyAnnotation(component, transformClass, value)
- @deprecated("Write a custom ChiselAnnotation subclass instead", "3.1")
- def unapply(anno: ChiselAnnotation): Option[(InstanceId, Class[_ <: Transform], String)] =
- anno match {
- case ChiselLegacyAnnotation(c, t, v) => Some(c, t, v)
- case _ => None
- }
-}
-
-/** Mixin for [[ChiselAnnotation]] that instantiates an associated FIRRTL Transform when this Annotation is present
- * during a run of
- * [[Driver$.execute(args:Array[String],dut:()=>chisel3\.experimental\.RawModule)* Driver.execute]].
- * Automatic Transform instantiation is *not* supported when the Circuit and Annotations are serialized before invoking
- * FIRRTL.
- */
-// TODO There should be a FIRRTL API for this instead
-trait RunFirrtlTransform extends ChiselAnnotation {
- def transformClass: Class[_ <: Transform]
-}
-
-// This exists for implementation reasons, we don't want people using this type directly
-final case class ChiselLegacyAnnotation private[chisel3] (
- component: InstanceId,
- transformClass: Class[_ <: Transform],
- value: String) extends ChiselAnnotation with RunFirrtlTransform {
- def toFirrtl: Annotation = Annotation(component.toNamed, transformClass, value)
-}
-private[chisel3] object ChiselLegacyAnnotation
-
-object annotate { // scalastyle:ignore object.name
- def apply(anno: ChiselAnnotation): Unit = {
- Builder.annotations += anno
- }
-}
-
-/** Marks that a signal should not be removed by Chisel and Firrtl optimization passes
- *
- * @example {{{
- * class MyModule extends Module {
- * val io = IO(new Bundle {
- * val a = Input(UInt(32.W))
- * val b = Output(UInt(32.W))
- * })
- * io.b := io.a
- * val dead = io.a +% 1.U // normally dead would be pruned by DCE
- * dontTouch(dead) // Marking it as such will preserve it
- * }
- * }}}
- *
- * @note Calling this on [[Data]] creates an annotation that Chisel emits to a separate annotations
- * file. This file must be passed to FIRRTL independently of the `.fir` file. The execute methods
- * in [[chisel3.Driver]] will pass the annotations to FIRRTL automatically.
- */
-object dontTouch { // scalastyle:ignore object.name
- /** Marks a signal to be preserved in Chisel and Firrtl
- *
- * @note Requires the argument to be bound to hardware
- * @param data The signal to be marked
- * @return Unmodified signal `data`
- */
- def apply[T <: Data](data: T)(implicit compileOptions: CompileOptions): T = {
- if (compileOptions.checkSynthesizable) {
- requireIsHardware(data, "Data marked dontTouch")
- }
- annotate(new ChiselAnnotation { def toFirrtl = DontTouchAnnotation(data.toNamed) })
- data
- }
-}
-
-/** Marks that a module to be ignored in Dedup Transform in Firrtl pass
- *
- * @example {{{
- * def fullAdder(a: UInt, b: UInt, myName: String): UInt = {
- * val m = Module(new Module {
- * val io = IO(new Bundle {
- * val a = Input(UInt(32.W))
- * val b = Input(UInt(32.W))
- * val out = Output(UInt(32.W))
- * })
- * override def desiredName = "adder_" + myNname
- * io.out := io.a + io.b
- * })
- * doNotDedup(m)
- * m.io.a := a
- * m.io.b := b
- * m.io.out
- * }
- *
- *class AdderTester extends Module
- * with ConstantPropagationTest {
- * val io = IO(new Bundle {
- * val a = Input(UInt(32.W))
- * val b = Input(UInt(32.W))
- * val out = Output(Vec(2, UInt(32.W)))
- * })
- *
- * io.out(0) := fullAdder(io.a, io.b, "mod1")
- * io.out(1) := fullAdder(io.a, io.b, "mod2")
- * }
- * }}}
- *
- * @note Calling this on [[Data]] creates an annotation that Chisel emits to a separate annotations
- * file. This file must be passed to FIRRTL independently of the `.fir` file. The execute methods
- * in [[chisel3.Driver]] will pass the annotations to FIRRTL automatically.
- */
-
-object doNotDedup { // scalastyle:ignore object.name
- /** Marks a module to be ignored in Dedup Transform in Firrtl
- *
- * @param data The module to be marked
- * @return Unmodified signal `module`
- */
- def apply[T <: LegacyModule](module: T)(implicit compileOptions: CompileOptions): Unit = {
- annotate(new ChiselAnnotation { def toFirrtl = NoDedupAnnotation(module.toNamed) })
- }
-}
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Assert.scala b/chiselFrontend/src/main/scala/chisel3/core/Assert.scala
deleted file mode 100644
index 054222c3..00000000
--- a/chiselFrontend/src/main/scala/chisel3/core/Assert.scala
+++ /dev/null
@@ -1,92 +0,0 @@
-// See LICENSE for license details.
-
-package chisel3.core
-
-import scala.reflect.macros.blackbox.Context
-import scala.language.experimental.macros
-
-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
- * 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 format string to print when the assertion fires
- * @param data optional bits to print in the message formatting
- *
- * @note See [[printf.apply(fmt:String* printf]] for format string documentation
- * @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, data: Bits*)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Unit = macro apply_impl_msg_data // scalastyle:ignore line.size.limit
- def apply(cond: Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Unit = macro apply_impl
-
- def apply_impl_msg_data(c: Context)(cond: c.Tree, message: c.Tree, data: c.Tree*)(sourceInfo: c.Tree, compileOptions: c.Tree): c.Tree = { // scalastyle:ignore line.size.limit
- 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), ..$data)($sourceInfo, $compileOptions)"
- }
-
- def apply_impl(c: Context)(cond: c.Tree)(sourceInfo: c.Tree, compileOptions: 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, $compileOptions)"
- }
-
- def apply_impl_do(cond: Bool, line: String, message: Option[String], data: Bits*)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) { // scalastyle:ignore line.size.limit
- val escLine = line.replaceAll("%", "%%")
- when (!(cond || Module.reset.asBool)) {
- val fmt = message match {
- case Some(msg) =>
- s"Assertion failed: $msg\n at $escLine\n"
- case None => s"Assertion failed\n at $escLine\n"
- }
- printf.printfWithoutReset(fmt, data:_*)
- pushCommand(Stop(sourceInfo, Builder.forcedClock.ref, 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, "")
- }
-}
-
-object stop { // scalastyle:ignore object.name
- /** Terminate execution with a failure code. */
- def apply(code: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Unit = {
- when (!Module.reset.asBool) {
- pushCommand(Stop(sourceInfo, Builder.forcedClock.ref, code))
- }
- }
-
- /** Terminate execution, indicating success. */
- def apply()(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Unit = {
- stop(0)
- }
-}
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Attach.scala b/chiselFrontend/src/main/scala/chisel3/core/Attach.scala
deleted file mode 100644
index 5fb89b18..00000000
--- a/chiselFrontend/src/main/scala/chisel3/core/Attach.scala
+++ /dev/null
@@ -1,45 +0,0 @@
-// See LICENSE for license details.
-
-package chisel3.core
-
-import chisel3.internal._
-import chisel3.internal.Builder.pushCommand
-import chisel3.internal.firrtl._
-import chisel3.internal.sourceinfo.{SourceInfo}
-
-object attach { // scalastyle:ignore object.name
- // Exceptions that can be generated by attach
- case class AttachException(message: String) extends ChiselException(message)
- def ConditionalAttachException: AttachException = // scalastyle:ignore method.name
- AttachException(": Conditional attach is not allowed!")
-
- // Actual implementation
- private[core] def impl(elts: Seq[Analog], contextModule: RawModule)(implicit sourceInfo: SourceInfo): Unit = {
- if (Builder.whenDepth != 0) throw ConditionalAttachException
-
- // TODO Check that references are valid and can be attached
-
- pushCommand(Attach(sourceInfo, elts.map(_.lref)))
- }
-
- /** Create an electrical connection between [[Analog]] components
- *
- * @param elts The components to attach
- *
- * @example
- * {{{
- * val a1 = Wire(Analog(32.W))
- * val a2 = Wire(Analog(32.W))
- * attach(a1, a2)
- * }}}
- */
- def apply(elts: Analog*)(implicit sourceInfo: SourceInfo): Unit = {
- try {
- impl(elts, Builder.forcedUserModule)
- } catch {
- case AttachException(message) =>
- throwException(elts.mkString("Attaching (", ", ", s") failed @$message"))
- }
- }
-}
-
diff --git a/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala b/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala
deleted file mode 100644
index b1f9bcb5..00000000
--- a/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala
+++ /dev/null
@@ -1,332 +0,0 @@
-// See LICENSE for license details.
-
-package chisel3.core
-
-import chisel3.internal.ChiselException
-import chisel3.internal.Builder.pushCommand
-import chisel3.internal.firrtl.{Connect, DefInvalid}
-import scala.language.experimental.macros
-import chisel3.internal.sourceinfo._
-
-/**
-* 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 {
- // scalastyle:off method.name public.methods.have.type
- // These are all the possible exceptions that can be thrown.
- case class BiConnectException(message: String) extends ChiselException(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 Record missing field ($field).")
- def MissingRightFieldException(field: String) =
- BiConnectException(s": Right Record missing field ($field).")
- def MismatchedException(left: String, right: String) =
- BiConnectException(s": Left ($left) and Right ($right) have different types.")
- def AttachAlreadyBulkConnectedException(sourceInfo: SourceInfo) =
- BiConnectException(sourceInfo.makeMessage(": Analog previously bulk connected at " + _))
- def DontCareCantBeSink =
- BiConnectException(": DontCare cannot be a connection sink (LHS)")
- // scalastyle:on method.name public.methods.have.type
-
- /** 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, connectCompileOptions: CompileOptions, left: Data, right: Data, context_mod: RawModule): Unit = { // scalastyle:ignore line.size.limit cyclomatic.complexity method.length
- (left, right) match {
- // Handle element case (root case)
- case (left_a: Analog, right_a: Analog) =>
- try {
- analogAttach(sourceInfo, left_a, right_a, context_mod)
- } catch {
- // If attach fails, convert to BiConnectException
- case attach.AttachException(message) => throw BiConnectException(message)
- }
- case (left_e: Element, right_e: Element) => {
- elemConnect(sourceInfo, connectCompileOptions, 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 {
- implicit val compileOptions = connectCompileOptions
- connect(sourceInfo, connectCompileOptions, left_v(idx), right_v(idx), context_mod)
- } catch {
- case BiConnectException(message) => throw BiConnectException(s"($idx)$message")
- }
- }
- }
- // Handle Vec connected to DontCare
- case (left_v: Vec[Data@unchecked], DontCare) => {
- for (idx <- 0 until left_v.length) {
- try {
- implicit val compileOptions = connectCompileOptions
- connect(sourceInfo, connectCompileOptions, left_v(idx), right, context_mod)
- } catch {
- case BiConnectException(message) => throw BiConnectException(s"($idx)$message")
- }
- }
- }
- // Handle DontCare connected to Vec
- case (DontCare, right_v: Vec[Data@unchecked]) => {
- for (idx <- 0 until right_v.length) {
- try {
- implicit val compileOptions = connectCompileOptions
- connect(sourceInfo, connectCompileOptions, left, right_v(idx), context_mod)
- } catch {
- case BiConnectException(message) => throw BiConnectException(s"($idx)$message")
- }
- }
- }
- // Handle Records defined in Chisel._ code (change to NotStrict)
- case (left_r: Record, right_r: Record) => (left_r.compileOptions, right_r.compileOptions) match {
- case (ExplicitCompileOptions.NotStrict, _) =>
- left_r.bulkConnect(right_r)(sourceInfo, ExplicitCompileOptions.NotStrict)
- case (_, ExplicitCompileOptions.NotStrict) =>
- left_r.bulkConnect(right_r)(sourceInfo, ExplicitCompileOptions.NotStrict)
- case _ => recordConnect(sourceInfo, connectCompileOptions, left_r, right_r, context_mod)
- }
-
- // Handle Records connected to DontCare (change to NotStrict)
- case (left_r: Record, DontCare) =>
- left_r.compileOptions match {
- case ExplicitCompileOptions.NotStrict =>
- left.bulkConnect(right)(sourceInfo, ExplicitCompileOptions.NotStrict)
- case _ =>
- // For each field in left, descend with right
- for ((field, left_sub) <- left_r.elements) {
- try {
- connect(sourceInfo, connectCompileOptions, left_sub, right, context_mod)
- } catch {
- case BiConnectException(message) => throw BiConnectException(s".$field$message")
- }
- }
- }
- case (DontCare, right_r: Record) =>
- right_r.compileOptions match {
- case ExplicitCompileOptions.NotStrict =>
- left.bulkConnect(right)(sourceInfo, ExplicitCompileOptions.NotStrict)
- case _ =>
- // For each field in left, descend with right
- for ((field, right_sub) <- right_r.elements) {
- try {
- connect(sourceInfo, connectCompileOptions, left, right_sub, context_mod)
- } 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)
- }
- }
-
- // Do connection of two Records
- def recordConnect(sourceInfo: SourceInfo,
- connectCompileOptions: CompileOptions,
- left_r: Record,
- right_r: Record,
- context_mod: RawModule): Unit = {
- // Verify right has no extra fields that left doesn't have
- for((field, right_sub) <- right_r.elements) {
- if(!left_r.elements.isDefinedAt(field)) {
- if (connectCompileOptions.connectFieldsMustMatch) {
- throw MissingLeftFieldException(field)
- }
- }
- }
- // For each field in left, descend with right
- for((field, left_sub) <- left_r.elements) {
- try {
- right_r.elements.get(field) match {
- case Some(right_sub) => connect(sourceInfo, connectCompileOptions, left_sub, right_sub, context_mod)
- case None => {
- if (connectCompileOptions.connectFieldsMustMatch) {
- throw MissingRightFieldException(field)
- }
- }
- }
- } catch {
- case BiConnectException(message) => throw BiConnectException(s".$field$message")
- }
- }
- }
-
-
- // 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 = {
- // Source and sink are ambiguous in the case of a Bi/Bulk Connect (<>).
- // If either is a DontCareBinding, just issue a DefInvalid for the other,
- // otherwise, issue a Connect.
- (left.topBinding, right.topBinding) match {
- case (lb: DontCareBinding, _) => pushCommand(DefInvalid(sourceInfo, right.lref))
- case (_, rb: DontCareBinding) => pushCommand(DefInvalid(sourceInfo, left.lref))
- case (_, _) => 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 = {
- // Source and sink are ambiguous in the case of a Bi/Bulk Connect (<>).
- // If either is a DontCareBinding, just issue a DefInvalid for the other,
- // otherwise, issue a Connect.
- (left.topBinding, right.topBinding) match {
- case (lb: DontCareBinding, _) => pushCommand(DefInvalid(sourceInfo, right.lref))
- case (_, rb: DontCareBinding) => pushCommand(DefInvalid(sourceInfo, left.lref))
- case (_, _) => 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, connectCompileOptions: CompileOptions, left: Element, right: Element, context_mod: RawModule): Unit = { // scalastyle:ignore line.size.limit cyclomatic.complexity method.length
- import BindingDirection.{Internal, 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: BaseModule = left.topBinding.location.getOrElse(context_mod)
- val right_mod: BaseModule = right.topBinding.location.getOrElse(context_mod)
-
- val left_direction = BindingDirection.from(left.topBinding, left.direction)
- val right_direction = BindingDirection.from(right.topBinding, right.direction)
-
- // 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): @unchecked) match {
- // CURRENT MOD CHILD MOD
- case (Input, Input) => issueConnectL2R(left, right)
- case (Internal, Input) => issueConnectL2R(left, right)
-
- case (Output, Output) => issueConnectR2L(left, right)
- case (Internal, Output) => issueConnectR2L(left, right)
-
- case (Input, Output) => throw BothDriversException
- case (Output, Input) => throw NeitherDriverException
- case (_, Internal) => 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): @unchecked) match {
- // CHILD MOD CURRENT MOD
- case (Input, Input) => issueConnectR2L(left, right)
- case (Input, Internal) => issueConnectR2L(left, right)
-
- case (Output, Output) => issueConnectL2R(left, right)
- case (Output, Internal) => issueConnectL2R(left, right)
-
- case (Input, Output) => throw NeitherDriverException
- case (Output, Input) => throw BothDriversException
- case (Internal, _) => 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): @unchecked) match {
- // CURRENT MOD CURRENT MOD
- case (Input, Output) => issueConnectL2R(left, right)
- case (Input, Internal) => issueConnectL2R(left, right)
- case (Internal, Output) => issueConnectL2R(left, right)
-
- case (Output, Input) => issueConnectR2L(left, right)
- case (Output, Internal) => issueConnectR2L(left, right)
- case (Internal, Input) => issueConnectR2L(left, right)
-
- case (Input, Input) => throw BothDriversException
- case (Output, Output) => throw BothDriversException
- case (Internal, Internal) => {
- if (connectCompileOptions.dontAssumeDirectionality) {
- throw UnknownDriverException
- } else {
- issueConnectR2L(left, right)
- }
- }
- }
- }
-
- // 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): @unchecked) match {
- // CHILD MOD CHILD MOD
- case (Input, Output) => issueConnectR2L(left, right)
- case (Output, Input) => issueConnectL2R(left, right)
-
- case (Input, Input) => throw NeitherDriverException
- case (Output, Output) => throw BothDriversException
- case (_, Internal) =>
- if (connectCompileOptions.dontAssumeDirectionality) {
- throw UnknownRelationException
- } else {
- issueConnectR2L(left, right)
- }
- case (Internal, _) =>
- if (connectCompileOptions.dontAssumeDirectionality) {
- throw UnknownRelationException
- } else {
- issueConnectR2L(left, right)
- }
- }
- }
-
- // Not quite sure where left and right are compared to current module
- // so just error out
- else throw UnknownRelationException
- }
-
- // This function checks if analog element-level attaching is allowed
- // Then it either issues it or throws the appropriate exception.
- def analogAttach(implicit sourceInfo: SourceInfo, left: Analog, right: Analog, contextModule: RawModule): Unit = {
- // Error if left or right is BICONNECTED in the current module already
- for (elt <- left :: right :: Nil) {
- elt.biConnectLocs.get(contextModule) match {
- case Some(sl) => throw AttachAlreadyBulkConnectedException(sl)
- case None => // Do nothing
- }
- }
-
- // Do the attachment
- attach.impl(Seq(left, right), contextModule)
- // Mark bulk connected
- left.biConnectLocs(contextModule) = sourceInfo
- right.biConnectLocs(contextModule) = sourceInfo
- }
-}
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Binding.scala b/chiselFrontend/src/main/scala/chisel3/core/Binding.scala
deleted file mode 100644
index e30b91ec..00000000
--- a/chiselFrontend/src/main/scala/chisel3/core/Binding.scala
+++ /dev/null
@@ -1,122 +0,0 @@
-// See LICENSE for license details.
-
-package chisel3.core
-
-import chisel3.internal.ChiselException
-import chisel3.internal.Builder.{forcedModule}
-import chisel3.internal.firrtl.LitArg
-
-object Binding {
- class BindingException(message: String) extends ChiselException(message)
- /** A function expected a Chisel type but got a hardware object
- */
- case class ExpectedChiselTypeException(message: String) extends BindingException(message)
- /**A function expected a hardware object but got a Chisel type
- */
- case class ExpectedHardwareException(message: String) extends BindingException(message)
- /** An aggregate had a mix of specified and unspecified directionality children
- */
- case class MixedDirectionAggregateException(message: String) extends BindingException(message)
- /** Attempted to re-bind an already bound (directionality or hardware) object
- */
- case class RebindingException(message: String) extends BindingException(message)
-}
-
-/** Requires that a node is hardware ("bound")
- */
-object requireIsHardware {
- def apply(node: Data, msg: String = ""): Unit = {
- node._parent match { // Compatibility layer hack
- case Some(x: BaseModule) => x._compatAutoWrapPorts
- case _ =>
- }
- if (!node.isSynthesizable) {
- val prefix = if (msg.nonEmpty) s"$msg " else ""
- throw Binding.ExpectedHardwareException(s"$prefix'$node' must be hardware, " +
- "not a bare Chisel type. Perhaps you forgot to wrap it in Wire(_) or IO(_)?")
- }
- }
-}
-
-/** Requires that a node is a chisel type (not hardware, "unbound")
- */
-object requireIsChiselType {
- def apply(node: Data, msg: String = ""): Unit = if (node.isSynthesizable) {
- val prefix = if (msg.nonEmpty) s"$msg " else ""
- throw Binding.ExpectedChiselTypeException(s"$prefix'$node' must be a Chisel type, not hardware")
- }
-}
-
-// Element only direction used for the Binding system only.
-sealed abstract class BindingDirection
-object BindingDirection {
- /** Internal type or wire
- */
- case object Internal extends BindingDirection
- /** Module port with output direction
- */
- case object Output extends BindingDirection
- /** Module port with input direction
- */
- case object Input extends BindingDirection
-
- /** Determine the BindingDirection of an Element given its top binding and resolved direction.
- */
- def from(binding: TopBinding, direction: ActualDirection): BindingDirection = {
- binding match {
- case PortBinding(_) => direction match {
- case ActualDirection.Output => Output
- case ActualDirection.Input => Input
- case dir => throw new RuntimeException(s"Unexpected port element direction '$dir'")
- }
- case _ => Internal
- }
- }
-}
-
-// Location refers to 'where' in the Module hierarchy this lives
-sealed trait Binding {
- def location: Option[BaseModule]
-}
-// Top-level binding representing hardware, not a pointer to another binding (like ChildBinding)
-sealed trait TopBinding extends Binding
-
-// Constrained-ness refers to whether 'bound by Module boundaries'
-// An unconstrained binding, like a literal, can be read by everyone
-sealed trait UnconstrainedBinding extends TopBinding {
- def location: Option[BaseModule] = None
-}
-// A constrained binding can only be read/written by specific modules
-// Location will track where this Module is, and the bound object can be referenced in FIRRTL
-sealed trait ConstrainedBinding extends TopBinding {
- def enclosure: BaseModule
- def location: Option[BaseModule] = Some(enclosure)
-}
-
-// A binding representing a data that cannot be (re)assigned to.
-sealed trait ReadOnlyBinding extends TopBinding
-
-// TODO(twigg): Ops between unenclosed nodes can also be unenclosed
-// However, Chisel currently binds all op results to a module
-case class OpBinding(enclosure: RawModule) extends ConstrainedBinding with ReadOnlyBinding
-case class MemoryPortBinding(enclosure: RawModule) extends ConstrainedBinding
-case class PortBinding(enclosure: BaseModule) extends ConstrainedBinding
-case class RegBinding(enclosure: RawModule) extends ConstrainedBinding
-case class WireBinding(enclosure: RawModule) extends ConstrainedBinding
-
-case class ChildBinding(parent: Data) extends Binding {
- def location: Option[BaseModule] = parent.topBinding.location
-}
-/** Special binding for Vec.sample_element */
-case class SampleElementBinding[T <: Data](parent: Vec[T]) extends Binding {
- def location = parent.topBinding.location
-}
-// A DontCare element has a specific Binding, somewhat like a literal.
-// It is a source (RHS). It may only be connected/applied to sinks.
-case class DontCareBinding() extends UnconstrainedBinding
-
-sealed trait LitBinding extends UnconstrainedBinding with ReadOnlyBinding
-// Literal binding attached to a element that is not part of a Bundle.
-case class ElementLitBinding(litArg: LitArg) extends LitBinding
-// Literal binding attached to the root of a Bundle, containing literal values of its children.
-case class BundleLitBinding(litMap: Map[Data, LitArg]) extends LitBinding
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala
deleted file mode 100644
index b18b27e5..00000000
--- a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala
+++ /dev/null
@@ -1,1808 +0,0 @@
-// See LICENSE for license details.
-
-package chisel3.core
-
-import scala.language.experimental.macros
-import collection.mutable
-
-import chisel3.internal._
-import chisel3.internal.Builder.{pushCommand, pushOp}
-import chisel3.internal.firrtl._
-import chisel3.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, SourceInfoTransform, SourceInfoWhiteboxTransform,
- UIntTransform}
-import chisel3.internal.firrtl.PrimOp._
-
-// scalastyle:off method.name line.size.limit file.size.limit
-
-/** Element is a leaf data type: it cannot contain other [[Data]] objects. Example uses are for representing primitive
- * data types, like integers and bits.
- *
- * @define coll element
- */
-abstract class Element extends Data {
- private[chisel3] final def allElements: Seq[Element] = Seq(this)
- def widthKnown: Boolean = width.known
- def name: String = getRef.name
-
- private[chisel3] override def bind(target: Binding, parentDirection: SpecifiedDirection) {
- binding = target
- val resolvedDirection = SpecifiedDirection.fromParent(parentDirection, specifiedDirection)
- direction = ActualDirection.fromSpecified(resolvedDirection)
- }
-
- private[core] override def topBindingOpt: Option[TopBinding] = super.topBindingOpt match {
- // Translate Bundle lit bindings to Element lit bindings
- case Some(BundleLitBinding(litMap)) => litMap.get(this) match {
- case Some(litArg) => Some(ElementLitBinding(litArg))
- case _ => Some(DontCareBinding())
- }
- case topBindingOpt => topBindingOpt
- }
-
- private[core] def litArgOption: Option[LitArg] = topBindingOpt match {
- case Some(ElementLitBinding(litArg)) => Some(litArg)
- case _ => None
- }
-
- override def litOption: Option[BigInt] = litArgOption.map(_.num)
- private[core] def litIsForcedWidth: Option[Boolean] = litArgOption.map(_.forcedWidth)
-
- // provide bits-specific literal handling functionality here
- override private[chisel3] def ref: Arg = topBindingOpt match {
- case Some(ElementLitBinding(litArg)) => litArg
- case Some(BundleLitBinding(litMap)) => litMap.get(this) match {
- case Some(litArg) => litArg
- case _ => throwException(s"internal error: DontCare should be caught before getting ref")
- }
- case _ => super.ref
- }
-
- private[core] def legacyConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit = {
- // If the source is a DontCare, generate a DefInvalid for the sink,
- // otherwise, issue a Connect.
- if (that == DontCare) {
- pushCommand(DefInvalid(sourceInfo, Node(this)))
- } else {
- pushCommand(Connect(sourceInfo, Node(this), that.ref))
- }
- }
-}
-
-/** Exists to unify common interfaces of [[Bits]] and [[Reset]].
- *
- * @note This is a workaround because macros cannot override abstract methods.
- */
-private[chisel3] sealed trait ToBoolable extends Element {
-
- /** Casts this $coll to a [[Bool]]
- *
- * @note The width must be known and equal to 1
- */
- final def asBool(): Bool = macro SourceInfoWhiteboxTransform.noArg
-
- /** @group SourceInfoTransformMacro */
- def do_asBool(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool
-
- /** Casts this $coll to a [[Bool]]
- *
- * @note The width must be known and equal to 1
- */
- final def toBool(): Bool = macro SourceInfoWhiteboxTransform.noArg
-
- /** @group SourceInfoTransformMacro */
- def do_toBool(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool
-}
-
-/** A data type for values represented by a single bitvector. This provides basic bitwise operations.
- *
- * @groupdesc Bitwise Bitwise hardware operators
- * @define coll [[Bits]]
- * @define sumWidthInt @note The width of the returned $coll is `width of this` + `that`.
- * @define sumWidth @note The width of the returned $coll is `width of this` + `width of that`.
- * @define unchangedWidth @note The width of the returned $coll is unchanged, i.e., the `width of this`.
- */
-sealed abstract class Bits(private[chisel3] val width: Width) extends Element with ToBoolable { //scalastyle:off number.of.methods
- // 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
-
- // Only used for in a few cases, hopefully to be removed
- private[core] def cloneTypeWidth(width: Width): this.type
-
- def cloneType: this.type = cloneTypeWidth(width)
-
- /** Tail operator
- *
- * @param n the number of bits to remove
- * @return This $coll with the `n` most significant bits removed.
- * @group Bitwise
- */
- final def tail(n: Int): UInt = macro SourceInfoTransform.nArg
-
- /** Head operator
- *
- * @param n the number of bits to take
- * @return The `n` most significant bits of this $coll
- * @group Bitwise
- */
- final def head(n: Int): UInt = macro SourceInfoTransform.nArg
-
- /** @group SourceInfoTransformMacro */
- def do_tail(n: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): 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)
- }
-
- /** @group SourceInfoTransformMacro */
- def do_head(n: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): 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 $coll as a [[Bool]], statically addressed.
- *
- * @param x an index
- * @return the specified bit
- */
- final def apply(x: BigInt): Bool = macro SourceInfoTransform.xArg
-
- /** @group SourceInfoTransformMacro */
- final def do_apply(x: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = {
- if (x < 0) {
- Builder.error(s"Negative bit indices are illegal (got $x)")
- }
- // This preserves old behavior while a more more consistent API is under debate
- // See https://github.com/freechipsproject/chisel3/issues/867
- litOption.map { value =>
- (((value >> castToInt(x, "Index")) & 1) == 1).asBool
- }.getOrElse {
- requireIsHardware(this, "bits to be indexed")
- pushOp(DefPrim(sourceInfo, Bool(), BitsExtractOp, this.ref, ILit(x), ILit(x)))
- }
- }
-
- /** Returns the specified bit on this $coll as a [[Bool]], statically addressed.
- *
- * @param x an index
- * @return the specified bit
- * @note convenience method allowing direct use of [[scala.Int]] without implicits
- */
- final def apply(x: Int): Bool = macro SourceInfoTransform.xArg
-
- /** @group SourceInfoTransformMacro */
- final def do_apply(x: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = apply(BigInt(x))
-
- /** Returns the specified bit on this wire as a [[Bool]], dynamically addressed.
- *
- * @param x a hardware component whose value will be used for dynamic addressing
- * @return the specified bit
- */
- final def apply(x: UInt): Bool = macro SourceInfoTransform.xArg
-
- /** @group SourceInfoTransformMacro */
- final def do_apply(x: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = {
- val theBits = this >> x
- theBits(0)
- }
-
- /** Returns a subset of bits on this $coll from `hi` to `lo` (inclusive), statically addressed.
- *
- * @example
- * {{{
- * myBits = 0x5 = 0b101
- * myBits(1,0) => 0b01 // extracts the two least significant bits
- * }}}
- * @param x the high bit
- * @param y the low bit
- * @return a hardware component contain the requested bits
- */
- final def apply(x: Int, y: Int): UInt = macro SourceInfoTransform.xyArg
-
- /** @group SourceInfoTransformMacro */
- final def do_apply(x: Int, y: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = {
- if (x < y || y < 0) {
- Builder.error(s"Invalid bit range ($x,$y)")
- }
- val w = x - y + 1
- // This preserves old behavior while a more more consistent API is under debate
- // See https://github.com/freechipsproject/chisel3/issues/867
- litOption.map { value =>
- ((value >> y) & ((BigInt(1) << w) - 1)).asUInt(w.W)
- }.getOrElse {
- requireIsHardware(this, "bits to be sliced")
- 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?
- /** Returns a subset of bits on this $coll from `hi` to `lo` (inclusive), statically addressed.
- *
- * @example
- * {{{
- * myBits = 0x5 = 0b101
- * myBits(1,0) => 0b01 // extracts the two least significant bits
- * }}}
- * @param x the high bit
- * @param y the low bit
- * @return a hardware component contain the requested bits
- */
- final def apply(x: BigInt, y: BigInt): UInt = macro SourceInfoTransform.xyArg
-
- /** @group SourceInfoTransformMacro */
- final def do_apply(x: BigInt, y: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt =
- apply(castToInt(x, "High index"), castToInt(y, "Low index"))
-
- private[core] def unop[T <: Data](sourceInfo: SourceInfo, dest: T, op: PrimOp): T = {
- requireIsHardware(this, "bits operated on")
- pushOp(DefPrim(sourceInfo, dest, op, this.ref))
- }
- private[core] def binop[T <: Data](sourceInfo: SourceInfo, dest: T, op: PrimOp, other: BigInt): T = {
- requireIsHardware(this, "bits operated on")
- pushOp(DefPrim(sourceInfo, dest, op, this.ref, ILit(other)))
- }
- private[core] def binop[T <: Data](sourceInfo: SourceInfo, dest: T, op: PrimOp, other: Bits): T = {
- requireIsHardware(this, "bits operated on")
- requireIsHardware(other, "bits operated on")
- pushOp(DefPrim(sourceInfo, dest, op, this.ref, other.ref))
- }
- private[core] def compop(sourceInfo: SourceInfo, op: PrimOp, other: Bits): Bool = {
- requireIsHardware(this, "bits operated on")
- requireIsHardware(other, "bits operated on")
- pushOp(DefPrim(sourceInfo, Bool(), op, this.ref, other.ref))
- }
- private[core] def redop(sourceInfo: SourceInfo, op: PrimOp): Bool = {
- requireIsHardware(this, "bits operated on")
- pushOp(DefPrim(sourceInfo, Bool(), op, this.ref))
- }
-
- /** Pad operator
- *
- * @param that the width to pad to
- * @return this @coll zero padded up to width `that`. If `that` is less than the width of the original component,
- * this method returns the original component.
- * @note For [[SInt]]s only, this will do sign extension.
- * @group Bitwise
- */
- final def pad(that: Int): this.type = macro SourceInfoTransform.thatArg
-
- /** @group SourceInfoTransformMacro */
- def do_pad(that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): this.type = this.width match {
- case KnownWidth(w) if w >= that => this
- case _ => binop(sourceInfo, cloneTypeWidth(this.width max Width(that)), PadOp, that)
- }
-
- /** Bitwise inversion operator
- *
- * @return this $coll with each bit inverted
- * @group Bitwise
- */
- final def unary_~ (): Bits = macro SourceInfoWhiteboxTransform.noArg
-
- /** @group SourceInfoTransformMacro */
- def do_unary_~ (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bits
-
- /** Static left shift operator
- *
- * @param that an amount to shift by
- * @return this $coll with `that` many zeros concatenated to its least significant end
- * $sumWidthInt
- * @group Bitwise
- */
- // REVIEW TODO: redundant
- // REVIEW TODO: should these return this.type or Bits?
- final def << (that: BigInt): Bits = macro SourceInfoWhiteboxTransform.thatArg
-
- /** @group SourceInfoTransformMacro */
- def do_<< (that: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bits
-
- /** Static left shift operator
- *
- * @param that an amount to shift by
- * @return this $coll with `that` many zeros concatenated to its least significant end
- * $sumWidthInt
- * @group Bitwise
- */
- final def << (that: Int): Bits = macro SourceInfoWhiteboxTransform.thatArg
-
- /** @group SourceInfoTransformMacro */
- def do_<< (that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bits
-
- /** Dynamic left shift operator
- *
- * @param that a hardware component
- * @return this $coll dynamically shifted left by `that` many places, shifting in zeros from the right
- * @note The width of the returned $coll is `width of this + pow(2, width of that) - 1`.
- * @group Bitwise
- */
- final def << (that: UInt): Bits = macro SourceInfoWhiteboxTransform.thatArg
-
- /** @group SourceInfoTransformMacro */
- def do_<< (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bits
-
- /** Static right shift operator
- *
- * @param that an amount to shift by
- * @return this $coll with `that` many least significant bits truncated
- * $unchangedWidth
- * @group Bitwise
- */
- // REVIEW TODO: redundant
- final def >> (that: BigInt): Bits = macro SourceInfoWhiteboxTransform.thatArg
-
- /** @group SourceInfoTransformMacro */
- def do_>> (that: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bits
-
- /** Static right shift operator
- *
- * @param that an amount to shift by
- * @return this $coll with `that` many least significant bits truncated
- * $unchangedWidth
- * @group Bitwise
- */
- final def >> (that: Int): Bits = macro SourceInfoWhiteboxTransform.thatArg
-
- /** @group SourceInfoTransformMacro */
- def do_>> (that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bits
-
- /** Dynamic right shift operator
- *
- * @param that a hardware component
- * @return this $coll dynamically shifted right by the value of `that` component, inserting zeros into the most
- * significant bits.
- * $unchangedWidth
- * @group Bitwise
- */
- final def >> (that: UInt): Bits = macro SourceInfoWhiteboxTransform.thatArg
-
- /** @group SourceInfoTransformMacro */
- def do_>> (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bits
-
- /** Returns the contents of this wire as a [[scala.collection.Seq]] of [[Bool]]. */
- final def toBools(): Seq[Bool] = macro SourceInfoTransform.noArg
-
- /** @group SourceInfoTransformMacro */
- @chiselRuntimeDeprecated
- @deprecated("Use asBools instead", "3.2")
- def do_toBools(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Seq[Bool] = do_asBools
-
- /** Returns the contents of this wire as a [[scala.collection.Seq]] of [[Bool]]. */
- final def asBools(): Seq[Bool] = macro SourceInfoTransform.noArg
-
- /** @group SourceInfoTransformMacro */
- def do_asBools(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Seq[Bool] =
- Seq.tabulate(this.getWidth)(i => this(i))
-
- /** Reinterpret this $coll as an [[SInt]]
- *
- * @note The arithmetic value is not preserved if the most-significant bit is set. For example, a [[UInt]] of
- * width 3 and value 7 (0b111) would become an [[SInt]] of width 3 and value -1.
- */
- final def asSInt(): SInt = macro SourceInfoTransform.noArg
-
- /** @group SourceInfoTransformMacro */
- def do_asSInt(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt
-
- /** Reinterpret this $coll as a [[FixedPoint]].
- *
- * @note The value is not guaranteed to be preserved. For example, a [[UInt]] of width 3 and value 7 (0b111) would
- * become a [[FixedPoint]] with value -1. The interpretation of the number is also affected by the specified binary
- * point. '''Caution is advised!'''
- */
- final def asFixedPoint(that: BinaryPoint): FixedPoint = macro SourceInfoTransform.thatArg
-
- /** @group SourceInfoTransformMacro */
- def do_asFixedPoint(that: BinaryPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = {
- throwException(s"Cannot call .asFixedPoint on $this")
- }
-
- /** Reinterpret cast to Bits. */
- @chiselRuntimeDeprecated
- @deprecated("Use asUInt, which does the same thing but returns a more concrete type", "chisel3")
- final def asBits(implicit compileOptions: CompileOptions): Bits = {
- implicit val sourceInfo = DeprecatedSourceInfo
- do_asUInt
- }
-
- @chiselRuntimeDeprecated
- @deprecated("Use asSInt, which makes the reinterpret cast more explicit", "chisel3")
- final def toSInt(implicit compileOptions: CompileOptions): SInt = {
- implicit val sourceInfo = DeprecatedSourceInfo
- do_asSInt
- }
-
- @chiselRuntimeDeprecated
- @deprecated("Use asUInt, which makes the reinterpret cast more explicit", "chisel3")
- final def toUInt(implicit compileOptions: CompileOptions): UInt = {
- implicit val sourceInfo = DeprecatedSourceInfo
- do_asUInt
- }
-
- final def do_asBool(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = {
- width match {
- case KnownWidth(1) => this(0)
- case _ => throwException(s"can't covert ${this.getClass.getSimpleName}$width to Bool")
- }
- }
-
- @chiselRuntimeDeprecated
- @deprecated("Use asBool instead", "3.2")
- final def do_toBool(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = do_asBool
-
- /** Concatenation operator
- *
- * @param that a hardware component
- * @return this $coll concatenated to the most significant end of `that`
- * $sumWidth
- * @group Bitwise
- */
- final def ## (that: Bits): UInt = macro SourceInfoTransform.thatArg
-
- /** @group SourceInfoTransformMacro */
- def do_## (that: Bits)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = {
- val w = this.width + that.width
- pushOp(DefPrim(sourceInfo, UInt(w), ConcatOp, this.ref, that.ref))
- }
-
- /** Default print as [[Decimal]] */
- final def toPrintable: Printable = Decimal(this)
-
- protected final def validateShiftAmount(x: Int): Int = {
- if (x < 0)
- Builder.error(s"Negative shift amounts are illegal (got $x)")
- x
- }
-}
-
-// REVIEW TODO: Further discussion needed on what Num actually is.
-/** Abstract trait defining operations available on numeric-like hardware data types.
- *
- * @tparam T the underlying type of the number
- * @groupdesc Arithmetic Arithmetic hardware operators
- * @groupdesc Comparison Comparison hardware operators
- * @groupdesc Logical Logical hardware operators
- * @define coll numeric-like type
- * @define numType hardware type
- * @define canHaveHighCost can result in significant cycle time and area costs
- * @define canGenerateA This method generates a
- * @define singleCycleMul @note $canGenerateA fully combinational multiplier which $canHaveHighCost.
- * @define singleCycleDiv @note $canGenerateA fully combinational divider which $canHaveHighCost.
- * @define maxWidth @note The width of the returned $numType is `max(width of this, width of that)`.
- * @define maxWidthPlusOne @note The width of the returned $numType is `max(width of this, width of that) + 1`.
- * @define sumWidth @note The width of the returned $numType is `width of this` + `width of that`.
- * @define unchangedWidth @note The width of the returned $numType is unchanged, i.e., the `width of this`.
- */
-abstract trait Num[T <: Data] {
- self: Num[T] =>
- // def << (b: T): T
- // def >> (b: T): T
- //def unary_-(): T
-
- // REVIEW TODO: double check ops conventions against FIRRTL
-
- /** Addition operator
- *
- * @param that a $numType
- * @return the sum of this $coll and `that`
- * $maxWidthPlusOne
- * @group Arithmetic
- */
- final def + (that: T): T = macro SourceInfoTransform.thatArg
-
- /** @group SourceInfoTransformMacro */
- def do_+ (that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T
-
- /** Multiplication operator
- *
- * @param that a $numType
- * @return the product of this $coll and `that`
- * $sumWidth
- * $singleCycleMul
- * @group Arithmetic
- */
- final def * (that: T): T = macro SourceInfoTransform.thatArg
-
- /** @group SourceInfoTransformMacro */
- def do_* (that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T
-
- /** Division operator
- *
- * @param that a $numType
- * @return the quotient of this $coll divided by `that`
- * $singleCycleDiv
- * @todo full rules
- * @group Arithmetic
- */
- final def / (that: T): T = macro SourceInfoTransform.thatArg
-
- /** @group SourceInfoTransformMacro */
- def do_/ (that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T
-
- /** Modulo operator
- *
- * @param that a $numType
- * @return the remainder of this $coll divided by `that`
- * $singleCycleDiv
- * @group Arithmetic
- */
- final def % (that: T): T = macro SourceInfoTransform.thatArg
-
- /** @group SourceInfoTransformMacro */
- def do_% (that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T
-
- /** Subtraction operator
- *
- * @param that a $numType
- * @return the difference of this $coll less `that`
- * $maxWidthPlusOne
- * @group Arithmetic
- */
- final def - (that: T): T = macro SourceInfoTransform.thatArg
-
- /** @group SourceInfoTransformMacro */
- def do_- (that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T
-
- /** Less than operator
- *
- * @param that a $numType
- * @return a hardware [[Bool]] asserted if this $coll is less than `that`
- * @group Comparison
- */
- final def < (that: T): Bool = macro SourceInfoTransform.thatArg
-
- /** @group SourceInfoTransformMacro */
- def do_< (that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool
-
- /** Less than or equal to operator
- *
- * @param that a $numType
- * @return a hardware [[Bool]] asserted if this $coll is less than or equal to `that`
- * @group Comparison
- */
- final def <= (that: T): Bool = macro SourceInfoTransform.thatArg
-
- /** @group SourceInfoTransformMacro */
- def do_<= (that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool
-
- /** Greater than operator
- *
- * @param that a hardware component
- * @return a hardware [[Bool]] asserted if this $coll is greater than `that`
- * @group Comparison
- */
- final def > (that: T): Bool = macro SourceInfoTransform.thatArg
-
- /** @group SourceInfoTransformMacro */
- def do_> (that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool
-
- /** Greater than or equal to operator
- *
- * @param that a hardware component
- * @return a hardware [[Bool]] asserted if this $coll is greather than or equal to `that`
- * @group Comparison
- */
- final def >= (that: T): Bool = macro SourceInfoTransform.thatArg
-
- /** @group SourceInfoTransformMacro */
- def do_>= (that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool
-
- /** Absolute value operator
- *
- * @return a $numType with a value equal to the absolute value of this $coll
- * $unchangedWidth
- * @group Arithmetic
- */
- final def abs(): T = macro SourceInfoTransform.noArg
-
- /** @group SourceInfoTransformMacro */
- def do_abs(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T
-
- /** Minimum operator
- *
- * @param that a hardware $coll
- * @return a $numType with a value equal to the mimimum value of this $coll and `that`
- * $maxWidth
- * @group Arithmetic
- */
- final def min(that: T): T = macro SourceInfoTransform.thatArg
-
- /** @group SourceInfoTransformMacro */
- def do_min(that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T =
- Mux(this < that, this.asInstanceOf[T], that)
-
- /** Maximum operator
- *
- * @param that a $numType
- * @return a $numType with a value equal to the mimimum value of this $coll and `that`
- * $maxWidth
- * @group Arithmetic
- */
- final def max(that: T): T = macro SourceInfoTransform.thatArg
-
- /** @group SourceInfoTransformMacro */
- def do_max(that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): 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.
- *
- * @define coll [[UInt]]
- * @define numType $coll
- * @define expandingWidth @note The width of the returned $coll is `width of this` + `1`.
- * @define constantWidth @note The width of the returned $coll is unchanged, i.e., `width of this`.
- */
-sealed class UInt private[core] (width: Width) extends Bits(width) with Num[UInt] {
- override def toString: String = {
- val bindingString = litOption match {
- case Some(value) => s"($value)"
- case _ => bindingToString
- }
- s"UInt$width$bindingString"
- }
-
- private[core] override def typeEquivalent(that: Data): Boolean =
- that.isInstanceOf[UInt] && this.width == that.width
-
- private[core] override def cloneTypeWidth(w: Width): this.type =
- new UInt(w).asInstanceOf[this.type]
-
- // TODO: refactor to share documentation with Num or add independent scaladoc
- /** Unary negation (expanding width)
- *
- * @return a $coll equal to zero minus this $coll
- * $constantWidth
- * @group Arithmetic
- */
- final def unary_- (): UInt = macro SourceInfoTransform.noArg
-
- /** Unary negation (constant width)
- *
- * @return a $coll equal to zero minus this $coll shifted right by one.
- * $constantWidth
- * @group Arithmetic
- */
- final def unary_-% (): UInt = macro SourceInfoTransform.noArg
-
- /** @group SourceInfoTransformMacro */
- def do_unary_- (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) : UInt = 0.U - this
- /** @group SourceInfoTransformMacro */
- def do_unary_-% (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = 0.U -% this
-
- override def do_+ (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = this +% that
- override def do_- (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = this -% that
- override def do_/ (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt =
- binop(sourceInfo, UInt(this.width), DivideOp, that)
- override def do_% (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt =
- binop(sourceInfo, UInt(this.width), RemOp, that)
- override def do_* (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt =
- binop(sourceInfo, UInt(this.width + that.width), TimesOp, that)
-
- /** Multiplication operator
- *
- * @param that a hardware [[SInt]]
- * @return the product of this $coll and `that`
- * $sumWidth
- * $singleCycleMul
- * @group Arithmetic
- */
- final def * (that: SInt): SInt = macro SourceInfoTransform.thatArg
- /** @group SourceInfoTransformMacro */
- def do_* (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = that * this
-
- /** Addition operator (expanding width)
- *
- * @param that a hardware $coll
- * @return the sum of this $coll and `that`
- * $maxWidthPlusOne
- * @group Arithmetic
- */
- final def +& (that: UInt): UInt = macro SourceInfoTransform.thatArg
-
- /** Addition operator (constant width)
- *
- * @param that a hardware $coll
- * @return the sum of this $coll and `that`
- * $maxWidth
- * @group Arithmetic
- */
- final def +% (that: UInt): UInt = macro SourceInfoTransform.thatArg
-
- /** Subtraction operator (increasing width)
- *
- * @param that a hardware $coll
- * @return the difference of this $coll less `that`
- * $maxWidthPlusOne
- * @group Arithmetic
- */
- final def -& (that: UInt): UInt = macro SourceInfoTransform.thatArg
-
- /** Subtraction operator (constant width)
- *
- * @param that a hardware $coll
- * @return the difference of this $coll less `that`
- * $maxWidth
- * @group Arithmetic
- */
- final def -% (that: UInt): UInt = macro SourceInfoTransform.thatArg
-
- /** @group SourceInfoTransformMacro */
- def do_+& (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt =
- binop(sourceInfo, UInt((this.width max that.width) + 1), AddOp, that)
- /** @group SourceInfoTransformMacro */
- def do_+% (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt =
- (this +& that).tail(1)
- /** @group SourceInfoTransformMacro */
- def do_-& (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt =
- (this subtractAsSInt that).asUInt
- /** @group SourceInfoTransformMacro */
- def do_-% (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt =
- (this subtractAsSInt that).tail(1)
-
- /** Bitwise and operator
- *
- * @param that a hardware $coll
- * @return the bitwise and of this $coll and `that`
- * $maxWidth
- * @group Bitwise
- */
- final def & (that: UInt): UInt = macro SourceInfoTransform.thatArg
-
- /** Bitwise or operator
- *
- * @param that a hardware $coll
- * @return the bitwise or of this $coll and `that`
- * $maxWidth
- * @group Bitwise
- */
- final def | (that: UInt): UInt = macro SourceInfoTransform.thatArg
-
- /** Bitwise exclusive or (xor) operator
- *
- * @param that a hardware $coll
- * @return the bitwise xor of this $coll and `that`
- * $maxWidth
- * @group Bitwise
- */
- final def ^ (that: UInt): UInt = macro SourceInfoTransform.thatArg
-
- // override def abs: UInt = macro SourceInfoTransform.noArg
- def do_abs(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = this
-
- /** @group SourceInfoTransformMacro */
- def do_& (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt =
- binop(sourceInfo, UInt(this.width max that.width), BitAndOp, that)
- /** @group SourceInfoTransformMacro */
- def do_| (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt =
- binop(sourceInfo, UInt(this.width max that.width), BitOrOp, that)
- /** @group SourceInfoTransformMacro */
- def do_^ (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt =
- binop(sourceInfo, UInt(this.width max that.width), BitXorOp, that)
-
- /** @group SourceInfoTransformMacro */
- def do_unary_~ (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt =
- unop(sourceInfo, UInt(width = width), BitNotOp)
-
- // REVIEW TODO: Can these be defined on Bits?
- /** Or reduction operator
- *
- * @return a hardware [[Bool]] resulting from every bit of this $coll or'd together
- * @group Bitwise
- */
- final def orR(): Bool = macro SourceInfoTransform.noArg
-
- /** And reduction operator
- *
- * @return a hardware [[Bool]] resulting from every bit of this $coll and'd together
- * @group Bitwise
- */
- final def andR(): Bool = macro SourceInfoTransform.noArg
-
- /** Exclusive or (xor) reduction operator
- *
- * @return a hardware [[Bool]] resulting from every bit of this $coll xor'd together
- * @group Bitwise
- */
- final def xorR(): Bool = macro SourceInfoTransform.noArg
-
- /** @group SourceInfoTransformMacro */
- def do_orR(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = this =/= 0.U
- /** @group SourceInfoTransformMacro */
- def do_andR(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = width match {
- // Generate a simpler expression if the width is known
- case KnownWidth(w) => this === ((BigInt(1) << w) - 1).U
- case UnknownWidth() => ~this === 0.U
- }
- /** @group SourceInfoTransformMacro */
- def do_xorR(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = redop(sourceInfo, XorReduceOp)
-
- override def do_< (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, LessOp, that)
- override def do_> (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, GreaterOp, that)
- override def do_<= (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, LessEqOp, that)
- override def do_>= (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, GreaterEqOp, that)
-
- @chiselRuntimeDeprecated
- @deprecated("Use '=/=', which avoids potential precedence problems", "chisel3")
- final def != (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = this =/= that
-
- /** Dynamic not equals operator
- *
- * @param that a hardware $coll
- * @return a hardware [[Bool]] asserted if this $coll is not equal to `that`
- * @group Comparison
- */
- final def =/= (that: UInt): Bool = macro SourceInfoTransform.thatArg
-
- /** Dynamic equals operator
- *
- * @param that a hardware $coll
- * @return a hardware [[Bool]] asserted if this $coll is equal to `that`
- * @group Comparison
- */
- final def === (that: UInt): Bool = macro SourceInfoTransform.thatArg
-
- /** @group SourceInfoTransformMacro */
- def do_=/= (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, NotEqualOp, that)
- /** @group SourceInfoTransformMacro */
- def do_=== (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, EqualOp, that)
-
- /** Unary not
- *
- * @return a hardware [[Bool]] asserted if this $coll equals zero
- * @group Bitwise
- */
- final def unary_! () : Bool = macro SourceInfoTransform.noArg
-
- /** @group SourceInfoTransformMacro */
- def do_unary_! (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) : Bool = this === 0.U(1.W)
-
- override def do_<< (that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt =
- binop(sourceInfo, UInt(this.width + that), ShiftLeftOp, validateShiftAmount(that))
- override def do_<< (that: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt =
- this << castToInt(that, "Shift amount")
- override def do_<< (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt =
- binop(sourceInfo, UInt(this.width.dynamicShiftLeft(that.width)), DynamicShiftLeftOp, that)
- override def do_>> (that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt =
- binop(sourceInfo, UInt(this.width.shiftRight(that)), ShiftRightOp, validateShiftAmount(that))
- override def do_>> (that: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt =
- this >> castToInt(that, "Shift amount")
- override def do_>> (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt =
- binop(sourceInfo, UInt(this.width), DynamicShiftRightOp, that)
-
- /** Conditionally set or clear a bit
- *
- * @param off a dynamic offset
- * @param dat set if true, clear if false
- * @return a hrdware $coll with bit `off` set or cleared based on the value of `dat`
- * $unchangedWidth
- */
- final def bitSet(off: UInt, dat: Bool): UInt = macro UIntTransform.bitset
-
- /** @group SourceInfoTransformMacro */
- def do_bitSet(off: UInt, dat: Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = {
- val bit = 1.U(1.W) << off
- Mux(dat, this | bit, ~(~this | bit))
- }
-
- // TODO: this eventually will be renamed as toSInt, once the existing toSInt
- // completes its deprecation phase.
- /** Zero extend as [[SInt]]
- *
- * @return an [[SInt]] equal to this $coll with an additional zero in its most significant bit
- * @note The width of the returned [[SInt]] is `width of this` + `1`.
- */
- final def zext(): SInt = macro SourceInfoTransform.noArg
- /** @group SourceInfoTransformMacro */
- def do_zext(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt =
- pushOp(DefPrim(sourceInfo, SInt(width + 1), ConvertOp, ref))
-
- override def do_asSInt(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt =
- pushOp(DefPrim(sourceInfo, SInt(width), AsSIntOp, ref))
- override def do_asUInt(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = this
- override def do_asFixedPoint(binaryPoint: BinaryPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = {
- binaryPoint match {
- case KnownBinaryPoint(value) =>
- val iLit = ILit(value)
- pushOp(DefPrim(sourceInfo, FixedPoint(width, binaryPoint), AsFixedPointOp, ref, iLit))
- case _ =>
- throwException(s"cannot call $this.asFixedPoint(binaryPoint=$binaryPoint), you must specify a known binaryPoint")
- }
- }
-
- private[core] override def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo,
- compileOptions: CompileOptions): Unit = {
- this := that.asUInt
- }
-
- private def subtractAsSInt(that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt =
- binop(sourceInfo, SInt((this.width max that.width) + 1), SubOp, that)
-}
-
-// This is currently a factory because both Bits and UInt inherit it.
-trait UIntFactory {
- /** Create a UInt type with inferred width. */
- def apply(): UInt = apply(Width())
- /** Create a UInt port with specified width. */
- def apply(width: Width): UInt = new UInt(width)
-
- /** Create a UInt literal with specified width. */
- protected[chisel3] def Lit(value: BigInt, width: Width): UInt = {
- val lit = ULit(value, width)
- val result = new UInt(lit.width)
- // Bind result to being an Literal
- lit.bindLitArg(result)
- }
-
- /** Create a UInt with the specified range */
- def apply(range: Range): UInt = {
- apply(range.getWidth)
- }
- /** Create a UInt with the specified range */
- def apply(range: (NumericBound[Int], NumericBound[Int])): UInt = {
- apply(KnownUIntRange(range._1, range._2))
- }
-}
-
-object UInt extends UIntFactory
-object Bits extends UIntFactory
-
-/** A data type for signed integers, represented as a binary bitvector. Defines arithmetic operations between other
- * integer types.
- *
- * @define coll [[SInt]]
- * @define numType $coll
- * @define expandingWidth @note The width of the returned $coll is `width of this` + `1`.
- * @define constantWidth @note The width of the returned $coll is unchanged, i.e., `width of this`.
- */
-sealed class SInt private[core] (width: Width) extends Bits(width) with Num[SInt] {
- override def toString: String = {
- val bindingString = litOption match {
- case Some(value) => s"($value)"
- case _ => bindingToString
- }
- s"SInt$width$bindingString"
- }
-
- private[core] override def typeEquivalent(that: Data): Boolean =
- this.getClass == that.getClass && this.width == that.width // TODO: should this be true for unspecified widths?
-
- private[core] override def cloneTypeWidth(w: Width): this.type =
- new SInt(w).asInstanceOf[this.type]
-
- /** Unary negation (expanding width)
- *
- * @return a hardware $coll equal to zero minus this $coll
- * $constantWidth
- * @group Arithmetic
- */
- final def unary_- (): SInt = macro SourceInfoTransform.noArg
-
- /** Unary negation (constant width)
- *
- * @return a hardware $coll equal to zero minus `this` shifted right by one
- * $constantWidth
- * @group Arithmetic
- */
- final def unary_-% (): SInt = macro SourceInfoTransform.noArg
-
- /** @group SourceInfoTransformMacro */
- def unary_- (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = 0.S - this
- /** @group SourceInfoTransformMacro */
- def unary_-% (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = 0.S -% this
-
- /** add (default - no growth) operator */
- override def do_+ (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt =
- this +% that
- /** subtract (default - no growth) operator */
- override def do_- (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt =
- this -% that
- override def do_* (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt =
- binop(sourceInfo, SInt(this.width + that.width), TimesOp, that)
- override def do_/ (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt =
- binop(sourceInfo, SInt(this.width), DivideOp, that)
- override def do_% (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt =
- binop(sourceInfo, SInt(this.width), RemOp, that)
-
- /** Multiplication operator
- *
- * @param that a hardware $coll
- * @return the product of this $coll and `that`
- * $sumWidth
- * $singleCycleMul
- * @group Arithmetic
- */
- final def * (that: UInt): SInt = macro SourceInfoTransform.thatArg
- /** @group SourceInfoTransformMacro */
- def do_* (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = {
- val thatToSInt = that.zext()
- val result = binop(sourceInfo, SInt(this.width + thatToSInt.width), TimesOp, thatToSInt)
- result.tail(1).asSInt
- }
-
- /** Addition operator (expanding width)
- *
- * @param that a hardware $coll
- * @return the sum of this $coll and `that`
- * $maxWidthPlusOne
- * @group Arithmetic
- */
- final def +& (that: SInt): SInt = macro SourceInfoTransform.thatArg
-
- /** Addition operator (constant width)
- *
- * @param that a hardware $coll
- * @return the sum of this $coll and `that` shifted right by one
- * $maxWidth
- * @group Arithmetic
- */
- final def +% (that: SInt): SInt = macro SourceInfoTransform.thatArg
-
- /** Subtraction operator (increasing width)
- *
- * @param that a hardware $coll
- * @return the difference of this $coll less `that`
- * $maxWidthPlusOne
- * @group Arithmetic
- */
- final def -& (that: SInt): SInt = macro SourceInfoTransform.thatArg
-
- /** Subtraction operator (constant width)
- *
- * @param that a hardware $coll
- * @return the difference of this $coll less `that` shifted right by one
- * $maxWidth
- * @group Arithmetic
- */
- final def -% (that: SInt): SInt = macro SourceInfoTransform.thatArg
-
- /** @group SourceInfoTransformMacro */
- def do_+& (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt =
- binop(sourceInfo, SInt((this.width max that.width) + 1), AddOp, that)
- /** @group SourceInfoTransformMacro */
- def do_+% (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt =
- (this +& that).tail(1).asSInt
- /** @group SourceInfoTransformMacro */
- def do_-& (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt =
- binop(sourceInfo, SInt((this.width max that.width) + 1), SubOp, that)
- /** @group SourceInfoTransformMacro */
- def do_-% (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt =
- (this -& that).tail(1).asSInt
-
- /** Bitwise and operator
- *
- * @param that a hardware $coll
- * @return the bitwise and of this $coll and `that`
- * $maxWidth
- * @group Bitwise
- */
- final def & (that: SInt): SInt = macro SourceInfoTransform.thatArg
-
- /** Bitwise or operator
- *
- * @param that a hardware $coll
- * @return the bitwise or of this $coll and `that`
- * $maxWidth
- * @group Bitwise
- */
- final def | (that: SInt): SInt = macro SourceInfoTransform.thatArg
-
- /** Bitwise exclusive or (xor) operator
- *
- * @param that a hardware $coll
- * @return the bitwise xor of this $coll and `that`
- * $maxWidth
- * @group Bitwise
- */
- final def ^ (that: SInt): SInt = macro SourceInfoTransform.thatArg
-
- /** @group SourceInfoTransformMacro */
- def do_& (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt =
- binop(sourceInfo, UInt(this.width max that.width), BitAndOp, that).asSInt
- /** @group SourceInfoTransformMacro */
- def do_| (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt =
- binop(sourceInfo, UInt(this.width max that.width), BitOrOp, that).asSInt
- /** @group SourceInfoTransformMacro */
- def do_^ (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt =
- binop(sourceInfo, UInt(this.width max that.width), BitXorOp, that).asSInt
-
- /** @group SourceInfoTransformMacro */
- def do_unary_~ (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt =
- unop(sourceInfo, UInt(width = width), BitNotOp).asSInt
-
- override def do_< (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, LessOp, that)
- override def do_> (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, GreaterOp, that)
- override def do_<= (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, LessEqOp, that)
- override def do_>= (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, GreaterEqOp, that)
-
- @chiselRuntimeDeprecated
- @deprecated("Use '=/=', which avoids potential precedence problems", "chisel3")
- final def != (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = this =/= that
-
- /** Dynamic not equals operator
- *
- * @param that a hardware $coll
- * @return a hardware [[Bool]] asserted if this $coll is not equal to `that`
- * @group Comparison
- */
- final def =/= (that: SInt): Bool = macro SourceInfoTransform.thatArg
-
- /** Dynamic equals operator
- *
- * @param that a hardware $coll
- * @return a hardware [[Bool]] asserted if this $coll is equal to `that`
- * @group Comparison
- */
- final def === (that: SInt): Bool = macro SourceInfoTransform.thatArg
-
- /** @group SourceInfoTransformMacro */
- def do_=/= (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, NotEqualOp, that)
- /** @group SourceInfoTransformMacro */
- def do_=== (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, EqualOp, that)
-
-// final def abs(): UInt = macro SourceInfoTransform.noArg
-
- def do_abs(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = {
- Mux(this < 0.S, (-this), this)
- }
-
- override def do_<< (that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt =
- binop(sourceInfo, SInt(this.width + that), ShiftLeftOp, validateShiftAmount(that))
- override def do_<< (that: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt =
- this << castToInt(that, "Shift amount")
- override def do_<< (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt =
- binop(sourceInfo, SInt(this.width.dynamicShiftLeft(that.width)), DynamicShiftLeftOp, that)
- override def do_>> (that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt =
- binop(sourceInfo, SInt(this.width.shiftRight(that)), ShiftRightOp, validateShiftAmount(that))
- override def do_>> (that: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt =
- this >> castToInt(that, "Shift amount")
- override def do_>> (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt =
- binop(sourceInfo, SInt(this.width), DynamicShiftRightOp, that)
-
- override def do_asUInt(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = pushOp(DefPrim(sourceInfo, UInt(this.width), AsUIntOp, ref))
- override def do_asSInt(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = this
- override def do_asFixedPoint(binaryPoint: BinaryPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = {
- binaryPoint match {
- case KnownBinaryPoint(value) =>
- val iLit = ILit(value)
- pushOp(DefPrim(sourceInfo, FixedPoint(width, binaryPoint), AsFixedPointOp, ref, iLit))
- case _ =>
- throwException(s"cannot call $this.asFixedPoint(binaryPoint=$binaryPoint), you must specify a known binaryPoint")
- }
- }
-
- private[core] override def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) {
- this := that.asSInt
- }
-}
-
-trait SIntFactory {
- /** Create an SInt type with inferred width. */
- def apply(): SInt = apply(Width())
- /** Create a SInt type or port with fixed width. */
- def apply(width: Width): SInt = new SInt(width)
-
- /** Create a SInt with the specified range */
- def apply(range: Range): SInt = {
- apply(range.getWidth)
- }
- /** Create a SInt with the specified range */
- def apply(range: (NumericBound[Int], NumericBound[Int])): SInt = {
- apply(KnownSIntRange(range._1, range._2))
- }
-
- /** Create an SInt literal with specified width. */
- protected[chisel3] def Lit(value: BigInt, width: Width): SInt = {
- val lit = SLit(value, width)
- val result = new SInt(lit.width)
- lit.bindLitArg(result)
- }
-}
-
-object SInt extends SIntFactory
-
-sealed trait Reset extends Element with ToBoolable
-
-// 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.
- *
- * @define coll [[Bool]]
- * @define numType $coll
- */
-sealed class Bool() extends UInt(1.W) with Reset {
- override def toString: String = {
- val bindingString = litToBooleanOption match {
- case Some(value) => s"($value)"
- case _ => bindingToString
- }
- s"Bool$bindingString"
- }
-
- private[core] override def cloneTypeWidth(w: Width): this.type = {
- require(!w.known || w.get == 1)
- new Bool().asInstanceOf[this.type]
- }
-
- /** Convert to a [[scala.Option]] of [[scala.Boolean]] */
- def litToBooleanOption: Option[Boolean] = litOption.map {
- case intVal if intVal == 1 => true
- case intVal if intVal == 0 => false
- case intVal => throwException(s"Boolean with unexpected literal value $intVal")
- }
-
- /** Convert to a [[scala.Boolean]] */
- def litToBoolean: Boolean = litToBooleanOption.get
-
- // REVIEW TODO: Why does this need to exist and have different conventions
- // than Bits?
-
- /** Bitwise and operator
- *
- * @param that a hardware $coll
- * @return the bitwise and of this $coll and `that`
- * @group Bitwise
- */
- final def & (that: Bool): Bool = macro SourceInfoTransform.thatArg
-
- /** Bitwise or operator
- *
- * @param that a hardware $coll
- * @return the bitwise or of this $coll and `that`
- * @group Bitwise
- */
- final def | (that: Bool): Bool = macro SourceInfoTransform.thatArg
-
- /** Bitwise exclusive or (xor) operator
- *
- * @param that a hardware $coll
- * @return the bitwise xor of this $coll and `that`
- * @group Bitwise
- */
- final def ^ (that: Bool): Bool = macro SourceInfoTransform.thatArg
-
- /** @group SourceInfoTransformMacro */
- def do_& (that: Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool =
- binop(sourceInfo, Bool(), BitAndOp, that)
- /** @group SourceInfoTransformMacro */
- def do_| (that: Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool =
- binop(sourceInfo, Bool(), BitOrOp, that)
- /** @group SourceInfoTransformMacro */
- def do_^ (that: Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool =
- binop(sourceInfo, Bool(), BitXorOp, that)
-
- /** @group SourceInfoTransformMacro */
- override def do_unary_~ (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool =
- unop(sourceInfo, Bool(), BitNotOp)
-
- /** Logical or operator
- *
- * @param that a hardware $coll
- * @return the lgocial or of this $coll and `that`
- * @note this is equivalent to [[Bool!.|(that:chisel3\.core\.Bool)* Bool.|)]]
- * @group Logical
- */
- def || (that: Bool): Bool = macro SourceInfoTransform.thatArg
-
- /** @group SourceInfoTransformMacro */
- def do_|| (that: Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = this | that
-
- /** Logical and operator
- *
- * @param that a hardware $coll
- * @return the lgocial and of this $coll and `that`
- * @note this is equivalent to [[Bool!.&(that:chisel3\.core\.Bool)* Bool.&]]
- * @group Logical
- */
- def && (that: Bool): Bool = macro SourceInfoTransform.thatArg
-
- /** @group SourceInfoTransformMacro */
- def do_&& (that: Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = this & that
-
- /** Reinterprets this $coll as a clock */
- def asClock(): Clock = macro SourceInfoTransform.noArg
-
- /** @group SourceInfoTransformMacro */
- def do_asClock(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Clock = pushOp(DefPrim(sourceInfo, Clock(), AsClockOp, ref))
-}
-
-trait BoolFactory {
- /** Creates an empty Bool.
- */
- def apply(): Bool = new Bool()
-
- /** Creates Bool literal.
- */
- protected[chisel3] def Lit(x: Boolean): Bool = {
- val result = new Bool()
- val lit = ULit(if (x) 1 else 0, Width(1))
- // Ensure we have something capable of generating a name.
- lit.bindLitArg(result)
- }
-}
-
-object Bool extends BoolFactory
-
-//scalastyle:off number.of.methods
-/** A sealed class representing a fixed point number that has a bit width and a binary point The width and binary point
- * may be inferred.
- *
- * IMPORTANT: The API provided here is experimental and may change in the future.
- *
- * @param width bit width of the fixed point number
- * @param binaryPoint the position of the binary point with respect to the right most bit of the width currently this
- * should be positive but it is hoped to soon support negative points and thus use this field as a
- * simple exponent
- * @define coll [[FixedPoint]]
- * @define numType $coll
- * @define expandingWidth @note The width of the returned $coll is `width of this` + `1`.
- * @define constantWidth @note The width of the returned $coll is unchanged, i.e., `width of this`.
- */
-sealed class FixedPoint private (width: Width, val binaryPoint: BinaryPoint)
- extends Bits(width) with Num[FixedPoint] {
- override def toString: String = {
- val bindingString = litToDoubleOption match {
- case Some(value) => s"($value)"
- case _ => bindingToString
- }
- s"FixedPoint$width$binaryPoint$bindingString"
- }
-
- private[core] override def typeEquivalent(that: Data): Boolean = that match {
- case that: FixedPoint => this.width == that.width && this.binaryPoint == that.binaryPoint // TODO: should this be true for unspecified widths?
- case _ => false
- }
-
- private[core] override def cloneTypeWidth(w: Width): this.type =
- new FixedPoint(w, binaryPoint).asInstanceOf[this.type]
-
- override def connect (that: Data)(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions): Unit = that match {
- case _: FixedPoint|DontCare => super.connect(that)
- case _ => this badConnect that
- }
-
- /** Convert to a [[scala.Option]] of [[scala.Boolean]] */
- def litToDoubleOption: Option[Double] = litOption.map { intVal =>
- val multiplier = math.pow(2, binaryPoint.get)
- intVal.toDouble / multiplier
- }
-
- /** Convert to a [[scala.Option]] */
- def litToDouble: Double = litToDoubleOption.get
-
-
- /** Unary negation (expanding width)
- *
- * @return a hardware $coll equal to zero minus this $coll
- * $expandingWidth
- * @group Arithmetic
- */
- final def unary_- (): FixedPoint = macro SourceInfoTransform.noArg
-
- /** Unary negation (constant width)
- *
- * @return a hardware $coll equal to zero minus `this` shifted right by one
- * $constantWidth
- * @group Arithmetic
- */
- final def unary_-% (): FixedPoint = macro SourceInfoTransform.noArg
-
- /** @group SourceInfoTransformMacro */
- def unary_- (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = FixedPoint.fromBigInt(0) - this
- /** @group SourceInfoTransformMacro */
- def unary_-% (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = FixedPoint.fromBigInt(0) -% this
-
- /** add (default - no growth) operator */
- override def do_+ (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint =
- this +% that
- /** subtract (default - no growth) operator */
- override def do_- (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint =
- this -% that
- override def do_* (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint =
- binop(sourceInfo, FixedPoint(this.width + that.width, this.binaryPoint + that.binaryPoint), TimesOp, that)
- override def do_/ (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint =
- throwException(s"division is illegal on FixedPoint types")
- override def do_% (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint =
- throwException(s"mod is illegal on FixedPoint types")
-
-
- /** Multiplication operator
- *
- * @param that a hardware [[UInt]]
- * @return the product of this $coll and `that`
- * $sumWidth
- * $singleCycleMul
- * @group Arithmetic
- */
- final def * (that: UInt): FixedPoint = macro SourceInfoTransform.thatArg
- /** @group SourceInfoTransformMacro */
- def do_* (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint =
- binop(sourceInfo, FixedPoint(this.width + that.width, binaryPoint), TimesOp, that)
-
- /** Multiplication operator
- *
- * @param that a hardware [[SInt]]
- * @return the product of this $coll and `that`
- * $sumWidth
- * $singleCycleMul
- * @group Arithmetic
- */
- final def * (that: SInt): FixedPoint = macro SourceInfoTransform.thatArg
- /** @group SourceInfoTransformMacro */
- def do_* (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint =
- binop(sourceInfo, FixedPoint(this.width + that.width, binaryPoint), TimesOp, that)
-
- /** Addition operator (expanding width)
- *
- * @param that a hardware $coll
- * @return the sum of this $coll and `that`
- * $maxWidthPlusOne
- * @group Arithmetic
- */
- final def +& (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg
-
- /** Addition operator (constant width)
- *
- * @param that a hardware $coll
- * @return the sum of this $coll and `that` shifted right by one
- * $maxWidth
- * @group Arithmetic
- */
- final def +% (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg
-
- /** Subtraction operator (increasing width)
- *
- * @param that a hardware $coll
- * @return the difference of this $coll less `that`
- * $maxWidthPlusOne
- * @group Arithmetic
- */
- final def -& (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg
-
- /** Subtraction operator (constant width)
- *
- * @param that a hardware $coll
- * @return the difference of this $coll less `that` shifted right by one
- * $maxWidth
- * @group Arithmetic
- */
- final def -% (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg
-
- /** @group SourceInfoTransformMacro */
- def do_+& (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = {
- (this.width, that.width, this.binaryPoint, that.binaryPoint) match {
- case (KnownWidth(thisWidth), KnownWidth(thatWidth), KnownBinaryPoint(thisBP), KnownBinaryPoint(thatBP)) =>
- val thisIntWidth = thisWidth - thisBP
- val thatIntWidth = thatWidth - thatBP
- val newBinaryPoint = thisBP max thatBP
- val newWidth = (thisIntWidth max thatIntWidth) + newBinaryPoint + 1
- binop(sourceInfo, FixedPoint(newWidth.W, newBinaryPoint.BP), AddOp, that)
- case _ =>
- val newBinaryPoint = this.binaryPoint max that.binaryPoint
- binop(sourceInfo, FixedPoint(UnknownWidth(), newBinaryPoint), AddOp, that)
- }
- }
-
- /** @group SourceInfoTransformMacro */
- def do_+% (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint =
- (this +& that).tail(1).asFixedPoint(this.binaryPoint max that.binaryPoint)
- /** @group SourceInfoTransformMacro */
- def do_-& (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = {
- (this.width, that.width, this.binaryPoint, that.binaryPoint) match {
- case (KnownWidth(thisWidth), KnownWidth(thatWidth), KnownBinaryPoint(thisBP), KnownBinaryPoint(thatBP)) =>
- val thisIntWidth = thisWidth - thisBP
- val thatIntWidth = thatWidth - thatBP
- val newBinaryPoint = thisBP max thatBP
- val newWidth = (thisIntWidth max thatIntWidth) + newBinaryPoint + 1
- binop(sourceInfo, FixedPoint(newWidth.W, newBinaryPoint.BP), SubOp, that)
- case _ =>
- val newBinaryPoint = this.binaryPoint max that.binaryPoint
- binop(sourceInfo, FixedPoint(UnknownWidth(), newBinaryPoint), SubOp, that)
- }
- }
-
- /** @group SourceInfoTransformMacro */
- def do_-% (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint =
- (this -& that).tail(1).asFixedPoint(this.binaryPoint max that.binaryPoint)
-
- /** Bitwise and operator
- *
- * @param that a hardware $coll
- * @return the bitwise and of this $coll and `that`
- * $maxWidth
- * @group Bitwise
- */
- final def & (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg
-
- /** Bitwise or operator
- *
- * @param that a hardware $coll
- * @return the bitwise or of this $coll and `that`
- * $maxWidth
- * @group Bitwise
- */
- final def | (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg
-
- /** Bitwise exclusive or (xor) operator
- *
- * @param that a hardware $coll
- * @return the bitwise xor of this $coll and `that`
- * $maxWidth
- * @group Bitwise
- */
- final def ^ (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg
-
- /** @group SourceInfoTransformMacro */
- def do_& (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint =
- throwException(s"And is illegal between $this and $that")
- /** @group SourceInfoTransformMacro */
- def do_| (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint =
- throwException(s"Or is illegal between $this and $that")
- /** @group SourceInfoTransformMacro */
- def do_^ (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint =
- throwException(s"Xor is illegal between $this and $that")
-
- final def setBinaryPoint(that: Int): FixedPoint = macro SourceInfoTransform.thatArg
-
- /** @group SourceInfoTransformMacro */
- def do_setBinaryPoint(that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = this.binaryPoint match {
- case KnownBinaryPoint(value) =>
- binop(sourceInfo, FixedPoint(this.width + (that - value), KnownBinaryPoint(that)), SetBinaryPoint, that)
- case _ =>
- binop(sourceInfo, FixedPoint(UnknownWidth(), KnownBinaryPoint(that)), SetBinaryPoint, that)
- }
-
- /** @group SourceInfoTransformMacro */
- def do_unary_~ (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint =
- throwException(s"Not is illegal on $this")
-
- // TODO(chick): Consider comparison with UInt and SInt
- override def do_< (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, LessOp, that)
- override def do_> (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, GreaterOp, that)
- override def do_<= (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, LessEqOp, that)
- override def do_>= (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, GreaterEqOp, that)
-
- final def != (that: FixedPoint): Bool = macro SourceInfoTransform.thatArg
-
- /** Dynamic not equals operator
- *
- * @param that a hardware $coll
- * @return a hardware [[Bool]] asserted if this $coll is not equal to `that`
- * @group Comparison
- */
- final def =/= (that: FixedPoint): Bool = macro SourceInfoTransform.thatArg
-
- /** Dynamic equals operator
- *
- * @param that a hardware $coll
- * @return a hardware [[Bool]] asserted if this $coll is equal to `that`
- * @group Comparison
- */
- final def === (that: FixedPoint): Bool = macro SourceInfoTransform.thatArg
-
- /** @group SourceInfoTransformMacro */
- def do_!= (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, NotEqualOp, that)
- /** @group SourceInfoTransformMacro */
- def do_=/= (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, NotEqualOp, that)
- /** @group SourceInfoTransformMacro */
- def do_=== (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, EqualOp, that)
-
- def do_abs(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = {
- // TODO: remove this once we have CompileOptions threaded through the macro system.
- import chisel3.core.ExplicitCompileOptions.NotStrict
- Mux(this < 0.F(0.BP), 0.F(0.BP) - this, this)
- }
-
- override def do_<< (that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint =
- binop(sourceInfo, FixedPoint(this.width + that, this.binaryPoint), ShiftLeftOp, validateShiftAmount(that))
- override def do_<< (that: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint =
- (this << castToInt(that, "Shift amount")).asFixedPoint(this.binaryPoint)
- override def do_<< (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint =
- binop(sourceInfo, FixedPoint(this.width.dynamicShiftLeft(that.width), this.binaryPoint), DynamicShiftLeftOp, that)
- override def do_>> (that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint =
- binop(sourceInfo, FixedPoint(this.width.shiftRight(that), this.binaryPoint), ShiftRightOp, validateShiftAmount(that))
- override def do_>> (that: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint =
- (this >> castToInt(that, "Shift amount")).asFixedPoint(this.binaryPoint)
- override def do_>> (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint =
- binop(sourceInfo, FixedPoint(this.width, this.binaryPoint), DynamicShiftRightOp, that)
-
- override def do_asUInt(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = pushOp(DefPrim(sourceInfo, UInt(this.width), AsUIntOp, ref))
- override def do_asSInt(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = pushOp(DefPrim(sourceInfo, SInt(this.width), AsSIntOp, ref))
-
- override def do_asFixedPoint(binaryPoint: BinaryPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = {
- binaryPoint match {
- case KnownBinaryPoint(value) =>
- val iLit = ILit(value)
- pushOp(DefPrim(sourceInfo, FixedPoint(width, binaryPoint), AsFixedPointOp, ref, iLit))
- case _ =>
- throwException(s"cannot call $this.asFixedPoint(binaryPoint=$binaryPoint), you must specify a known binaryPoint")
- }
- }
-
- private[core] override def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) {
- // TODO: redefine as just asFixedPoint on that, where FixedPoint.asFixedPoint just works.
- this := (that match {
- case fp: FixedPoint => fp.asSInt.asFixedPoint(this.binaryPoint)
- case _ => that.asFixedPoint(this.binaryPoint)
- })
- }
- //TODO(chick): Consider "convert" as an arithmetic conversion to UInt/SInt
-}
-
-/** Use PrivateObject to force users to specify width and binaryPoint by name
- */
-sealed trait PrivateType
-private case object PrivateObject extends PrivateType
-
-/**
- * Factory and convenience methods for the FixedPoint class
- * IMPORTANT: The API provided here is experimental and may change in the future.
- */
-object FixedPoint {
- /** Create an FixedPoint type with inferred width. */
- def apply(): FixedPoint = apply(Width(), BinaryPoint())
-
- /** Create an FixedPoint type or port with fixed width. */
- @chiselRuntimeDeprecated
- @deprecated("Use FixedPoint(width: Width, binaryPoint: BinaryPoint) example FixedPoint(16.W, 8.BP)", "chisel3")
- def apply(width: Int, binaryPoint: Int): FixedPoint = apply(Width(width), BinaryPoint(binaryPoint))
-
- /** Create an FixedPoint type or port with fixed width. */
- def apply(width: Width, binaryPoint: BinaryPoint): FixedPoint = new FixedPoint(width, binaryPoint)
-
- /** Create an FixedPoint literal with inferred width from BigInt.
- * Use PrivateObject to force users to specify width and binaryPoint by name
- */
- def fromBigInt(value: BigInt, width: Width, binaryPoint: BinaryPoint): FixedPoint = {
- apply(value, width, binaryPoint)
- }
- /** Create an FixedPoint literal with inferred width from BigInt.
- * Use PrivateObject to force users to specify width and binaryPoint by name
- */
- def fromBigInt(value: BigInt, binaryPoint: BinaryPoint = 0.BP): FixedPoint = {
- apply(value, Width(), binaryPoint)
- }
- /** Create an FixedPoint literal with inferred width from BigInt.
- * Use PrivateObject to force users to specify width and binaryPoint by name
- */
- def fromBigInt(value: BigInt, width: Int, binaryPoint: Int): FixedPoint =
- if(width == -1) {
- apply(value, Width(), BinaryPoint(binaryPoint))
- }
- else {
- apply(value, Width(width), BinaryPoint(binaryPoint))
- }
- /** Create an FixedPoint literal with inferred width from Double.
- * Use PrivateObject to force users to specify width and binaryPoint by name
- */
- @chiselRuntimeDeprecated
- @deprecated("use fromDouble(value: Double, width: Width, binaryPoint: BinaryPoint)", "chisel3")
- def fromDouble(value: Double, dummy: PrivateType = PrivateObject,
- width: Int = -1, binaryPoint: Int = 0): FixedPoint = {
- fromBigInt(
- toBigInt(value, binaryPoint), width = width, binaryPoint = binaryPoint
- )
- }
- /** Create an FixedPoint literal with inferred width from Double.
- * Use PrivateObject to force users to specify width and binaryPoint by name
- */
- def fromDouble(value: Double, width: Width, binaryPoint: BinaryPoint): FixedPoint = {
- fromBigInt(
- toBigInt(value, binaryPoint.get), width = width, binaryPoint = binaryPoint
- )
- }
-
- /** Create an FixedPoint port with specified width and binary position. */
- def apply(value: BigInt, width: Width, binaryPoint: BinaryPoint): FixedPoint = {
- val lit = FPLit(value, width, binaryPoint)
- val newLiteral = new FixedPoint(lit.width, lit.binaryPoint)
- // Ensure we have something capable of generating a name.
- lit.bindLitArg(newLiteral)
- }
-
- /**
- * How to create a bigint from a double with a specific binaryPoint
- * @param x a double value
- * @param binaryPoint a binaryPoint that you would like to use
- * @return
- */
- def toBigInt(x: Double, binaryPoint : Int): BigInt = {
- val multiplier = math.pow(2,binaryPoint )
- val result = BigInt(math.round(x * multiplier))
- result
- }
-
- /**
- * converts a bigInt with the given binaryPoint into the double representation
- * @param i a bigint
- * @param binaryPoint the implied binaryPoint of @i
- * @return
- */
- def toDouble(i: BigInt, binaryPoint : Int): Double = {
- val multiplier = math.pow(2,binaryPoint)
- val result = i.toDouble / multiplier
- result
- }
-
-}
-
-/** Data type for representing bidirectional bitvectors of a given width
- *
- * Analog support is limited to allowing wiring up of Verilog BlackBoxes with bidirectional (inout)
- * pins. There is currently no support for reading or writing of Analog types within Chisel code.
- *
- * Given that Analog is bidirectional, it is illegal to assign a direction to any Analog type. It
- * is legal to "flip" the direction (since Analog can be a member of aggregate types) which has no
- * effect.
- *
- * Analog types are generally connected using the bidirectional [[attach]] mechanism, but also
- * support limited bulkconnect `<>`. Analog types are only allowed to be bulk connected *once* in a
- * given module. This is to prevent any surprising consequences of last connect semantics.
- *
- * @note This API is experimental and subject to change
- */
-final class Analog private (private[chisel3] val width: Width) extends Element {
- require(width.known, "Since Analog is only for use in BlackBoxes, width must be known")
-
- override def toString: String = {
- s"Analog$width$bindingToString"
- }
-
- private[core] override def typeEquivalent(that: Data): Boolean =
- that.isInstanceOf[Analog] && this.width == that.width
-
- override def litOption: Option[BigInt] = None
-
- def cloneType: this.type = new Analog(width).asInstanceOf[this.type]
-
- // Used to enforce single bulk connect of Analog types, multi-attach is still okay
- // Note that this really means 1 bulk connect per Module because a port can
- // be connected in the parent module as well
- private[core] val biConnectLocs = mutable.Map.empty[RawModule, SourceInfo]
-
- // Define setter/getter pairing
- // Analog can only be bound to Ports and Wires (and Unbound)
- private[chisel3] override def bind(target: Binding, parentDirection: SpecifiedDirection) {
- SpecifiedDirection.fromParent(parentDirection, specifiedDirection) match {
- case SpecifiedDirection.Unspecified | SpecifiedDirection.Flip =>
- case x => throwException(s"Analog may not have explicit direction, got '$x'")
- }
- val targetTopBinding = target match {
- case target: TopBinding => target
- case ChildBinding(parent) => parent.topBinding
- // See https://github.com/freechipsproject/chisel3/pull/946
- case SampleElementBinding(parent) => parent.topBinding
- }
-
- // Analog counts as different directions based on binding context
- targetTopBinding match {
- case WireBinding(_) => direction = ActualDirection.Unspecified // internal wire
- case PortBinding(_) => direction = ActualDirection.Bidirectional(ActualDirection.Default)
- case x => throwException(s"Analog can only be Ports and Wires, not '$x'")
- }
- binding = target
- }
-
- override def do_asUInt(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt =
- throwException("Analog does not support asUInt")
-
- private[core] override def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo,
- compileOptions: CompileOptions): Unit = {
- throwException("Analog does not support connectFromBits")
- }
-
- final def toPrintable: Printable = PString("Analog")
-}
-/** Object that provides factory methods for [[Analog]] objects
- *
- * @note This API is experimental and subject to change
- */
-object Analog {
- def apply(width: Width): Analog = new Analog(width)
-}
diff --git a/chiselFrontend/src/main/scala/chisel3/core/BlackBox.scala b/chiselFrontend/src/main/scala/chisel3/core/BlackBox.scala
deleted file mode 100644
index e8dc2bfe..00000000
--- a/chiselFrontend/src/main/scala/chisel3/core/BlackBox.scala
+++ /dev/null
@@ -1,172 +0,0 @@
-// See LICENSE for license details.
-
-package chisel3.core
-
-import chisel3.internal.Builder.pushCommand
-import chisel3.internal.firrtl._
-import chisel3.internal.throwException
-import chisel3.internal.sourceinfo.{SourceInfo, UnlocatableSourceInfo}
-
-/** Parameters for BlackBoxes */
-sealed abstract class Param
-case class IntParam(value: BigInt) extends Param
-case class DoubleParam(value: Double) extends Param
-case class StringParam(value: String) extends Param
-/** Unquoted String */
-case class RawParam(value: String) extends Param
-
-abstract class BaseBlackBox extends BaseModule
-
-/** 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.
- *
- * A variant of BlackBox, this has a more consistent naming scheme in allowing
- * multiple top-level IO and does not drop the top prefix.
- *
- * @example
- * Some design require a differential input clock to clock the all design.
- * With the xilinx FPGA for example, a Verilog template named IBUFDS must be
- * integrated to use differential input:
- * {{{
- * IBUFDS #(.DIFF_TERM("TRUE"),
- * .IOSTANDARD("DEFAULT")) ibufds (
- * .IB(ibufds_IB),
- * .I(ibufds_I),
- * .O(ibufds_O)
- * );
- * }}}
- *
- * To instantiate it, a BlackBox can be used like following:
- * {{{
- * import chisel3._
- * import chisel3.experimental._
- *
- * // Example with Xilinx differential buffer IBUFDS
- * class IBUFDS extends ExtModule(Map("DIFF_TERM" -> "TRUE", // Verilog parameters
- * "IOSTANDARD" -> "DEFAULT"
- * )) {
- * val O = IO(Output(Clock()))
- * val I = IO(Input(Clock()))
- * val IB = IO(Input(Clock()))
- * }
- * }}}
- * @note The parameters API is experimental and may change
- */
-abstract class ExtModule(val params: Map[String, Param] = Map.empty[String, Param]) extends BaseBlackBox {
- private[core] override def generateComponent(): Component = {
- require(!_closed, "Can't generate module more than once")
- _closed = true
-
- val names = nameIds(classOf[ExtModule])
-
- // Name ports based on reflection
- for (port <- getModulePorts) {
- require(names.contains(port), s"Unable to name port $port in $this")
- port.setRef(ModuleIO(this, _namespace.name(names(port))))
- }
-
- // All suggestions are in, force names to every node.
- // While BlackBoxes are not supposed to have an implementation, we still need to call
- // _onModuleClose on all nodes (for example, Aggregates use it for recursive naming).
- for (id <- getIds) {
- id._onModuleClose
- }
-
- val firrtlPorts = getModulePorts map {port => Port(port, port.specifiedDirection)}
- val component = DefBlackBox(this, name, firrtlPorts, SpecifiedDirection.Unspecified, params)
- _component = Some(component)
- component
- }
-
- private[core] def initializeInParent(parentCompileOptions: CompileOptions): Unit = {
- implicit val sourceInfo = UnlocatableSourceInfo
-
- for (x <- getModulePorts) {
- pushCommand(DefInvalid(sourceInfo, x.ref))
- }
- }
-}
-
-/** 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
- * Some design require a differential input clock to clock the all design.
- * With the xilinx FPGA for example, a Verilog template named IBUFDS must be
- * integrated to use differential input:
- * {{{
- * IBUFDS #(.DIFF_TERM("TRUE"),
- * .IOSTANDARD("DEFAULT")) ibufds (
- * .IB(ibufds_IB),
- * .I(ibufds_I),
- * .O(ibufds_O)
- * );
- * }}}
- *
- * To instantiate it, a BlackBox can be used like following:
- * {{{
- * import chisel3._
- * import chisel3.experimental._
- *
- * // Example with Xilinx differential buffer IBUFDS
- * class IBUFDS extends BlackBox(Map("DIFF_TERM" -> "TRUE", // Verilog parameters
- * "IOSTANDARD" -> "DEFAULT"
- * )) {
- * val io = IO(new Bundle {
- * val O = Output(Clock()) // IO names will be the same
- * val I = Input(Clock()) // (without 'io_' in prefix)
- * val IB = Input(Clock()) //
- * })
- * }
- * }}}
- * @note The parameters API is experimental and may change
- */
-abstract class BlackBox(val params: Map[String, Param] = Map.empty[String, Param])(implicit compileOptions: CompileOptions) extends BaseBlackBox { // scalastyle:ignore line.size.limit
- def io: Record
-
- // Allow access to bindings from the compatibility package
- protected def _compatIoPortBound() = portsContains(io) // scalastyle:ignore method.name
-
- private[core] override def generateComponent(): Component = {
- _compatAutoWrapPorts() // pre-IO(...) compatibility hack
-
- // Restrict IO to just io, clock, and reset
- require(io != null, "BlackBox must have io")
- require(portsContains(io), "BlackBox must have io wrapped in IO(...)")
- require(portsSize == 1, "BlackBox must only have io as IO")
-
- require(!_closed, "Can't generate module more than once")
- _closed = true
-
- val namedPorts = io.elements.toSeq.reverse // ListMaps are stored in reverse order
-
- // 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) <- namedPorts) {
- 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 <- getIds; if id ne io) {
- id._onModuleClose
- }
-
- val firrtlPorts = namedPorts map {namedPort => Port(namedPort._2, namedPort._2.specifiedDirection)}
- val component = DefBlackBox(this, name, firrtlPorts, io.specifiedDirection, params)
- _component = Some(component)
- component
- }
-
- private[core] def initializeInParent(parentCompileOptions: CompileOptions): Unit = {
- for ((_, port) <- io.elements) {
- pushCommand(DefInvalid(UnlocatableSourceInfo, port.ref))
- }
- }
-}
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Clock.scala b/chiselFrontend/src/main/scala/chisel3/core/Clock.scala
deleted file mode 100644
index 364ac5aa..00000000
--- a/chiselFrontend/src/main/scala/chisel3/core/Clock.scala
+++ /dev/null
@@ -1,38 +0,0 @@
-// See LICENSE for license details.
-
-package chisel3.core
-
-import chisel3.internal.Builder.{pushOp}
-import chisel3.internal.firrtl._
-import chisel3.internal.sourceinfo._
-import chisel3.internal.firrtl.PrimOp.AsUIntOp
-
-object Clock {
- def apply(): Clock = new Clock
-}
-
-// TODO: Document this.
-sealed class Clock(private[chisel3] val width: Width = Width(1)) extends Element {
- override def toString: String = s"Clock$bindingToString"
-
- def cloneType: this.type = Clock().asInstanceOf[this.type]
-
- private[core] def typeEquivalent(that: Data): Boolean =
- this.getClass == that.getClass
-
- override def connect(that: Data)(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions): Unit = that match { // scalastyle:ignore line.size.limit
- case _: Clock => super.connect(that)(sourceInfo, connectCompileOptions)
- case _ => super.badConnect(that)(sourceInfo)
- }
-
- override def litOption: Option[BigInt] = None
-
- /** Not really supported */
- def toPrintable: Printable = PString("CLOCK")
-
- override def do_asUInt(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions): UInt = pushOp(DefPrim(sourceInfo, UInt(this.width), AsUIntOp, ref)) // scalastyle:ignore line.size.limit
- private[core] override def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo,
- compileOptions: CompileOptions): Unit = {
- this := that
- }
-}
diff --git a/chiselFrontend/src/main/scala/chisel3/core/CompileOptions.scala b/chiselFrontend/src/main/scala/chisel3/core/CompileOptions.scala
deleted file mode 100644
index a2f94e51..00000000
--- a/chiselFrontend/src/main/scala/chisel3/core/CompileOptions.scala
+++ /dev/null
@@ -1,76 +0,0 @@
-// See LICENSE for license details.
-
-package chisel3.core
-
-import scala.language.experimental.macros
-import scala.reflect.macros.blackbox.Context
-
-trait CompileOptions {
- // Should Record 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
- // 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
- // Check that referenced Data have actually been declared.
- val checkSynthesizable: Boolean
- // Require explicit assignment of DontCare to generate "x is invalid"
- val explicitInvalidate: Boolean
-}
-
-object CompileOptions {
- // Provides a low priority Strict default. Can be overridden by importing the NotStrict option.
- // Implemented as a macro to prevent this from being used inside chisel core.
- implicit def materialize: CompileOptions = macro materialize_impl
-
- def materialize_impl(c: Context): c.Tree = {
- import c.universe._
- q"_root_.chisel3.core.ExplicitCompileOptions.Strict"
- }
-}
-
-object ExplicitCompileOptions {
- case class CompileOptionsClass (
- // Should Record 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,
- // 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,
- // Check that referenced Data have actually been declared.
- val checkSynthesizable: Boolean,
- // Require an explicit DontCare assignment to generate a firrtl DefInvalid
- val explicitInvalidate: Boolean
- ) extends CompileOptions
-
- // Collection of "not strict" connection compile options.
- // These provide compatibility with existing code.
- // import chisel3.core.ExplicitCompileOptions.NotStrict
- implicit val NotStrict = new CompileOptionsClass (
- connectFieldsMustMatch = false,
- declaredTypeMustBeUnbound = false,
- dontTryConnectionsSwapped = false,
- dontAssumeDirectionality = false,
- checkSynthesizable = false,
- explicitInvalidate = false
- )
-
- // Collection of "strict" connection compile options, preferred for new code.
- // import chisel3.core.ExplicitCompileOptions.Strict
- implicit val Strict = new CompileOptionsClass (
- connectFieldsMustMatch = true,
- declaredTypeMustBeUnbound = true,
- dontTryConnectionsSwapped = true,
- dontAssumeDirectionality = true,
- checkSynthesizable = true,
- explicitInvalidate = true
- )
-}
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Data.scala b/chiselFrontend/src/main/scala/chisel3/core/Data.scala
deleted file mode 100644
index 3ce79786..00000000
--- a/chiselFrontend/src/main/scala/chisel3/core/Data.scala
+++ /dev/null
@@ -1,742 +0,0 @@
-// See LICENSE for license details.
-
-package chisel3.core
-
-import scala.language.experimental.macros
-
-import chisel3.internal._
-import chisel3.internal.Builder.{pushCommand, pushOp}
-import chisel3.internal.firrtl._
-import chisel3.internal.sourceinfo.{SourceInfo, SourceInfoTransform, UnlocatableSourceInfo, DeprecatedSourceInfo}
-import chisel3.SourceInfoDoc
-import chisel3.core.BiConnect.DontCareCantBeSink
-
-/** User-specified directions.
- */
-sealed abstract class SpecifiedDirection
-object SpecifiedDirection {
- /** Default user direction, also meaning 'not-flipped'
- */
- case object Unspecified extends SpecifiedDirection
- /** Node and its children are forced as output
- */
- case object Output extends SpecifiedDirection
- /** Node and its children are forced as inputs
- */
- case object Input extends SpecifiedDirection
- /** Mainly for containers, children are flipped.
- */
- case object Flip extends SpecifiedDirection
-
- def flip(dir: SpecifiedDirection): SpecifiedDirection = dir match {
- case Unspecified => Flip
- case Flip => Unspecified
- case Output => Input
- case Input => Output
- }
-
- /** Returns the effective SpecifiedDirection of this node given the parent's effective SpecifiedDirection
- * and the user-specified SpecifiedDirection of this node.
- */
- def fromParent(parentDirection: SpecifiedDirection, thisDirection: SpecifiedDirection): SpecifiedDirection =
- (parentDirection, thisDirection) match {
- case (SpecifiedDirection.Output, _) => SpecifiedDirection.Output
- case (SpecifiedDirection.Input, _) => SpecifiedDirection.Input
- case (SpecifiedDirection.Unspecified, thisDirection) => thisDirection
- case (SpecifiedDirection.Flip, thisDirection) => SpecifiedDirection.flip(thisDirection)
- }
-}
-
-/** Resolved directions for both leaf and container nodes, only visible after
- * a node is bound (since higher-level specifications like Input and Output
- * can override directions).
- */
-sealed abstract class ActualDirection
-
-object ActualDirection {
- /** The object does not exist / is empty and hence has no direction
- */
- case object Empty extends ActualDirection
-
- /** Undirectioned, struct-like
- */
- case object Unspecified extends ActualDirection
- /** Output element, or container with all outputs (even if forced)
- */
- case object Output extends ActualDirection
- /** Input element, or container with all inputs (even if forced)
- */
- case object Input extends ActualDirection
-
- sealed abstract class BidirectionalDirection
- case object Default extends BidirectionalDirection
- case object Flipped extends BidirectionalDirection
-
- case class Bidirectional(dir: BidirectionalDirection) extends ActualDirection
-
- def fromSpecified(direction: SpecifiedDirection): ActualDirection = direction match {
- case SpecifiedDirection.Unspecified | SpecifiedDirection.Flip => ActualDirection.Unspecified
- case SpecifiedDirection.Output => ActualDirection.Output
- case SpecifiedDirection.Input => ActualDirection.Input
- }
-
- /** Determine the actual binding of a container given directions of its children.
- * Returns None in the case of mixed specified / unspecified directionality.
- */
- def fromChildren(childDirections: Set[ActualDirection], containerDirection: SpecifiedDirection):
- Option[ActualDirection] = {
- if (childDirections == Set()) { // Sadly, Scala can't do set matching
- ActualDirection.fromSpecified(containerDirection) match {
- case ActualDirection.Unspecified => Some(ActualDirection.Empty) // empty direction if relative / no direction
- case dir => Some(dir) // use assigned direction if specified
- }
- } else if (childDirections == Set(ActualDirection.Unspecified)) {
- Some(ActualDirection.Unspecified)
- } else if (childDirections == Set(ActualDirection.Input)) {
- Some(ActualDirection.Input)
- } else if (childDirections == Set(ActualDirection.Output)) {
- Some(ActualDirection.Output)
- } else if (childDirections subsetOf
- Set(ActualDirection.Output, ActualDirection.Input,
- ActualDirection.Bidirectional(ActualDirection.Default),
- ActualDirection.Bidirectional(ActualDirection.Flipped))) {
- containerDirection match {
- case SpecifiedDirection.Unspecified => Some(ActualDirection.Bidirectional(ActualDirection.Default))
- case SpecifiedDirection.Flip => Some(ActualDirection.Bidirectional(ActualDirection.Flipped))
- case _ => throw new RuntimeException("Unexpected forced Input / Output")
- }
- } else {
- None
- }
- }
-}
-
-object debug { // scalastyle:ignore object.name
- @chiselRuntimeDeprecated
- @deprecated("debug doesn't do anything in Chisel3 as no pruning happens in the frontend", "chisel3")
- def apply (arg: Data): Data = arg
-}
-
-/** Experimental hardware construction reflection API
- */
-object DataMirror {
- def widthOf(target: Data): Width = target.width
- def specifiedDirectionOf(target: Data): SpecifiedDirection = target.specifiedDirection
- def directionOf(target: Data): ActualDirection = {
- requireIsHardware(target, "node requested directionality on")
- target.direction
- }
-
- // Returns the top-level module ports
- // TODO: maybe move to something like Driver or DriverUtils, since this is mainly for interacting
- // with compiled artifacts (vs. elaboration-time reflection)?
- def modulePorts(target: BaseModule): Seq[(String, Data)] = target.getChiselPorts
-
- // Returns all module ports with underscore-qualified names
- def fullModulePorts(target: BaseModule): Seq[(String, Data)] = {
- def getPortNames(name: String, data: Data): Seq[(String, Data)] = Seq(name -> data) ++ (data match {
- case _: Element => Seq()
- case r: Record => r.elements.toSeq flatMap { case (eltName, elt) => getPortNames(s"${name}_${eltName}", elt) }
- case v: Vec[_] => v.zipWithIndex flatMap { case (elt, index) => getPortNames(s"${name}_${index}", elt) }
- })
- modulePorts(target).flatMap { case (name, data) =>
- getPortNames(name, data).toList
- }
- }
-
- // Internal reflection-style APIs, subject to change and removal whenever.
- object internal { // scalastyle:ignore object.name
- def isSynthesizable(target: Data): Boolean = target.isSynthesizable
- // For those odd cases where you need to care about object reference and uniqueness
- def chiselTypeClone[T<:Data](target: Data): T = {
- target.cloneTypeFull.asInstanceOf[T]
- }
- }
-}
-
-/** Creates a clone of the super-type of the input elements. Super-type is defined as:
- * - for Bits type of the same class: the cloned type of the largest width
- * - Bools are treated as UInts
- * - For other types of the same class are are the same: clone of any of the elements
- * - Otherwise: fail
- */
-//scalastyle:off cyclomatic.complexity
-private[core] object cloneSupertype {
- def apply[T <: Data](elts: Seq[T], createdType: String)(implicit sourceInfo: SourceInfo,
- compileOptions: CompileOptions): T = {
- require(!elts.isEmpty, s"can't create $createdType with no inputs")
-
- val filteredElts = elts.filter(_ != DontCare)
- require(!filteredElts.isEmpty, s"can't create $createdType with only DontCare inputs")
-
- if (filteredElts.head.isInstanceOf[Bits]) {
- val model: T = filteredElts reduce { (elt1: T, elt2: T) => ((elt1, elt2) match {
- case (elt1: Bool, elt2: Bool) => elt1
- case (elt1: Bool, elt2: UInt) => elt2 // TODO: what happens with zero width UInts?
- case (elt1: UInt, elt2: Bool) => elt1 // TODO: what happens with zero width UInts?
- case (elt1: UInt, elt2: UInt) =>
- // TODO: perhaps redefine Widths to allow >= op?
- if (elt1.width == (elt1.width max elt2.width)) elt1 else elt2
- case (elt1: SInt, elt2: SInt) => if (elt1.width == (elt1.width max elt2.width)) elt1 else elt2
- case (elt1: FixedPoint, elt2: FixedPoint) => {
- (elt1.binaryPoint, elt2.binaryPoint, elt1.width, elt2.width) match {
- case (KnownBinaryPoint(bp1), KnownBinaryPoint(bp2), KnownWidth(w1), KnownWidth(w2)) =>
- val maxBinaryPoint = bp1 max bp2
- val maxIntegerWidth = (w1 - bp1) max (w2 - bp2)
- FixedPoint((maxIntegerWidth + maxBinaryPoint).W, (maxBinaryPoint).BP)
- case (KnownBinaryPoint(bp1), KnownBinaryPoint(bp2), _, _) =>
- FixedPoint(Width(), (bp1 max bp2).BP)
- case _ => FixedPoint()
- }
- }
- case (elt1, elt2) =>
- throw new AssertionError(
- s"can't create $createdType with heterogeneous types ${elt1.getClass} and ${elt2.getClass}")
- }).asInstanceOf[T] }
- model.cloneTypeFull
- }
- else {
- for (elt <- filteredElts.tail) {
- require(elt.getClass == filteredElts.head.getClass,
- s"can't create $createdType with heterogeneous types ${filteredElts.head.getClass} and ${elt.getClass}")
- require(elt typeEquivalent filteredElts.head,
- s"can't create $createdType with non-equivalent types ${filteredElts.head} and ${elt}")
- }
- filteredElts.head.cloneTypeFull
- }
- }
-}
-
-/** Returns the chisel type of a hardware object, allowing other hardware to be constructed from it.
- */
-object chiselTypeOf {
- def apply[T <: Data](target: T): T = {
- requireIsHardware(target)
- target.cloneTypeFull.asInstanceOf[T]
- }
-}
-
-/**
-* Input, Output, and Flipped are used to define the directions of Module IOs.
-*
-* 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](source: T)(implicit compileOptions: CompileOptions): T = {
- if (compileOptions.checkSynthesizable) {
- requireIsChiselType(source)
- }
- val out = source.cloneType.asInstanceOf[T]
- out.specifiedDirection = SpecifiedDirection.Input
- out
- }
-}
-object Output {
- def apply[T<:Data](source: T)(implicit compileOptions: CompileOptions): T = {
- if (compileOptions.checkSynthesizable) {
- requireIsChiselType(source)
- }
- val out = source.cloneType.asInstanceOf[T]
- out.specifiedDirection = SpecifiedDirection.Output
- out
- }
-}
-object Flipped {
- def apply[T<:Data](source: T)(implicit compileOptions: CompileOptions): T = {
- if (compileOptions.checkSynthesizable) {
- requireIsChiselType(source)
- }
- val out = source.cloneType.asInstanceOf[T]
- out.specifiedDirection = SpecifiedDirection.flip(source.specifiedDirection)
- out
- }
-}
-
-/** 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.
- *
- * @groupdesc Connect Utilities for connecting hardware components
- * @define coll data
- */
-abstract class Data extends HasId with NamedComponent with SourceInfoDoc { // scalastyle:ignore number.of.methods
- // This is a bad API that punches through object boundaries.
- @deprecated("pending removal once all instances replaced", "chisel3")
- private[chisel3] def flatten: IndexedSeq[Element] = {
- this match {
- case elt: Aggregate => elt.getElements.toIndexedSeq flatMap {_.flatten}
- case elt: Element => IndexedSeq(elt)
- case elt => throwException(s"Cannot flatten type ${elt.getClass}")
- }
- }
-
- // User-specified direction, local at this node only.
- // Note that the actual direction of this node can differ from child and parent specifiedDirection.
- private var _specifiedDirection: SpecifiedDirection = SpecifiedDirection.Unspecified
- private[chisel3] def specifiedDirection: SpecifiedDirection = _specifiedDirection
- private[core] def specifiedDirection_=(direction: SpecifiedDirection) = {
- if (_specifiedDirection != SpecifiedDirection.Unspecified) {
- this match {
- // Anything flies in compatibility mode
- case t: Record if !t.compileOptions.dontAssumeDirectionality =>
- case _ => throw Binding.RebindingException(s"Attempted reassignment of user-specified direction to $this")
- }
- }
- _specifiedDirection = direction
- }
-
- /** This overwrites a relative SpecifiedDirection with an explicit one, and is used to implement
- * the compatibility layer where, at the elements, Flip is Input and unspecified is Output.
- * DO NOT USE OUTSIDE THIS PURPOSE. THIS OPERATION IS DANGEROUS!
- */
- private[core] def _assignCompatibilityExplicitDirection: Unit = { // scalastyle:off method.name
- (this, _specifiedDirection) match {
- case (_: Analog, _) => // nothing to do
- case (_, SpecifiedDirection.Unspecified) => _specifiedDirection = SpecifiedDirection.Output
- case (_, SpecifiedDirection.Flip) => _specifiedDirection = SpecifiedDirection.Input
- case (_, SpecifiedDirection.Input | SpecifiedDirection.Output) => // nothing to do
- }
- }
-
- // Binding stores information about this node's position in the hardware graph.
- // This information is supplemental (more than is necessary to generate FIRRTL) and is used to
- // perform checks in Chisel, where more informative error messages are possible.
- private var _binding: Option[Binding] = None
- // Only valid after node is bound (synthesizable), crashes otherwise
- protected[core] def binding: Option[Binding] = _binding
- protected def binding_=(target: Binding) {
- if (_binding.isDefined) {
- throw Binding.RebindingException(s"Attempted reassignment of binding to $this")
- }
- _binding = Some(target)
- }
-
- // Similar to topBindingOpt except it explicitly excludes SampleElements which are bound but not
- // hardware
- private[core] final def isSynthesizable: Boolean = _binding.map {
- case ChildBinding(parent) => parent.isSynthesizable
- case _: TopBinding => true
- case _: SampleElementBinding[_] => false
- }.getOrElse(false)
-
- private[core] def topBindingOpt: Option[TopBinding] = _binding.flatMap {
- case ChildBinding(parent) => parent.topBindingOpt
- case bindingVal: TopBinding => Some(bindingVal)
- case SampleElementBinding(parent) => parent.topBindingOpt
- }
-
- private[core] def topBinding: TopBinding = topBindingOpt.get
-
- /** Binds this node to the hardware graph.
- * parentDirection is the direction of the parent node, or Unspecified (default) if the target
- * node is the top-level.
- * binding and direction are valid after this call completes.
- */
- private[chisel3] def bind(target: Binding, parentDirection: SpecifiedDirection = SpecifiedDirection.Unspecified)
-
- // Both _direction and _resolvedUserDirection are saved versions of computed variables (for
- // efficiency, avoid expensive recomputation of frequent operations).
- // Both are only valid after binding is set.
-
- // Direction of this node, accounting for parents (force Input / Output) and children.
- private var _direction: Option[ActualDirection] = None
-
- private[chisel3] def direction: ActualDirection = _direction.get
- private[core] def direction_=(actualDirection: ActualDirection) {
- if (_direction.isDefined) {
- throw Binding.RebindingException(s"Attempted reassignment of resolved direction to $this")
- }
- _direction = Some(actualDirection)
- }
-
- // User-friendly representation of the binding as a helper function for toString.
- // Provides a unhelpful fallback for literals, which should have custom rendering per
- // Data-subtype.
- // TODO Is this okay for sample_element? It *shouldn't* be visible to users
- protected def bindingToString: String = topBindingOpt match {
- case None => ""
- case Some(OpBinding(enclosure)) => s"(OpResult in ${enclosure.desiredName})"
- case Some(MemoryPortBinding(enclosure)) => s"(MemPort in ${enclosure.desiredName})"
- case Some(PortBinding(enclosure)) if !enclosure.isClosed => s"(IO in unelaborated ${enclosure.desiredName})"
- case Some(PortBinding(enclosure)) if enclosure.isClosed =>
- DataMirror.fullModulePorts(enclosure).find(_._2 eq this) match {
- case Some((name, _)) => s"(IO $name in ${enclosure.desiredName})"
- case None => s"(IO (unknown) in ${enclosure.desiredName})"
- }
- case Some(RegBinding(enclosure)) => s"(Reg in ${enclosure.desiredName})"
- case Some(WireBinding(enclosure)) => s"(Wire in ${enclosure.desiredName})"
- case Some(DontCareBinding()) => s"(DontCare)"
- case Some(ElementLitBinding(litArg)) => s"(unhandled literal)"
- case Some(BundleLitBinding(litMap)) => s"(unhandled bundle literal)"
- }
-
- // Return ALL elements at root of this type.
- // Contasts with flatten, which returns just Bits
- // TODO: refactor away this, this is outside the scope of Data
- private[chisel3] def allElements: Seq[Element]
-
- 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 = { // scalastyle:ignore line.size.limit
- if (connectCompileOptions.checkSynthesizable) {
- requireIsHardware(this, "data to be connected")
- requireIsHardware(that, "data to be connected")
- this.topBinding match {
- case _: ReadOnlyBinding => throwException(s"Cannot reassign to read-only $this")
- case _ => // fine
- }
- try {
- MonoConnect.connect(sourceInfo, connectCompileOptions, this, that, Builder.forcedUserModule)
- } 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 = { // scalastyle:ignore line.size.limit
- if (connectCompileOptions.checkSynthesizable) {
- requireIsHardware(this, s"data to be bulk-connected")
- requireIsHardware(that, s"data to be bulk-connected")
- (this.topBinding, that.topBinding) match {
- case (_: ReadOnlyBinding, _: ReadOnlyBinding) => throwException(s"Both $this and $that are read-only")
- // DontCare cannot be a sink (LHS)
- case (_: DontCareBinding, _) => throw DontCareCantBeSink
- case _ => // fine
- }
- try {
- BiConnect.connect(sourceInfo, connectCompileOptions, this, that, Builder.forcedUserModule)
- } catch {
- case BiConnect.BiConnectException(message) =>
- throwException(
- s"Connection between left ($this) and source ($that) failed @$message"
- )
- }
- } else {
- this legacyConnect that
- }
- }
-
- /** Whether this Data has the same model ("data type") as that Data.
- * Data subtypes should overload this with checks against their own type.
- */
- private[core] def typeEquivalent(that: Data): Boolean
-
- // Internal API: returns a ref that can be assigned to, if consistent with the binding
- private[chisel3] def lref: Node = {
- requireIsHardware(this)
- topBindingOpt match {
- case Some(binding: ReadOnlyBinding) => throwException(s"internal error: attempted to generate LHS ref to ReadOnlyBinding $binding") // scalastyle:ignore line.size.limit
- case Some(binding: TopBinding) => Node(this)
- case opt => throwException(s"internal error: unknown binding $opt in generating LHS ref")
- }
- }
-
-
- // Internal API: returns a ref, if bound. Literals should override this as needed.
- private[chisel3] def ref: Arg = {
- requireIsHardware(this)
- topBindingOpt match {
- case Some(binding: LitBinding) => throwException(s"internal error: can't handle literal binding $binding")
- case Some(binding: TopBinding) => Node(this)
- case opt => throwException(s"internal error: unknown binding $opt in generating LHS ref")
- }
- }
-
- private[chisel3] def width: Width
- private[core] def legacyConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit
-
- /** Internal API; Chisel users should look at chisel3.chiselTypeOf(...).
- *
- * cloneType must be defined for any Chisel object extending Data.
- * It is responsible for constructing a basic copy of the object being cloned.
- *
- * @return a copy of the object.
- */
- def cloneType: this.type
-
- /** Internal API; Chisel users should look at chisel3.chiselTypeOf(...).
- *
- * Returns a copy of this data type, with hardware bindings (if any) removed.
- * Directionality data is still preserved.
- */
- private[chisel3] def cloneTypeFull: this.type = {
- val clone = this.cloneType.asInstanceOf[this.type] // get a fresh object, without bindings
- // Only the top-level direction needs to be fixed up, cloneType should do the rest
- clone.specifiedDirection = specifiedDirection
- clone
- }
-
- /** Connect this $coll to that $coll mono-directionally and element-wise.
- *
- * This uses the [[MonoConnect]] algorithm.
- *
- * @param that the $coll to connect to
- * @group Connect
- */
- final def := (that: Data)(implicit sourceInfo: SourceInfo, connectionCompileOptions: CompileOptions): Unit = this.connect(that)(sourceInfo, connectionCompileOptions) // scalastyle:ignore line.size.limit
-
- /** Connect this $coll to that $coll bi-directionally and element-wise.
- *
- * This uses the [[BiConnect]] algorithm.
- *
- * @param that the $coll to connect to
- * @group Connect
- */
- final def <> (that: Data)(implicit sourceInfo: SourceInfo, connectionCompileOptions: CompileOptions): Unit = this.bulkConnect(that)(sourceInfo, connectionCompileOptions) // scalastyle:ignore line.size.limit
-
- @chiselRuntimeDeprecated
- @deprecated("litArg is deprecated, use litOption or litTo*Option", "chisel3.2")
- def litArg(): Option[LitArg] = topBindingOpt match {
- case Some(ElementLitBinding(litArg)) => Some(litArg)
- case Some(BundleLitBinding(litMap)) => None // this API does not support Bundle literals
- case _ => None
- }
-
- def isLit(): Boolean = litArg.isDefined
-
- /**
- * If this is a literal that is representable as bits, returns the value as a BigInt.
- * If not a literal, or not representable as bits (for example, is or contains Analog), returns None.
- */
- def litOption(): Option[BigInt]
-
- /**
- * Returns the literal value if this is a literal that is representable as bits, otherwise crashes.
- */
- def litValue(): BigInt = litOption.get
-
- /** Returns the width, in bits, if currently known. */
- final def getWidth: Int =
- if (isWidthKnown) width.get else throwException(s"Width of $this is unknown!")
- /** 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
-
- /** Packs the value of this object as plain Bits.
- *
- * This performs the inverse operation of fromBits(Bits).
- */
- @chiselRuntimeDeprecated
- @deprecated("Best alternative, .asUInt()", "chisel3")
- def toBits(implicit compileOptions: CompileOptions): UInt = do_asUInt(DeprecatedSourceInfo, compileOptions)
-
- /** Does a reinterpret cast of the bits in this node into the format that provides.
- * Returns a new Wire of that type. Does not modify existing nodes.
- *
- * x.asTypeOf(that) performs the inverse operation of x := that.toBits.
- *
- * @note bit widths are NOT checked, may pad or drop bits from input
- * @note that should have known widths
- */
- def asTypeOf[T <: Data](that: T): T = macro SourceInfoTransform.thatArg
-
- /** @group SourceInfoTransformMacro */
- def do_asTypeOf[T <: Data](that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T = {
- val thatCloned = Wire(that.cloneTypeFull)
- thatCloned.connectFromBits(this.asUInt())
- thatCloned
- }
-
- /** Assigns this node from Bits type. Internal implementation for asTypeOf.
- */
- private[core] def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo,
- compileOptions: CompileOptions): Unit
-
- /** 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
-
- /** @group SourceInfoTransformMacro */
- def do_asUInt(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt
-
- /** Default pretty printing */
- def toPrintable: Printable
-}
-
-trait WireFactory {
- /** Construct a [[Wire]] from a type template
- * @param t The template from which to construct this wire
- */
- def apply[T <: Data](t: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T = {
- if (compileOptions.declaredTypeMustBeUnbound) {
- requireIsChiselType(t, "wire type")
- }
- val x = t.cloneTypeFull
-
- // Bind each element of x to being a Wire
- x.bind(WireBinding(Builder.forcedUserModule))
-
- pushCommand(DefWire(sourceInfo, x))
- if (!compileOptions.explicitInvalidate) {
- pushCommand(DefInvalid(sourceInfo, x.ref))
- }
-
- x
- }
-}
-
-/** Utility for constructing hardware wires
- *
- * The width of a `Wire` (inferred or not) is copied from the type template
- * {{{
- * val w0 = Wire(UInt()) // width is inferred
- * val w1 = Wire(UInt(8.W)) // width is set to 8
- *
- * val w2 = Wire(Vec(4, UInt())) // width is inferred
- * val w3 = Wire(Vec(4, UInt(8.W))) // width of each element is set to 8
- *
- * class MyBundle {
- * val unknown = UInt()
- * val known = UInt(8.W)
- * }
- * val w4 = Wire(new MyBundle)
- * // Width of w4.unknown is inferred
- * // Width of w4.known is set to 8
- * }}}
- *
- */
-object Wire extends WireFactory
-
-
-/** Utility for constructing hardware wires with a default connection
- *
- * The two forms of `WireDefault` differ in how the type and width of the resulting [[Wire]] are
- * specified.
- *
- * ==Single Argument==
- * The single argument form uses the argument to specify both the type and default connection. For
- * non-literal [[Bits]], the width of the [[Wire]] will be inferred. For literal [[Bits]] and all
- * non-Bits arguments, the type will be copied from the argument. See the following examples for
- * more details:
- *
- * 1. Literal [[Bits]] initializer: width will be set to match
- * {{{
- * val w1 = WireDefault(1.U) // width will be inferred to be 1
- * val w2 = WireDefault(1.U(8.W)) // width is set to 8
- * }}}
- *
- * 2. Non-Literal [[Element]] initializer - width will be inferred
- * {{{
- * val x = Wire(UInt())
- * val y = Wire(UInt(8.W))
- * val w1 = WireDefault(x) // width will be inferred
- * val w2 = WireDefault(y) // width will be inferred
- * }}}
- *
- * 3. [[Aggregate]] initializer - width will be set to match the aggregate
- *
- * {{{
- * class MyBundle {
- * val unknown = UInt()
- * val known = UInt(8.W)
- * }
- * val w1 = Wire(new MyBundle)
- * val w2 = WireDefault(w1)
- * // Width of w2.unknown is inferred
- * // Width of w2.known is set to 8
- * }}}
- *
- * ==Double Argument==
- * The double argument form allows the type of the [[Wire]] and the default connection to be
- * specified independently.
- *
- * The width inference semantics for `WireDefault` with two arguments match those of [[Wire]]. The
- * first argument to `WireDefault` is the type template which defines the width of the `Wire` in
- * exactly the same way as the only argument to [[Wire]].
- *
- * More explicitly, you can reason about `WireDefault` with multiple arguments as if it were defined
- * as:
- * {{{
- * def WireDefault[T <: Data](t: T, init: T): T = {
- * val x = Wire(t)
- * x := init
- * x
- * }
- * }}}
- *
- * @note The `Default` in `WireDefault` refers to a `default` connection. This is in contrast to
- * [[RegInit]] where the `Init` refers to a value on reset.
- */
-object WireDefault {
-
- private def applyImpl[T <: Data](t: T, init: Data)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T = { // scalastyle:ignore line.size.limit
- implicit val noSourceInfo = UnlocatableSourceInfo
- val x = Wire(t)
- requireIsHardware(init, "wire initializer")
- x := init
- x
- }
-
- /** Construct a [[Wire]] with a type template and a [[chisel3.DontCare]] default
- * @param t The type template used to construct this [[Wire]]
- * @param init The default connection to this [[Wire]], can only be [[DontCare]]
- * @note This is really just a specialized form of `apply[T <: Data](t: T, init: T): T` with [[DontCare]] as `init`
- */
- def apply[T <: Data](t: T, init: DontCare.type)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T = { // scalastyle:ignore line.size.limit
- applyImpl(t, init)
- }
-
- /** Construct a [[Wire]] with a type template and a default connection
- * @param t The type template used to construct this [[Wire]]
- * @param init The hardware value that will serve as the default value
- */
- def apply[T <: Data](t: T, init: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T = {
- applyImpl(t, init)
- }
-
- /** Construct a [[Wire]] with a default connection
- * @param init The hardware value that will serve as a type template and default value
- */
- def apply[T <: Data](init: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T = {
- val model = (init match {
- // If init is a literal without forced width OR any non-literal, let width be inferred
- case init: Bits if !init.litIsForcedWidth.getOrElse(false) => init.cloneTypeWidth(Width())
- case _ => init.cloneTypeFull
- }).asInstanceOf[T]
- apply(model, init)
- }
-}
-
-/** RHS (source) for Invalidate API.
- * Causes connection logic to emit a DefInvalid when connected to an output port (or wire).
- */
-private[chisel3] object DontCare extends Element {
- // This object should be initialized before we execute any user code that refers to it,
- // otherwise this "Chisel" object will end up on the UserModule's id list.
- // We make it private to chisel3 so it has to be accessed through the package object.
-
- private[chisel3] override val width: Width = UnknownWidth()
-
- bind(DontCareBinding(), SpecifiedDirection.Output)
- override def cloneType: this.type = DontCare
-
- override def toString: String = "DontCare()"
-
- override def litOption: Option[BigInt] = None
-
- def toPrintable: Printable = PString("DONTCARE")
-
- private[core] def connectFromBits(that: chisel3.core.Bits)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Unit = { // scalastyle:ignore line.size.limit
- Builder.error("connectFromBits: DontCare cannot be a connection sink (LHS)")
- }
-
- def do_asUInt(implicit sourceInfo: chisel3.internal.sourceinfo.SourceInfo, compileOptions: CompileOptions): chisel3.core.UInt = { // scalastyle:ignore line.size.limit
- Builder.error("DontCare does not have a UInt representation")
- 0.U
- }
- // DontCare's only match themselves.
- private[core] def typeEquivalent(that: chisel3.core.Data): Boolean = that == DontCare
-}
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Mem.scala b/chiselFrontend/src/main/scala/chisel3/core/Mem.scala
deleted file mode 100644
index d44178ad..00000000
--- a/chiselFrontend/src/main/scala/chisel3/core/Mem.scala
+++ /dev/null
@@ -1,216 +0,0 @@
-// See LICENSE for license details.
-
-package chisel3.core
-
-import scala.language.experimental.macros
-
-import chisel3.internal._
-import chisel3.internal.Builder.pushCommand
-import chisel3.internal.firrtl._
-import chisel3.internal.sourceinfo.{SourceInfo, SourceInfoTransform, UnlocatableSourceInfo, MemTransform}
-import chisel3.SourceInfoDoc
-
-object Mem {
- // scalastyle:off line.size.limit
- @chiselRuntimeDeprecated
- @deprecated("Mem argument order should be size, t; this will be removed by the official release", "chisel3")
- def apply[T <: Data](t: T, size: BigInt)(implicit compileOptions: CompileOptions): Mem[T] = do_apply(size, t)(UnlocatableSourceInfo, compileOptions)
-
- // scalastyle:off line.size.limit
- @chiselRuntimeDeprecated
- @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)(implicit compileOptions: CompileOptions): Mem[T] = do_apply(size, t)(UnlocatableSourceInfo, compileOptions)
-
- /** Creates a combinational/asynchronous-read, sequential/synchronous-write [[Mem]].
- *
- * @param size number of elements in the memory
- * @param t data type of memory element
- */
- def apply[T <: Data](size: BigInt, t: T): Mem[T] = macro MemTransform.apply[T]
-
- /** Creates a combinational/asynchronous-read, sequential/synchronous-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]
-
- /** @group SourceInfoTransformMacro */
- def do_apply[T <: Data](size: BigInt, t: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Mem[T] = {
- if (compileOptions.declaredTypeMustBeUnbound) {
- requireIsChiselType(t, "memory type")
- }
- val mt = t.cloneTypeFull
- val mem = new Mem(mt, size)
- pushCommand(DefMemory(sourceInfo, mem, mt, size))
- mem
- }
-
- /** @group SourceInfoTransformMacro */
- def do_apply[T <: Data](size: Int, t: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Mem[T] =
- do_apply(BigInt(size), t)(sourceInfo, compileOptions)
-}
-
-sealed abstract class MemBase[T <: Data](t: T, val length: BigInt) extends HasId with NamedComponent with SourceInfoDoc {
- // 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(x: BigInt): T = macro SourceInfoTransform.xArg
-
- /** Creates a read accessor into the memory with static addressing. See the
- * class documentation of the memory for more detailed information.
- */
- def apply(x: Int): T = macro SourceInfoTransform.xArg
-
- /** @group SourceInfoTransformMacro */
- def do_apply(idx: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T = {
- require(idx >= 0 && idx < length)
- apply(idx.asUInt)
- }
-
- /** @group SourceInfoTransformMacro */
- def do_apply(idx: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T =
- do_apply(BigInt(idx))(sourceInfo, compileOptions)
-
- /** Creates a read/write accessor into the memory with dynamic addressing.
- * See the class documentation of the memory for more detailed information.
- */
- def apply(x: UInt): T = macro SourceInfoTransform.xArg
-
- /** @group SourceInfoTransformMacro */
- def do_apply(idx: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T =
- makePort(sourceInfo, 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(x: UInt): T = macro SourceInfoTransform.xArg
-
- /** @group SourceInfoTransformMacro */
- def do_read(idx: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T =
- makePort(sourceInfo, 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)(implicit compileOptions: CompileOptions): 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 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
- */
- def write(idx: UInt, data: T, mask: Seq[Bool]) (implicit evidence: T <:< Vec[_], compileOptions: CompileOptions): 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)(implicit compileOptions: CompileOptions): T = {
- requireIsHardware(idx, "memory port index")
- val i = Vec.truncateIndex(idx, length)(sourceInfo, compileOptions)
-
- val port = pushCommand(
- DefMemPort(sourceInfo,
- t.cloneTypeFull, Node(this), dir, i.ref, Builder.forcedClock.ref)
- ).id
- // Bind each element of port to being a MemoryPort
- port.bind(MemoryPortBinding(Builder.forcedUserModule))
- port
- }
-}
-
-/** A combinational/asynchronous-read, sequential/synchronous-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] private (t: T, length: BigInt) extends MemBase(t, length)
-
-object SyncReadMem {
- @chiselRuntimeDeprecated
- @deprecated("SeqMem/SyncReadMem argument order should be size, t; this will be removed by the official release", "chisel3")
- def apply[T <: Data](t: T, size: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SyncReadMem[T] = do_apply(size, t)
-
- @chiselRuntimeDeprecated
- @deprecated("SeqMem/SyncReadMem argument order should be size, t; this will be removed by the official release", "chisel3")
- def apply[T <: Data](t: T, size: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SyncReadMem[T] = do_apply(size, t)
-
- /** Creates a sequential/synchronous-read, sequential/synchronous-write [[SyncReadMem]].
- *
- * @param size number of elements in the memory
- * @param t data type of memory element
- */
- def apply[T <: Data](size: BigInt, t: T): SyncReadMem[T] = macro MemTransform.apply[T]
-
- /** Creates a sequential/synchronous-read, sequential/synchronous-write [[SyncReadMem]].
- *
- * @param size number of elements in the memory
- * @param t data type of memory element
- */
- def apply[T <: Data](size: Int, t: T): SyncReadMem[T] = macro MemTransform.apply[T]
-
- /** @group SourceInfoTransformMacro */
- def do_apply[T <: Data](size: BigInt, t: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SyncReadMem[T] = {
- if (compileOptions.declaredTypeMustBeUnbound) {
- requireIsChiselType(t, "memory type")
- }
- val mt = t.cloneTypeFull
- val mem = new SyncReadMem(mt, size)
- pushCommand(DefSeqMemory(sourceInfo, mem, mt, size))
- mem
- }
-
- /** @group SourceInfoTransformMacro */
- def do_apply[T <: Data](size: Int, t: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SyncReadMem[T] =
- do_apply(BigInt(size), t)(sourceInfo, compileOptions)
-}
-
-/** A sequential/synchronous-read, sequential/synchronous-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 SyncReadMem[T <: Data] private (t: T, n: BigInt) extends MemBase[T](t, n) {
- def read(x: UInt, en: Bool): T = macro SourceInfoTransform.xEnArg
-
- /** @group SourceInfoTransformMacro */
- def do_read(addr: UInt, enable: Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T = {
- val a = Wire(UInt())
- a := DontCare
- var port: Option[T] = None
- when (enable) {
- a := addr
- port = Some(read(a))
- }
- port.get
- }
-}
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Module.scala b/chiselFrontend/src/main/scala/chisel3/core/Module.scala
deleted file mode 100644
index 5cd48a6a..00000000
--- a/chiselFrontend/src/main/scala/chisel3/core/Module.scala
+++ /dev/null
@@ -1,355 +0,0 @@
-// See LICENSE for license details.
-
-package chisel3.core
-
-import scala.collection.immutable.ListMap
-import scala.collection.mutable.{ArrayBuffer, HashMap}
-import scala.collection.JavaConversions._
-import scala.language.experimental.macros
-
-import java.util.IdentityHashMap
-
-import chisel3.internal._
-import chisel3.internal.Builder._
-import chisel3.internal.firrtl._
-import chisel3.internal.sourceinfo.{InstTransform, SourceInfo}
-import chisel3.SourceInfoDoc
-
-import _root_.firrtl.annotations.{CircuitName, ModuleName}
-
-object Module extends SourceInfoDoc {
- /** A wrapper method that all Module instantiations must be wrapped in
- * (necessary to help Chisel track internal state).
- *
- * @param bc the Module being created
- *
- * @return the input module `m` with Chisel metadata properly set
- */
- def apply[T <: BaseModule](bc: => T): T = macro InstTransform.apply[T]
-
- /** @group SourceInfoTransformMacro */
- def do_apply[T <: BaseModule](bc: => T)
- (implicit sourceInfo: SourceInfo,
- compileOptions: CompileOptions): T = {
- if (Builder.readyForModuleConstr) {
- throwException("Error: Called Module() twice without instantiating a Module." +
- sourceInfo.makeMessage(" See " + _))
- }
- Builder.readyForModuleConstr = true
-
- val parent = Builder.currentModule
- val whenDepth: Int = Builder.whenDepth
-
- // Save then clear clock and reset to prevent leaking scope, must be set again in the Module
- val (saveClock, saveReset) = (Builder.currentClock, Builder.currentReset)
- Builder.currentClock = None
- Builder.currentReset = None
-
- // Execute the module, this has the following side effects:
- // - set currentModule
- // - unset readyForModuleConstr
- // - reset whenDepth to 0
- // - set currentClockAndReset
- val module: T = bc // bc is actually evaluated here
-
- if (Builder.whenDepth != 0) {
- throwException("Internal Error! when() scope depth is != 0, this should have been caught!")
- }
- if (Builder.readyForModuleConstr) {
- throwException("Error: attempted to instantiate a Module, but nothing happened. " +
- "This is probably due to rewrapping a Module instance with Module()." +
- sourceInfo.makeMessage(" See " + _))
- }
- Builder.currentModule = parent // Back to parent!
- Builder.whenDepth = whenDepth
- Builder.currentClock = saveClock // Back to clock and reset scope
- Builder.currentReset = saveReset
-
- val component = module.generateComponent()
- Builder.components += component
-
- // Handle connections at enclosing scope
- if(!Builder.currentModule.isEmpty) {
- pushCommand(DefInstance(sourceInfo, module, component.ports))
- module.initializeInParent(compileOptions)
- }
- module
- }
-
- /** Returns the implicit Clock */
- def clock: Clock = Builder.forcedClock
- /** Returns the implicit Reset */
- def reset: Reset = Builder.forcedReset
- /** Returns the current Module */
- def currentModule: Option[BaseModule] = Builder.currentModule
-}
-
-object IO {
- /** Constructs a port for the current Module
- *
- * 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 must be a chisel type and not be bound to hardware.
- *
- * Also registers a Data as a port, also performing bindings. Cannot be called once ports are
- * requested (so that all calls to ports will return the same information).
- * Internal API.
- */
- def apply[T<:Data](iodef: T): T = {
- val module = Module.currentModule.get // Impossible to fail
- require(!module.isClosed, "Can't add more ports after module close")
- requireIsChiselType(iodef, "io type")
-
- // Clone the IO so we preserve immutability of data types
- val iodefClone = try {
- iodef.cloneTypeFull
- } catch {
- // For now this is going to be just a deprecation so we don't suddenly break everyone's code
- case e: AutoClonetypeException =>
- Builder.deprecated(e.getMessage, Some(s"${iodef.getClass}"))
- iodef
- }
- module.bindIoInPlace(iodefClone)
- iodefClone
- }
-}
-
-object BaseModule {
- private[chisel3] class ClonePorts (elts: Data*)(implicit compileOptions: CompileOptions) extends Record {
- val elements = ListMap(elts.map(d => d.instanceName -> d.cloneTypeFull): _*)
- def apply(field: String) = elements(field)
- override def cloneType = (new ClonePorts(elts: _*)).asInstanceOf[this.type]
- }
-
- private[chisel3] def cloneIORecord(proto: BaseModule)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): ClonePorts = {
- require(proto.isClosed, "Can't clone a module before module close")
- val clonePorts = new ClonePorts(proto.getModulePorts: _*)
- clonePorts.bind(WireBinding(Builder.forcedUserModule))
- val cloneInstance = new DefInstance(sourceInfo, proto, proto._component.get.ports) {
- override def name = clonePorts.getRef.name
- }
- pushCommand(cloneInstance)
- if (!compileOptions.explicitInvalidate) {
- pushCommand(DefInvalid(sourceInfo, clonePorts.ref))
- }
- if (proto.isInstanceOf[MultiIOModule]) {
- clonePorts("clock") := Module.clock
- clonePorts("reset") := Module.reset
- }
- clonePorts
- }
-}
-
-/** Abstract base class for Modules, an instantiable organizational unit for RTL.
- */
-// TODO: seal this?
-abstract class BaseModule extends HasId {
- //
- // Builder Internals - this tracks which Module RTL construction belongs to.
- //
- if (!Builder.readyForModuleConstr) {
- throwException("Error: attempted to instantiate a Module without wrapping it in Module().")
- }
- readyForModuleConstr = false
-
- Builder.currentModule = Some(this)
- Builder.whenDepth = 0
-
- //
- // Module Construction Internals
- //
- protected var _closed = false
-
- /** Internal check if a Module is closed */
- private[core] def isClosed = _closed
-
- // Fresh Namespace because in Firrtl, Modules namespaces are disjoint with the global namespace
- private[core] val _namespace = Namespace.empty
- private val _ids = ArrayBuffer[HasId]()
- private[chisel3] def addId(d: HasId) {
- require(!_closed, "Can't write to module after module close")
- _ids += d
- }
- protected def getIds = {
- require(_closed, "Can't get ids before module close")
- _ids.toSeq
- }
-
- private val _ports = new ArrayBuffer[Data]()
- // getPorts unfortunately already used for tester compatibility
- protected def getModulePorts = {
- require(_closed, "Can't get ports before module close")
- _ports.toSeq
- }
-
- // These methods allow checking some properties of ports before the module is closed,
- // mainly for compatibility purposes.
- protected def portsContains(elem: Data): Boolean = _ports contains elem
- protected def portsSize: Int = _ports.size
-
- /** Generates the FIRRTL Component (Module or Blackbox) of this Module.
- * Also closes the module so no more construction can happen inside.
- */
- private[core] def generateComponent(): Component
-
- /** Sets up this module in the parent context
- */
- private[core] def initializeInParent(parentCompileOptions: CompileOptions): Unit
-
- //
- // Chisel Internals
- //
- /** Desired name of this module. Override this to give this module a custom, perhaps parametric,
- * name.
- */
- def desiredName: String = this.getClass.getName.split('.').last
-
- /** Legalized name of this module. */
- final lazy val name = try {
- Builder.globalNamespace.name(desiredName)
- } catch {
- case e: NullPointerException => throwException(
- s"Error: desiredName of ${this.getClass.getName} is null. Did you evaluate 'name' before all values needed by desiredName were available?", e) // scalastyle:ignore line.size.limit
- case t: Throwable => throw t
- }
-
- /** Returns a FIRRTL ModuleName that references this object
- * @note Should not be called until circuit elaboration is complete
- */
- final def toNamed: ModuleName = ModuleName(this.name, CircuitName(this.circuitName))
-
- /**
- * Internal API. Returns a list of this module's generated top-level ports as a map of a String
- * (FIRRTL name) to the IO object. Only valid after the module is closed.
- *
- * Note: for BlackBoxes (but not ExtModules), this returns the contents of the top-level io
- * object, consistent with what is emitted in FIRRTL.
- *
- * TODO: Use SeqMap/VectorMap when those data structures become available.
- */
- private[core] def getChiselPorts: Seq[(String, Data)] = {
- require(_closed, "Can't get ports before module close")
- _component.get.ports.map { port =>
- (port.id.getRef.asInstanceOf[ModuleIO].name, port.id)
- }
- }
-
- /** Called at the Module.apply(...) level after this Module has finished elaborating.
- * Returns a map of nodes -> names, for named nodes.
- *
- * Helper method.
- */
- protected def nameIds(rootClass: Class[_]): HashMap[HasId, String] = {
- val names = new HashMap[HasId, String]()
-
- def name(node: HasId, name: String) {
- // First name takes priority, like suggestName
- // TODO: DRYify with suggestName
- if (!names.contains(node)) {
- names.put(node, name)
- }
- }
-
- /** Scala generates names like chisel3$util$Queue$$ram for private vals
- * This extracts the part after $$ for names like this and leaves names
- * without $$ unchanged
- */
- def cleanName(name: String): String = name.split("""\$\$""").lastOption.getOrElse(name)
-
- for (m <- getPublicFields(rootClass)) {
- Builder.nameRecursively(cleanName(m.getName), m.invoke(this), name)
- }
-
- names
- }
-
- /** Compatibility function. Allows Chisel2 code which had ports without the IO wrapper to
- * compile under Bindings checks. Does nothing in non-compatibility mode.
- *
- * Should NOT be used elsewhere. This API will NOT last.
- *
- * TODO: remove this, perhaps by removing Bindings checks in compatibility mode.
- */
- def _compatAutoWrapPorts() {} // scalastyle:ignore method.name
-
- //
- // BaseModule User API functions
- //
- @deprecated("Use chisel3.experimental.annotate instead", "3.1")
- protected def annotate(annotation: ChiselAnnotation): Unit = {
- Builder.annotations += annotation
- }
-
- /** Chisel2 code didn't require the IO(...) wrapper and would assign a Chisel type directly to
- * io, then do operations on it. This binds a Chisel type in-place (mutably) as an IO.
- */
- protected def _bindIoInPlace(iodef: Data): Unit = { // scalastyle:ignore method.name
- // Compatibility code: Chisel2 did not require explicit direction on nodes
- // (unspecified treated as output, and flip on nothing was input).
- // This sets assigns the explicit directions required by newer semantics on
- // Bundles defined in compatibility mode.
- // This recursively walks the tree, and assigns directions if no explicit
- // direction given by upper-levels (override Input / Output) AND element is
- // directly inside a compatibility Bundle determined by compile options.
- def assignCompatDir(data: Data, insideCompat: Boolean): Unit = {
- data match {
- case data: Element if insideCompat => data._assignCompatibilityExplicitDirection
- case data: Element => // Not inside a compatibility Bundle, nothing to be done
- case data: Aggregate => data.specifiedDirection match {
- // Recurse into children to ensure explicit direction set somewhere
- case SpecifiedDirection.Unspecified | SpecifiedDirection.Flip => data match {
- case record: Record =>
- val compatRecord = !record.compileOptions.dontAssumeDirectionality
- record.getElements.foreach(assignCompatDir(_, compatRecord))
- case vec: Vec[_] =>
- vec.getElements.foreach(assignCompatDir(_, insideCompat))
- }
- case SpecifiedDirection.Input | SpecifiedDirection.Output => // forced assign, nothing to do
- }
- }
- }
- assignCompatDir(iodef, false)
-
- iodef.bind(PortBinding(this))
- _ports += iodef
- }
- /** Private accessor for _bindIoInPlace */
- private[core] def bindIoInPlace(iodef: Data): Unit = _bindIoInPlace(iodef)
-
- /**
- * 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 must be a chisel type and not be bound to hardware.
- *
- * Also registers a Data as a port, also performing bindings. Cannot be called once ports are
- * requested (so that all calls to ports will return the same information).
- * Internal API.
- *
- * TODO(twigg): Specifically walk the Data definition to call out which nodes
- * are problematic.
- */
- protected def IO[T<:Data](iodef: T): T = chisel3.core.IO.apply(iodef) // scalastyle:ignore method.name
-
- //
- // Internal Functions
- //
-
- /** Keep component for signal names */
- private[chisel3] var _component: Option[Component] = None
-
- /** Signal name (for simulation). */
- override def instanceName: String =
- 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/core/MonoConnect.scala b/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala
deleted file mode 100644
index 6a4ae9bf..00000000
--- a/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala
+++ /dev/null
@@ -1,246 +0,0 @@
-// See LICENSE for license details.
-
-package chisel3.core
-
-import chisel3.internal.ChiselException
-import chisel3.internal.Builder.pushCommand
-import chisel3.internal.firrtl.{Connect, DefInvalid}
-import scala.language.experimental.macros
-import chisel3.internal.sourceinfo.SourceInfo
-
-/**
-* 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 Record 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 {
- // scalastyle:off method.name public.methods.have.type
- // These are all the possible exceptions that can be thrown.
- case class MonoConnectException(message: String) extends ChiselException(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 Record missing field ($field).")
- def MismatchedException(sink: String, source: String) =
- MonoConnectException(s": Sink ($sink) and Source ($source) have different types.")
- def DontCareCantBeSink =
- MonoConnectException(": DontCare cannot be a connection sink (LHS)")
- // scalastyle:on method.name public.methods.have.type
-
- /** 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( //scalastyle:off cyclomatic.complexity method.length
- sourceInfo: SourceInfo,
- connectCompileOptions: CompileOptions,
- sink: Data,
- source: Data,
- context_mod: RawModule): Unit =
- (sink, source) match {
-
- // Handle legal element cases, note (Bool, Bool) is caught by the first two, as Bool is a UInt
- case (sink_e: Bool, source_e: UInt) =>
- elemConnect(sourceInfo, connectCompileOptions, sink_e, source_e, context_mod)
- case (sink_e: UInt, source_e: Bool) =>
- elemConnect(sourceInfo, connectCompileOptions, sink_e, source_e, context_mod)
- case (sink_e: UInt, source_e: UInt) =>
- elemConnect(sourceInfo, connectCompileOptions, sink_e, source_e, context_mod)
- case (sink_e: SInt, source_e: SInt) =>
- elemConnect(sourceInfo, connectCompileOptions, sink_e, source_e, context_mod)
- case (sink_e: FixedPoint, source_e: FixedPoint) =>
- elemConnect(sourceInfo, connectCompileOptions, sink_e, source_e, context_mod)
- case (sink_e: Clock, source_e: Clock) =>
- elemConnect(sourceInfo, connectCompileOptions, sink_e, source_e, context_mod)
- case (sink_e: EnumType, source_e: UnsafeEnum) =>
- elemConnect(sourceInfo, connectCompileOptions, sink_e, source_e, context_mod)
- case (sink_e: EnumType, source_e: EnumType) if sink_e.typeEquivalent(source_e) =>
- elemConnect(sourceInfo, connectCompileOptions, sink_e, source_e, context_mod)
- case (sink_e: UnsafeEnum, source_e: UInt) =>
- elemConnect(sourceInfo, connectCompileOptions, sink_e, source_e, context_mod)
-
- // 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 {
- implicit val compileOptions = connectCompileOptions
- connect(sourceInfo, connectCompileOptions, sink_v(idx), source_v(idx), context_mod)
- } catch {
- case MonoConnectException(message) => throw MonoConnectException(s"($idx)$message")
- }
- }
- // Handle Vec connected to DontCare. Apply the DontCare to individual elements.
- case (sink_v: Vec[Data @unchecked], DontCare) =>
- for(idx <- 0 until sink_v.length) {
- try {
- implicit val compileOptions = connectCompileOptions
- connect(sourceInfo, connectCompileOptions, sink_v(idx), source, context_mod)
- } catch {
- case MonoConnectException(message) => throw MonoConnectException(s"($idx)$message")
- }
- }
-
- // Handle Record case
- case (sink_r: Record, source_r: Record) =>
- // For each field, descend with right
- for((field, sink_sub) <- sink_r.elements) {
- try {
- source_r.elements.get(field) match {
- case Some(source_sub) => connect(sourceInfo, connectCompileOptions, sink_sub, source_sub, context_mod)
- case None => {
- if (connectCompileOptions.connectFieldsMustMatch) {
- throw MissingFieldException(field)
- }
- }
- }
- } catch {
- case MonoConnectException(message) => throw MonoConnectException(s".$field$message")
- }
- }
- // Handle Record connected to DontCare. Apply the DontCare to individual elements.
- case (sink_r: Record, DontCare) =>
- // For each field, descend with right
- for((field, sink_sub) <- sink_r.elements) {
- try {
- connect(sourceInfo, connectCompileOptions, sink_sub, source, context_mod)
- } catch {
- case MonoConnectException(message) => throw MonoConnectException(s".$field$message")
- }
- }
-
- // Source is DontCare - it may be connected to anything. It generates a defInvalid for the sink.
- case (sink, DontCare) => pushCommand(DefInvalid(sourceInfo, sink.lref))
- // DontCare as a sink is illegal.
- case (DontCare, _) => throw DontCareCantBeSink
- // 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 = {
- // If the source is a DontCare, generate a DefInvalid for the sink,
- // otherwise, issue a Connect.
- source.topBinding match {
- case b: DontCareBinding => pushCommand(DefInvalid(sourceInfo, sink.lref))
- case _ => 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, connectCompileOptions: CompileOptions, sink: Element, source: Element, context_mod: RawModule): Unit = { // scalastyle:ignore line.size.limit
- import BindingDirection.{Internal, 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: BaseModule = sink.topBinding.location.getOrElse(throw UnwritableSinkException)
- val source_mod: BaseModule = source.topBinding.location.getOrElse(context_mod)
-
- val sink_direction = BindingDirection.from(sink.topBinding, sink.direction)
- val source_direction = BindingDirection.from(source.topBinding, source.direction)
-
- // 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): @unchecked) match {
- // SINK SOURCE
- // CURRENT MOD CURRENT MOD
- case (Output, _) => issueConnect(sink, source)
- case (Internal, _) => issueConnect(sink, source)
- case (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): @unchecked) match {
- // SINK SOURCE
- // CURRENT MOD CHILD MOD
- case (Internal, Output) => issueConnect(sink, source)
- case (Internal, Input) => issueConnect(sink, source)
- case (Output, Output) => issueConnect(sink, source)
- case (Output, Input) => issueConnect(sink, source)
- case (_, Internal) => {
- if (!(connectCompileOptions.dontAssumeDirectionality)) {
- issueConnect(sink, source)
- } else {
- throw UnreadableSourceException
- }
- }
- case (Input, Output) if (!(connectCompileOptions.dontTryConnectionsSwapped)) => issueConnect(source, sink) // scalastyle:ignore line.size.limit
- case (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): @unchecked) match {
- // SINK SOURCE
- // CHILD MOD CURRENT MOD
- case (Input, _) => issueConnect(sink, source)
- case (Output, _) => throw UnwritableSinkException
- case (Internal, _) => 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): @unchecked) match {
- // SINK SOURCE
- // CHILD MOD CHILD MOD
- case (Input, Input) => issueConnect(sink, source)
- case (Input, Output) => issueConnect(sink, source)
- case (Output, _) => throw UnwritableSinkException
- case (_, Internal) => {
- if (!(connectCompileOptions.dontAssumeDirectionality)) {
- issueConnect(sink, source)
- } else {
- throw UnreadableSourceException
- }
- }
- case (Internal, _) => 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/MultiClock.scala b/chiselFrontend/src/main/scala/chisel3/core/MultiClock.scala
deleted file mode 100644
index aaa03d78..00000000
--- a/chiselFrontend/src/main/scala/chisel3/core/MultiClock.scala
+++ /dev/null
@@ -1,70 +0,0 @@
-// See LICENSE for license details.
-
-package chisel3.core
-
-import chisel3.internal._
-
-import scala.language.experimental.macros
-
-object withClockAndReset { // scalastyle:ignore object.name
- /** Creates a new Clock and Reset scope
- *
- * @param clock the new implicit Clock
- * @param reset the new implicit Reset
- * @param block the block of code to run with new implicit Clock and Reset
- * @return the result of the block
- */
- def apply[T](clock: Clock, reset: Reset)(block: => T): T = {
- // Save parentScope
- val parentClock = Builder.currentClock
- val parentReset = Builder.currentReset
-
- Builder.currentClock = Some(clock)
- Builder.currentReset = Some(reset)
-
- val res = block // execute block
-
- // Return to old scope
- Builder.currentClock = parentClock
- Builder.currentReset = parentReset
- res
- }
-}
-
-object withClock { // scalastyle:ignore object.name
- /** Creates a new Clock scope
- *
- * @param clock the new implicit Clock
- * @param block the block of code to run with new implicit Clock
- * @return the result of the block
- */
- def apply[T](clock: Clock)(block: => T): T = {
- // Save parentScope
- val parentClock = Builder.currentClock
- Builder.currentClock = Some(clock)
- val res = block // execute block
- // Return to old scope
- Builder.currentClock = parentClock
- res
- }
-}
-
-object withReset { // scalastyle:ignore object.name
- /** Creates a new Reset scope
- *
- * @param reset the new implicit Reset
- * @param block the block of code to run with new implicit Reset
- * @return the result of the block
- */
- def apply[T](reset: Reset)(block: => T): T = {
- // Save parentScope
- val parentReset = Builder.currentReset
- Builder.currentReset = Some(reset)
- val res = block // execute block
- // Return to old scope
- Builder.currentReset = parentReset
- res
- }
-
-}
-
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Mux.scala b/chiselFrontend/src/main/scala/chisel3/core/Mux.scala
deleted file mode 100644
index 7dd1b98b..00000000
--- a/chiselFrontend/src/main/scala/chisel3/core/Mux.scala
+++ /dev/null
@@ -1,51 +0,0 @@
-// See LICENSE for license details.
-
-package chisel3.core
-
-import scala.language.experimental.macros
-
-import chisel3.internal._
-import chisel3.internal.Builder.{pushOp}
-import chisel3.internal.sourceinfo.{SourceInfo, MuxTransform}
-import chisel3.internal.firrtl._
-import chisel3.internal.firrtl.PrimOp._
-import chisel3.SourceInfoDoc
-
-object Mux extends SourceInfoDoc {
- /** 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 === 3.U, 3.U(4.W), 0.U(4.W))
- * }}}
- */
- def apply[T <: Data](cond: Bool, con: T, alt: T): T = macro MuxTransform.apply[T]
-
- /** @group SourceInfoTransformMacro */
- def do_apply[T <: Data](cond: Bool, con: T, alt: T)(implicit sourceInfo: SourceInfo,
- compileOptions: CompileOptions): T = {
- requireIsHardware(cond, "mux condition")
- requireIsHardware(con, "mux true value")
- requireIsHardware(alt, "mux false value")
- val d = cloneSupertype(Seq(con, alt), "Mux")
- val conRef = con match { // this matches chisel semantics (DontCare as object) to firrtl semantics (invalidate)
- case DontCare =>
- val dcWire = Wire(d)
- dcWire := DontCare
- dcWire.ref
- case _ => con.ref
- }
- val altRef = alt match {
- case DontCare =>
- val dcWire = Wire(d)
- dcWire := DontCare
- dcWire.ref
- case _ => alt.ref
- }
- pushOp(DefPrim(sourceInfo, d, MultiplexOp, cond.ref, conRef, altRef))
- }
-}
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Printable.scala b/chiselFrontend/src/main/scala/chisel3/core/Printable.scala
deleted file mode 100644
index c724f682..00000000
--- a/chiselFrontend/src/main/scala/chisel3/core/Printable.scala
+++ /dev/null
@@ -1,179 +0,0 @@
-// 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"..."`. Printable string interpolation is
- * similar to [[https://docs.scala-lang.org/overviews/core/string-interpolation.html String
- * interpolation in Scala]] For example:
- * {{{
- * printf(p"The value of wire = \$wire\n")
- * }}}
- * This is equivalent to writing:
- * {{{
- * printf(p"The value of wire = %d\n", wire)
- * }}}
- * All Chisel data types have a method `.toPrintable` that gives a default pretty print that can be
- * accessed via `p"..."`. This works even for aggregate types, for example:
- * {{{
- * val myVec = VecInit(5.U, 10.U, 13.U)
- * printf(p"myVec = \$myVec\n")
- * // myVec = Vec(5, 10, 13)
- *
- * val myBundle = Wire(new Bundle {
- * val foo = UInt()
- * val bar = UInt()
- * })
- * myBundle.foo := 3.U
- * myBundle.bar := 11.U
- * printf(p"myBundle = \$myBundle\n")
- * // myBundle = Bundle(a -> 3, b -> 11)
- * }}}
- * Users can override the default behavior of `.toPrintable` in custom [[Bundle]] and [[Record]]
- * types.
- */
-// 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 {
- /** 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(ctx: Component): (String, Iterable[String])
- /** Allow for appending Printables like Strings */
- final def +(that: Printable): Printables = Printables(List(this, that))
- /** Allow for appending Strings to Printables */
- final def +(that: String): Printables = Printables(List(this, PString(that)))
-}
-object Printable {
- /** Pack standard printf fmt, args* style into Printable
- */
- def pack(fmt: String, data: Data*): Printable = { // scalastyle:ignore method.length
- 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(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(ctx: Component): (String, Iterable[String]) =
- (str replaceAll ("%", "%%"), List.empty)
-}
-/** Superclass for Firrtl format specifiers for Bits */
-sealed abstract class FirrtlFormat(private[chisel3] val specifier: Char) extends Printable {
- def bits: Bits
- def unpack(ctx: Component): (String, Iterable[String]) = {
- (s"%$specifier", List(bits.ref.fullName(ctx)))
- }
-}
-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(ctx: Component): (String, Iterable[String]) = (data.ref.name, List.empty)
-}
-/** Put full name within parent namespace (eg. bundleName.field) */
-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(ctx: Component): (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
deleted file mode 100644
index 5c2f89e9..00000000
--- a/chiselFrontend/src/main/scala/chisel3/core/Printf.scala
+++ /dev/null
@@ -1,100 +0,0 @@
-// See LICENSE for license details.
-
-package chisel3.core
-
-import scala.language.experimental.macros
-
-import chisel3.internal._
-import chisel3.internal.Builder.pushCommand
-import chisel3.internal.firrtl._
-import chisel3.internal.sourceinfo.SourceInfo
-
-/** Prints a message in simulation
- *
- * See apply methods for use
- */
-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
- *
- * Prints a message every cycle. If defined within the scope of a [[when]] block, the message
- * will only be printed on cycles that the when condition is true.
- *
- * 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), uses the current default clock
- * and reset. These can be overriden with [[withClockAndReset]].
- *
- * ==Format Strings==
- *
- * This method expects a ''format string'' and an ''argument list'' in a similar style to printf
- * in C. The format string expects a [[scala.Predef.String String]] that may contain ''format
- * specifiers'' For example:
- * {{{
- * printf("myWire has the value %d\n", myWire)
- * }}}
- * This prints the string "myWire has the value " followed by the current value of `myWire` (in
- * decimal, followed by a newline.
- *
- * There must be exactly as many arguments as there are format specifiers
- *
- * ===Format Specifiers===
- *
- * Format specifiers are prefixed by `%`. If you wish to print a literal `%`, use `%%`.
- * - `%d` - Decimal
- * - `%x` - Hexadecimal
- * - `%b` - Binary
- * - `%c` - 8-bit Character
- * - `%n` - Name of a signal
- * - `%N` - Full name of a leaf signal (in an aggregate)
- *
- * @param fmt printf format string
- * @param data format string varargs containing data to print
- */
- def apply(fmt: String, data: Bits*)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Unit =
- apply(Printable.pack(fmt, data:_*))
- /** Prints a message in simulation
- *
- * Prints a message every cycle. If defined within the scope of a [[when]] block, the message
- * will only be printed on cycles that the when condition is true.
- *
- * 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), uses the current default clock
- * and reset. These can be overriden with [[withClockAndReset]].
- *
- * @see [[Printable]] documentation
- * @param pable [[Printable]] to print
- */
- def apply(pable: Printable)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Unit = {
- when (!Module.reset.asBool) {
- printfWithoutReset(pable)
- }
- }
-
- private[chisel3] def printfWithoutReset(pable: Printable)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Unit = { // scalastyle:ignore line.size.limit
- val clock = Builder.forcedClock
- pushCommand(Printf(sourceInfo, clock.ref, pable))
- }
- private[chisel3] def printfWithoutReset(fmt: String, data: Bits*)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Unit = // scalastyle:ignore line.size.limit
- printfWithoutReset(Printable.pack(fmt, data:_*))
-}
diff --git a/chiselFrontend/src/main/scala/chisel3/core/RawModule.scala b/chiselFrontend/src/main/scala/chisel3/core/RawModule.scala
deleted file mode 100644
index b224d9a3..00000000
--- a/chiselFrontend/src/main/scala/chisel3/core/RawModule.scala
+++ /dev/null
@@ -1,255 +0,0 @@
-// See LICENSE for license details.
-
-package chisel3.core
-
-import scala.collection.mutable.{ArrayBuffer, HashMap}
-import scala.collection.JavaConversions._
-import scala.language.experimental.macros
-
-import chisel3.internal._
-import chisel3.internal.Builder._
-import chisel3.internal.firrtl._
-import chisel3.internal.firrtl.{Command => _, _}
-import chisel3.internal.sourceinfo.UnlocatableSourceInfo
-
-/** Abstract base class for Modules that contain Chisel RTL.
- * This abstract base class is a user-defined module which does not include implicit clock and reset and supports
- * multiple IO() declarations.
- */
-abstract class RawModule(implicit moduleCompileOptions: CompileOptions)
- extends BaseModule {
- //
- // RTL construction internals
- //
- private val _commands = ArrayBuffer[Command]()
- private[chisel3] def addCommand(c: Command) {
- require(!_closed, "Can't write to module after module close")
- _commands += c
- }
- protected def getCommands = {
- require(_closed, "Can't get commands before module close")
- _commands.toSeq
- }
-
- //
- // Other Internal Functions
- //
- // For debuggers/testers, TODO: refactor out into proper public API
- private var _firrtlPorts: Option[Seq[firrtl.Port]] = None
- lazy val getPorts = _firrtlPorts.get
-
- val compileOptions = moduleCompileOptions
-
- private[chisel3] def namePorts(names: HashMap[HasId, String]): Unit = {
- for (port <- getModulePorts) {
- port.suggestedName.orElse(names.get(port)) match {
- case Some(name) =>
- if (_namespace.contains(name)) {
- Builder.error(s"""Unable to name port $port to "$name" in $this,""" +
- " name is already taken by another port!")
- }
- port.setRef(ModuleIO(this, _namespace.name(name)))
- case None => Builder.error(s"Unable to name port $port in $this, " +
- "try making it a public field of the Module")
- }
- }
- }
-
-
- private[core] override def generateComponent(): Component = { // scalastyle:ignore cyclomatic.complexity
- require(!_closed, "Can't generate module more than once")
- _closed = true
-
- val names = nameIds(classOf[RawModule])
-
- // Ports get first naming priority, since they are part of a Module's IO spec
- namePorts(names)
-
- // Then everything else gets named
- for ((node, name) <- names) {
- node.suggestName(name)
- }
-
- // All suggestions are in, force names to every node.
- for (id <- getIds) {
- id match {
- case id: BaseModule => id.forceName(default=id.desiredName, _namespace)
- case id: MemBase[_] => id.forceName(default="_T", _namespace)
- case id: Data =>
- if (id.isSynthesizable) {
- id.topBinding match {
- case OpBinding(_) | MemoryPortBinding(_) | PortBinding(_) | RegBinding(_) | WireBinding(_) =>
- id.forceName(default="_T", _namespace)
- case _ => // don't name literals
- }
- } // else, don't name unbound types
- }
- id._onModuleClose
- }
-
- val firrtlPorts = getModulePorts map { port: Data =>
- // Special case Vec to make FIRRTL emit the direction of its
- // element.
- // Just taking the Vec's specifiedDirection is a bug in cases like
- // Vec(Flipped()), since the Vec's specifiedDirection is
- // Unspecified.
- val direction = port match {
- case v: Vec[_] => v.specifiedDirection match {
- case SpecifiedDirection.Input => SpecifiedDirection.Input
- case SpecifiedDirection.Output => SpecifiedDirection.Output
- case SpecifiedDirection.Flip => SpecifiedDirection.flip(v.sample_element.specifiedDirection)
- case SpecifiedDirection.Unspecified => v.sample_element.specifiedDirection
- }
- case _ => port.specifiedDirection
- }
-
- Port(port, direction)
- }
- _firrtlPorts = Some(firrtlPorts)
-
- // Generate IO invalidation commands to initialize outputs as unused,
- // unless the client wants explicit control over their generation.
- val invalidateCommands = {
- if (!compileOptions.explicitInvalidate) {
- getModulePorts map { port => DefInvalid(UnlocatableSourceInfo, port.ref) }
- } else {
- Seq()
- }
- }
- val component = DefModule(this, name, firrtlPorts, invalidateCommands ++ getCommands)
- _component = Some(component)
- component
- }
-
- private[core] def initializeInParent(parentCompileOptions: CompileOptions): Unit = {
- implicit val sourceInfo = UnlocatableSourceInfo
-
- if (!parentCompileOptions.explicitInvalidate) {
- for (port <- getModulePorts) {
- pushCommand(DefInvalid(sourceInfo, port.ref))
- }
- }
- }
-}
-
-/** 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).
- * This abstract base class includes an implicit clock and reset.
- *
- * @note Module instantiations must be wrapped in a Module() call.
- */
-abstract class MultiIOModule(implicit moduleCompileOptions: CompileOptions)
- extends RawModule {
- // Implicit clock and reset pins
- val clock: Clock = IO(Input(Clock()))
- val reset: Reset = IO(Input(Bool()))
-
- // Setup ClockAndReset
- Builder.currentClock = Some(clock)
- Builder.currentReset = Some(reset)
-
- private[core] override def initializeInParent(parentCompileOptions: CompileOptions): Unit = {
- implicit val sourceInfo = UnlocatableSourceInfo
-
- super.initializeInParent(parentCompileOptions)
- clock := Builder.forcedClock
- reset := Builder.forcedReset
- }
-}
-
-/** Legacy Module class that restricts IOs to just io, clock, and reset, and provides a constructor
- * for threading through explicit clock and reset.
- *
- * While this class isn't planned to be removed anytime soon (there are benefits to restricting
- * IO), the clock and reset constructors will be phased out. Recommendation is to wrap the module
- * in a withClock/withReset/withClockAndReset block, or directly hook up clock or reset IO pins.
- */
-abstract class LegacyModule(implicit moduleCompileOptions: CompileOptions)
- extends MultiIOModule {
- // These are to be phased out
- protected var override_clock: Option[Clock] = None
- protected var override_reset: Option[Bool] = None
-
- // _clock and _reset can be clock and reset in these 2ary constructors
- // once chisel2 compatibility issues are resolved
- @chiselRuntimeDeprecated
- @deprecated("Module constructor with override_clock and override_reset deprecated, use withClockAndReset", "chisel3")
- def this(override_clock: Option[Clock]=None, override_reset: Option[Bool]=None)
- (implicit moduleCompileOptions: CompileOptions) = {
- this()
- this.override_clock = override_clock
- this.override_reset = override_reset
- }
-
- @chiselRuntimeDeprecated
- @deprecated("Module constructor with override _clock deprecated, use withClock", "chisel3")
- def this(_clock: Clock)(implicit moduleCompileOptions: CompileOptions) = this(Option(_clock), None)(moduleCompileOptions) // scalastyle:ignore line.size.limit
-
- @chiselRuntimeDeprecated
- @deprecated("Module constructor with override _reset deprecated, use withReset", "chisel3")
- def this(_reset: Bool)(implicit moduleCompileOptions: CompileOptions) = this(None, Option(_reset))(moduleCompileOptions) // scalastyle:ignore line.size.limit
-
- @chiselRuntimeDeprecated
- @deprecated("Module constructor with override _clock, _reset deprecated, use withClockAndReset", "chisel3")
- def this(_clock: Clock, _reset: Bool)(implicit moduleCompileOptions: CompileOptions) = this(Option(_clock), Option(_reset))(moduleCompileOptions) // scalastyle:ignore line.size.limit
-
- // 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: Record
-
- // Allow access to bindings from the compatibility package
- protected def _compatIoPortBound() = portsContains(io)// scalastyle:ignore method.name
-
- protected override def nameIds(rootClass: Class[_]): HashMap[HasId, String] = {
- val names = super.nameIds(rootClass)
-
- // Allow IO naming without reflection
- names.put(io, "io")
- names.put(clock, "clock")
- names.put(reset, "reset")
-
- names
- }
-
- private[chisel3] override def namePorts(names: HashMap[HasId, String]): Unit = {
- for (port <- getModulePorts) {
- // This should already have been caught
- if (!names.contains(port)) throwException(s"Unable to name port $port in $this")
- val name = names(port)
- port.setRef(ModuleIO(this, _namespace.name(name)))
- }
- }
-
- private[core] override def generateComponent(): Component = {
- _compatAutoWrapPorts() // pre-IO(...) compatibility hack
-
- // Restrict IO to just io, clock, and reset
- require(io != null, "Module must have io")
- require(portsContains(io), "Module must have io wrapped in IO(...)")
- require((portsContains(clock)) && (portsContains(reset)), "Internal error, module did not have clock or reset as IO") // scalastyle:ignore line.size.limit
- require(portsSize == 3, "Module must only have io, clock, and reset as IO")
-
- super.generateComponent()
- }
-
- private[core] override def initializeInParent(parentCompileOptions: CompileOptions): Unit = {
- // Don't generate source info referencing parents inside a module, since this interferes with
- // module de-duplication in FIRRTL emission.
- implicit val sourceInfo = UnlocatableSourceInfo
-
- if (!parentCompileOptions.explicitInvalidate) {
- pushCommand(DefInvalid(sourceInfo, io.ref))
- }
-
- override_clock match {
- case Some(override_clock) => clock := override_clock
- case _ => clock := Builder.forcedClock
- }
-
- override_reset match {
- case Some(override_reset) => reset := override_reset
- case _ => reset := Builder.forcedReset
- }
- }
-}
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Reg.scala b/chiselFrontend/src/main/scala/chisel3/core/Reg.scala
deleted file mode 100644
index 747fad73..00000000
--- a/chiselFrontend/src/main/scala/chisel3/core/Reg.scala
+++ /dev/null
@@ -1,175 +0,0 @@
-// See LICENSE for license details.
-
-package chisel3.core
-
-import scala.language.experimental.macros
-
-import chisel3.internal._
-import chisel3.internal.Builder.pushCommand
-import chisel3.internal.firrtl._
-import chisel3.internal.sourceinfo.{SourceInfo}
-
-/** Utility for constructing hardware registers
- *
- * The width of a `Reg` (inferred or not) is copied from the type template
- * {{{
- * val r0 = Reg(UInt()) // width is inferred
- * val r1 = Reg(UInt(8.W)) // width is set to 8
- *
- * val r2 = Reg(Vec(4, UInt())) // width is inferred
- * val r3 = Reg(Vec(4, UInt(8.W))) // width of each element is set to 8
- *
- * class MyBundle {
- * val unknown = UInt()
- * val known = UInt(8.W)
- * }
- * val r4 = Reg(new MyBundle)
- * // Width of r4.unknown is inferred
- * // Width of r4.known is set to 8
- * }}}
- *
- */
-object Reg {
- /** Construct a [[Reg]] from a type template with no initialization value (reset is ignored).
- * Value will not change unless the [[Reg]] is given a connection.
- * @param t The template from which to construct this wire
- */
- def apply[T <: Data](t: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T = {
- if (compileOptions.declaredTypeMustBeUnbound) {
- requireIsChiselType(t, "reg type")
- }
- val reg = t.cloneTypeFull
- val clock = Node(Builder.forcedClock)
-
- reg.bind(RegBinding(Builder.forcedUserModule))
- pushCommand(DefReg(sourceInfo, reg, clock))
- reg
- }
-}
-
-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)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T = {
- val model = (next match {
- case next: Bits => next.cloneTypeWidth(Width())
- case next => next.cloneTypeFull
- }).asInstanceOf[T]
- val reg = Reg(model)
-
- requireIsHardware(next, "reg next")
- reg := next
-
- reg
- }
-
- /** 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)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T = {
- val model = (next match {
- case next: Bits => next.cloneTypeWidth(Width())
- case next => next.cloneTypeFull
- }).asInstanceOf[T]
- val reg = RegInit(model, init) // TODO: this makes NO sense
-
- requireIsHardware(next, "reg next")
- reg := next
-
- reg
- }
-}
-
-/** Utility for constructing hardware registers with an initialization value.
- *
- * The register is set to the initialization value when the current implicit `reset` is high
- *
- * The two forms of `RegInit` differ in how the type and width of the resulting [[Reg]] are
- * specified.
- *
- * ==Single Argument==
- * The single argument form uses the argument to specify both the type and reset value. For
- * non-literal [[Bits]], the width of the [[Reg]] will be inferred. For literal [[Bits]] and all
- * non-Bits arguments, the type will be copied from the argument. See the following examples for
- * more details:
- *
- * 1. Literal [[Bits]] initializer: width will be set to match
- * {{{
- * val r1 = RegInit(1.U) // width will be inferred to be 1
- * val r2 = RegInit(1.U(8.W)) // width is set to 8
- * }}}
- *
- * 2. Non-Literal [[Element]] initializer - width will be inferred
- * {{{
- * val x = Wire(UInt())
- * val y = Wire(UInt(8.W))
- * val r1 = RegInit(x) // width will be inferred
- * val r2 = RegInit(y) // width will be inferred
- * }}}
- *
- * 3. [[Aggregate]] initializer - width will be set to match the aggregate
- *
- * {{{
- * class MyBundle {
- * val unknown = UInt()
- * val known = UInt(8.W)
- * }
- * val w1 = Reg(new MyBundle)
- * val w2 = RegInit(w1)
- * // Width of w2.unknown is inferred
- * // Width of w2.known is set to 8
- * }}}
- *
- * ==Double Argument==
- * The double argument form allows the type of the [[Reg]] and the default connection to be
- * specified independently.
- *
- * The width inference semantics for `RegInit` with two arguments match those of [[Reg]]. The
- * first argument to `RegInit` is the type template which defines the width of the `Reg` in
- * exactly the same way as the only argument to [[Wire]].
- *
- * More explicitly, you can reason about `RegInit` with multiple arguments as if it were defined
- * as:
- * {{{
- * def RegInit[T <: Data](t: T, init: T): T = {
- * val x = Reg(t)
- * x := init
- * x
- * }
- * }}}
- */
-object RegInit {
- /** Construct a [[Reg]] from a type template initialized to the specified value on reset
- * @param t The type template used to construct this [[Reg]]
- * @param init The value the [[Reg]] is initialized to on reset
- */
- def apply[T <: Data](t: T, init: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T = {
- if (compileOptions.declaredTypeMustBeUnbound) {
- requireIsChiselType(t, "reg type")
- }
- val reg = t.cloneTypeFull
- val clock = Builder.forcedClock.ref
- val reset = Builder.forcedReset.ref
-
- reg.bind(RegBinding(Builder.forcedUserModule))
- requireIsHardware(init, "reg initializer")
- pushCommand(DefRegInit(sourceInfo, reg, clock, reset, init.ref))
- reg
- }
-
- /** Construct a [[Reg]] initialized on reset to the specified value.
- * @param init Initial value that serves as a type template and reset value
- */
- def apply[T <: Data](init: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T = {
- val model = (init match {
- // If init is a literal without forced width OR any non-literal, let width be inferred
- case init: Bits if !init.litIsForcedWidth.getOrElse(false) => init.cloneTypeWidth(Width())
- case init => init.cloneTypeFull
- }).asInstanceOf[T]
- RegInit(model, init)
- }
-
-}
diff --git a/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala b/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala
deleted file mode 100644
index f15fb178..00000000
--- a/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala
+++ /dev/null
@@ -1,127 +0,0 @@
-// See LICENSE for license details.
-
-package chisel3.core
-
-import chisel3.internal.throwException
-
-import scala.language.experimental.macros
-import chisel3.internal.sourceinfo._
-
-//scalastyle:off method.name
-
-private[chisel3] object SeqUtils {
- /** 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
-
- /** @group SourceInfoTransformMacros */
- def do_asUInt[T <: Bits](in: Seq[T])(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): 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
- }
- }
-
- /** Outputs the number of elements that === true.B.
- */
- def count(in: Seq[Bool]): UInt = macro SourceInfoTransform.inArg
-
- /** @group SourceInfoTransformMacros */
- def do_count(in: Seq[Bool])(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = in.size match {
- case 0 => 0.U
- case 1 => in.head
- case n =>
- val sum = count(in take n/2) +& count(in drop n/2)
- sum(BigInt(n).bitLength - 1, 0)
- }
-
- /** Returns the data value corresponding to the first true predicate.
- */
- def priorityMux[T <: Data](in: Seq[(Bool, T)]): T = macro SourceInfoTransform.inArg
-
- /** @group SourceInfoTransformMacros */
- def do_priorityMux[T <: Data](in: Seq[(Bool, T)])
- (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T = {
- if (in.size == 1) {
- in.head._2
- } else {
- Mux(in.head._1, in.head._2, priorityMux(in.tail))
- }
- }
-
- /** Returns the data value corresponding to the lone true predicate.
- * This is elaborated to firrtl using a structure that should be optimized into and and/or tree.
- *
- * @note assumes exactly one true predicate, results undefined otherwise
- * FixedPoint values or aggregates containing FixedPoint values cause this optimized structure to be lost
- */
- def oneHotMux[T <: Data](in: Iterable[(Bool, T)]): T = macro SourceInfoTransform.inArg
-
- //scalastyle:off method.length cyclomatic.complexity
- /** @group SourceInfoTransformMacros */
- def do_oneHotMux[T <: Data](in: Iterable[(Bool, T)])
- (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T = {
- if (in.tail.isEmpty) {
- in.head._2
- }
- else {
- val output = cloneSupertype(in.toSeq map { _._2}, "oneHotMux")
-
- def buildAndOrMultiplexor[TT <: Data](inputs: Iterable[(Bool, TT)]): T = {
- val masked = for ((s, i) <- inputs) yield Mux(s, i.asUInt(), 0.U)
- masked.reduceLeft(_ | _).asTypeOf(output)
- }
-
- output match {
- case _: SInt =>
- // SInt's have to be managed carefully so sign extension works
-
- val sInts: Iterable[(Bool, SInt)] = in.collect { case (s: Bool, f: SInt) =>
- (s, f.asTypeOf(output).asInstanceOf[SInt])
- }
-
- val masked = for ((s, i) <- sInts) yield Mux(s, i, 0.S)
- masked.reduceLeft(_ | _).asTypeOf(output)
-
- case _: FixedPoint =>
- val (sels, possibleOuts) = in.toSeq.unzip
-
- val (intWidths, binaryPoints) = in.toSeq.map { case (_, o) =>
- val fo = o.asInstanceOf[FixedPoint]
- require(fo.binaryPoint.known, "Mux1H requires width/binary points to be defined")
- (fo.getWidth - fo.binaryPoint.get, fo.binaryPoint.get)
- }.unzip
-
- if (intWidths.distinct.length == 1 && binaryPoints.distinct.length == 1) {
- buildAndOrMultiplexor(in)
- }
- else {
- val maxIntWidth = intWidths.max
- val maxBP = binaryPoints.max
- val inWidthMatched = Seq.fill(intWidths.length)(Wire(FixedPoint((maxIntWidth + maxBP).W, maxBP.BP)))
- inWidthMatched.zipWithIndex foreach { case (e, idx) => e := possibleOuts(idx).asInstanceOf[FixedPoint] }
- buildAndOrMultiplexor(sels.zip(inWidthMatched))
- }
-
- case _: Aggregate =>
- val allDefineWidth = in.forall { case (_, element) => element.widthOption.isDefined }
- if(allDefineWidth) {
- buildAndOrMultiplexor(in)
- }
- else {
- throwException(s"Cannot Mux1H with aggregates with inferred widths")
- }
-
- case _ =>
- buildAndOrMultiplexor(in)
- }
- }
- }
-}
diff --git a/chiselFrontend/src/main/scala/chisel3/core/StrongEnum.scala b/chiselFrontend/src/main/scala/chisel3/core/StrongEnum.scala
deleted file mode 100644
index 63f7a8a0..00000000
--- a/chiselFrontend/src/main/scala/chisel3/core/StrongEnum.scala
+++ /dev/null
@@ -1,344 +0,0 @@
-// See LICENSE for license details.
-
-package chisel3.core
-
-import scala.language.experimental.macros
-import scala.reflect.macros.blackbox.Context
-import scala.collection.mutable
-import chisel3.internal.Builder.pushOp
-import chisel3.internal.firrtl.PrimOp._
-import chisel3.internal.firrtl._
-import chisel3.internal.sourceinfo._
-import chisel3.internal.{Builder, InstanceId, throwException}
-import firrtl.annotations._
-
-
-object EnumAnnotations {
- /** An annotation for strong enum instances that are ''not'' inside of Vecs
- *
- * @param target the enum instance being annotated
- * @param typeName the name of the enum's type (e.g. ''"mypackage.MyEnum"'')
- */
- case class EnumComponentAnnotation(target: Named, enumTypeName: String) extends SingleTargetAnnotation[Named] {
- def duplicate(n: Named): EnumComponentAnnotation = this.copy(target = n)
- }
-
- case class EnumComponentChiselAnnotation(target: InstanceId, enumTypeName: String) extends ChiselAnnotation {
- def toFirrtl: EnumComponentAnnotation = EnumComponentAnnotation(target.toNamed, enumTypeName)
- }
-
- /** An annotation for Vecs of strong enums.
- *
- * The ''fields'' parameter deserves special attention, since it may be difficult to understand. Suppose you create a the following Vec:
-
- * {{{
- * VecInit(new Bundle {
- * val e = MyEnum()
- * val b = new Bundle {
- * val inner_e = MyEnum()
- * }
- * val v = Vec(3, MyEnum())
- * }
- * }}}
- *
- * Then, the ''fields'' parameter will be: ''Seq(Seq("e"), Seq("b", "inner_e"), Seq("v"))''. Note that for any Vec that doesn't contain Bundles, this field will simply be an empty Seq.
- *
- * @param target the Vec being annotated
- * @param typeName the name of the enum's type (e.g. ''"mypackage.MyEnum"'')
- * @param fields a list of all chains of elements leading from the Vec instance to its inner enum fields.
- *
- */
- case class EnumVecAnnotation(target: Named, typeName: String, fields: Seq[Seq[String]]) extends SingleTargetAnnotation[Named] {
- def duplicate(n: Named) = this.copy(target = n)
- }
-
- case class EnumVecChiselAnnotation(target: InstanceId, typeName: String, fields: Seq[Seq[String]]) extends ChiselAnnotation {
- override def toFirrtl = EnumVecAnnotation(target.toNamed, typeName, fields)
- }
-
- /** An annotation for enum types (rather than enum ''instances'').
- *
- * @param typeName the name of the enum's type (e.g. ''"mypackage.MyEnum"'')
- * @param definition a map describing which integer values correspond to which enum names
- */
- case class EnumDefAnnotation(typeName: String, definition: Map[String, BigInt]) extends NoTargetAnnotation
-
- case class EnumDefChiselAnnotation(typeName: String, definition: Map[String, BigInt]) extends ChiselAnnotation {
- override def toFirrtl: Annotation = EnumDefAnnotation(typeName, definition)
- }
-}
-import EnumAnnotations._
-
-
-abstract class EnumType(private val factory: EnumFactory, selfAnnotating: Boolean = true) extends Element {
- override def toString: String = {
- val bindingString = litOption match {
- case Some(value) => factory.nameOfValue(value) match {
- case Some(name) => s"($value=$name)"
- case None => s"($value=(invalid))"
- }
- case _ => bindingToString
- }
- // Use getSimpleName instead of enumTypeName because for debugging purposes the fully qualified name isn't
- // necessary (compared to for the Enum annotation), and it's more consistent with Bundle printing.
- s"${factory.getClass.getSimpleName.init}$bindingString"
- }
-
- override def cloneType: this.type = factory().asInstanceOf[this.type]
-
- private[core] def compop(sourceInfo: SourceInfo, op: PrimOp, other: EnumType): Bool = {
- requireIsHardware(this, "bits operated on")
- requireIsHardware(other, "bits operated on")
-
- if(!this.typeEquivalent(other)) {
- throwException(s"Enum types are not equivalent: ${this.enumTypeName}, ${other.enumTypeName}")
- }
-
- pushOp(DefPrim(sourceInfo, Bool(), op, this.ref, other.ref))
- }
-
- private[core] override def typeEquivalent(that: Data): Boolean = {
- this.getClass == that.getClass &&
- this.factory == that.asInstanceOf[EnumType].factory
- }
-
- private[core] override def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo,
- compileOptions: CompileOptions): Unit = {
- this := factory.apply(that.asUInt)
- }
-
- final def === (that: EnumType): Bool = macro SourceInfoTransform.thatArg
- final def =/= (that: EnumType): Bool = macro SourceInfoTransform.thatArg
- final def < (that: EnumType): Bool = macro SourceInfoTransform.thatArg
- final def <= (that: EnumType): Bool = macro SourceInfoTransform.thatArg
- final def > (that: EnumType): Bool = macro SourceInfoTransform.thatArg
- final def >= (that: EnumType): Bool = macro SourceInfoTransform.thatArg
-
- // scalastyle:off line.size.limit method.name
- def do_=== (that: EnumType)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, EqualOp, that)
- def do_=/= (that: EnumType)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, NotEqualOp, that)
- def do_< (that: EnumType)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, LessOp, that)
- def do_> (that: EnumType)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, GreaterOp, that)
- def do_<= (that: EnumType)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, LessEqOp, that)
- def do_>= (that: EnumType)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, GreaterEqOp, that)
- // scalastyle:on line.size.limit method.name
-
- override def do_asUInt(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt =
- pushOp(DefPrim(sourceInfo, UInt(width), AsUIntOp, ref))
-
- protected[chisel3] override def width: Width = factory.width
-
- def isValid(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = {
- if (litOption.isDefined) {
- true.B
- } else {
- factory.all.map(this === _).reduce(_ || _)
- }
- }
-
- def next(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): this.type = {
- if (litOption.isDefined) {
- val index = factory.all.indexOf(this)
-
- if (index < factory.all.length-1) {
- factory.all(index + 1).asInstanceOf[this.type]
- } else {
- factory.all.head.asInstanceOf[this.type]
- }
- } else {
- val enums_with_nexts = factory.all zip (factory.all.tail :+ factory.all.head)
- val next_enum = SeqUtils.priorityMux(enums_with_nexts.map { case (e,n) => (this === e, n) } )
- next_enum.asInstanceOf[this.type]
- }
- }
-
- private[core] def bindToLiteral(num: BigInt, w: Width): Unit = {
- val lit = ULit(num, w)
- lit.bindLitArg(this)
- }
-
- override private[chisel3] def bind(target: Binding, parentDirection: SpecifiedDirection = SpecifiedDirection.Unspecified): Unit = {
- super.bind(target, parentDirection)
-
- // Make sure we only annotate hardware and not literals
- if (selfAnnotating && isSynthesizable && topBindingOpt.get.isInstanceOf[ConstrainedBinding]) {
- annotateEnum()
- }
- }
-
- // This function conducts a depth-wise search to find all enum-type fields within a vector or bundle (or vector of bundles)
- private def enumFields(d: Aggregate): Seq[Seq[String]] = d match {
- case v: Vec[_] => v.sample_element match {
- case b: Bundle => enumFields (b)
- case _ => Seq ()
- }
- case b: Bundle =>
- b.elements.collect {
- case (name, e: EnumType) if this.typeEquivalent(e) => Seq(Seq(name))
- case (name, v: Vec[_]) if this.typeEquivalent(v.sample_element) => Seq(Seq(name))
- case (name, b2: Bundle) => enumFields(b2).map(name +: _)
- }.flatten.toSeq
- }
-
- private def outerMostVec(d: Data = this): Option[Vec[_]] = {
- val currentVecOpt = d match {
- case v: Vec[_] => Some(v)
- case _ => None
- }
-
- d.binding match {
- case Some(ChildBinding(parent)) => outerMostVec(parent) match {
- case outer @ Some(_) => outer
- case None => currentVecOpt
- }
- case _ => currentVecOpt
- }
- }
-
- private def annotateEnum(): Unit = {
- val anno = outerMostVec() match {
- case Some(v) => EnumVecChiselAnnotation(v, enumTypeName, enumFields(v))
- case None => EnumComponentChiselAnnotation(this, enumTypeName)
- }
-
- if (!Builder.annotations.contains(anno)) {
- annotate(anno)
- }
-
- if (!Builder.annotations.contains(factory.globalAnnotation)) {
- annotate(factory.globalAnnotation)
- }
- }
-
- protected def enumTypeName: String = factory.enumTypeName
-
- def toPrintable: Printable = FullName(this) // TODO: Find a better pretty printer
-}
-
-
-abstract class EnumFactory {
- class Type extends EnumType(this)
- object Type {
- def apply(): Type = EnumFactory.this.apply()
- }
-
- private var id: BigInt = 0
- private[core] var width: Width = 0.W
-
- private case class EnumRecord(inst: Type, name: String)
- private val enum_records = mutable.ArrayBuffer.empty[EnumRecord]
-
- private def enumNames = enum_records.map(_.name).toSeq
- private def enumValues = enum_records.map(_.inst.litValue()).toSeq
- private def enumInstances = enum_records.map(_.inst).toSeq
-
- private[core] val enumTypeName = getClass.getName.init
-
- private[core] def globalAnnotation: EnumDefChiselAnnotation =
- EnumDefChiselAnnotation(enumTypeName, (enumNames, enumValues).zipped.toMap)
-
- def getWidth: Int = width.get
-
- def all: Seq[Type] = enumInstances
-
- private[chisel3] def nameOfValue(id: BigInt): Option[String] = {
- enum_records.find(_.inst.litValue() == id).map(_.name)
- }
-
- protected def Value: Type = macro EnumMacros.ValImpl // scalastyle:off method.name
- protected def Value(id: UInt): Type = macro EnumMacros.ValCustomImpl // scalastyle:off method.name
-
- protected def do_Value(names: Seq[String]): Type = {
- val result = new Type
-
- // We have to use UnknownWidth here, because we don't actually know what the final width will be
- result.bindToLiteral(id, UnknownWidth())
-
- val result_name = names.find(!enumNames.contains(_)).get
- enum_records.append(EnumRecord(result, result_name))
-
- width = (1 max id.bitLength).W
- id += 1
-
- result
- }
-
- protected def do_Value(names: Seq[String], id: UInt): Type = {
- // TODO: These throw ExceptionInInitializerError which can be confusing to the user. Get rid of the error, and just
- // throw an exception
- if (id.litOption.isEmpty) {
- throwException(s"$enumTypeName defined with a non-literal type")
- }
- if (id.litValue() < this.id) {
- throwException(s"Enums must be strictly increasing: $enumTypeName")
- }
-
- this.id = id.litValue()
- do_Value(names)
- }
-
- def apply(): Type = new Type
-
- def apply(n: UInt)(implicit sourceInfo: SourceInfo, connectionCompileOptions: CompileOptions): Type = {
- // scalastyle:off line.size.limit
- if (n.litOption.isDefined) {
- enumInstances.find(_.litValue == n.litValue) match {
- case Some(result) => result
- case None => throwException(s"${n.litValue} is not a valid value for $enumTypeName")
- }
- } else if (!n.isWidthKnown) {
- throwException(s"Non-literal UInts being cast to $enumTypeName must have a defined width")
- } else if (n.getWidth > this.getWidth) {
- throwException(s"The UInt being cast to $enumTypeName is wider than $enumTypeName's width ($getWidth)")
- } else {
- Builder.warning(s"Casting non-literal UInt to $enumTypeName. You can check that its value is legal by calling isValid")
-
- val glue = Wire(new UnsafeEnum(width))
- glue := n
- val result = Wire(new Type)
- result := glue
- result
- }
- }
- // scalastyle:on line.size.limit
-}
-
-
-private[core] object EnumMacros {
- def ValImpl(c: Context) : c.Tree = { // scalastyle:off method.name
- import c.universe._
- val names = getNames(c)
- q"""this.do_Value(Seq(..$names))"""
- }
-
- def ValCustomImpl(c: Context)(id: c.Expr[UInt]): c.universe.Tree = { // scalastyle:off method.name
- import c.universe._
- val names = getNames(c)
- q"""this.do_Value(Seq(..$names), $id)"""
- }
-
- // Much thanks to Travis Brown for this solution:
- // stackoverflow.com/questions/18450203/retrieve-the-name-of-the-value-a-scala-macro-invocation-will-be-assigned-to
- def getNames(c: Context): Seq[String] = {
- import c.universe._
-
- val names = c.enclosingClass.collect {
- case ValDef(_, name, _, rhs)
- if rhs.pos == c.macroApplication.pos => name.decodedName.toString
- }
-
- if (names.isEmpty) {
- c.abort(c.enclosingPosition, "Value cannot be called without assigning to an enum")
- }
-
- names
- }
-}
-
-
-// This is an enum type that can be connected directly to UInts. It is used as a "glue" to cast non-literal UInts
-// to enums.
-private[chisel3] class UnsafeEnum(override val width: Width) extends EnumType(UnsafeEnum, selfAnnotating = false) {
- override def cloneType: this.type = new UnsafeEnum(width).asInstanceOf[this.type]
-}
-private object UnsafeEnum extends EnumFactory
diff --git a/chiselFrontend/src/main/scala/chisel3/core/When.scala b/chiselFrontend/src/main/scala/chisel3/core/When.scala
deleted file mode 100644
index 78fc0fc5..00000000
--- a/chiselFrontend/src/main/scala/chisel3/core/When.scala
+++ /dev/null
@@ -1,85 +0,0 @@
-// See LICENSE for license details.
-
-package chisel3.core
-
-import scala.language.experimental.macros
-
-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
- * 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 === 3.U ) {
- * // Some logic to run when myData equals 3.
- * } .elsewhen ( myData === 1.U ) {
- * // 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, compileOptions: CompileOptions): WhenContext = { // scalastyle:ignore line.size.limit
- new WhenContext(sourceInfo, Some(() => cond), block)
- }
-}
-
-/** A WhenContext may represent a when, and elsewhen, or an
- * otherwise. Since FIRRTL does not have an "elsif" statement,
- * alternatives must be mapped to nested if-else statements inside
- * the alternatives of the preceeding condition. In order to emit
- * proper FIRRTL, it is necessary to keep track of the depth of
- * nesting of the FIRRTL whens. Due to the "thin frontend" nature of
- * Chisel3, it is not possible to know if a when or elsewhen has a
- * succeeding elsewhen or otherwise; therefore, this information is
- * added by preprocessing the command queue.
- */
-final class WhenContext(sourceInfo: SourceInfo, cond: Option[() => Bool], block: => Unit, firrtlDepth: Int = 0) {
-
- /** This block of logic gets executed if above conditions have been
- * false and this condition is true. The lazy argument pattern
- * makes it possible to delay evaluation of cond, emitting the
- * declaration and assignment of the Bool node of the predicate in
- * the correct place.
- */
- def elsewhen (elseCond: => Bool)(block: => Unit)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): WhenContext = { // scalastyle:ignore line.size.limit
- new WhenContext(sourceInfo, Some(() => elseCond), block, firrtlDepth + 1)
- }
-
- /** This block of logic gets executed only if the above conditions
- * were all false. No additional logic blocks may be appended past
- * the `otherwise`. The lazy argument pattern makes it possible to
- * delay evaluation of cond, emitting the declaration and
- * assignment of the Bool node of the predicate in the correct
- * place.
- */
- def otherwise(block: => Unit)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Unit =
- new WhenContext(sourceInfo, None, block, firrtlDepth + 1)
-
- /*
- *
- */
- if (firrtlDepth > 0) { pushCommand(AltBegin(sourceInfo)) }
- cond.foreach( c => pushCommand(WhenBegin(sourceInfo, c().ref)) )
- Builder.whenDepth += 1
- try {
- block
- } catch {
- case ret: scala.runtime.NonLocalReturnControl[_] =>
- throwException("Cannot exit from a when() block with a \"return\"!" +
- " Perhaps you meant to use Mux or a Wire as a return value?"
- )
- }
- Builder.whenDepth -= 1
- cond.foreach( c => pushCommand(WhenEnd(sourceInfo,firrtlDepth)) )
- if (cond.isEmpty) { pushCommand(OtherwiseEnd(sourceInfo,firrtlDepth)) }
-}
diff --git a/chiselFrontend/src/main/scala/chisel3/core/package.scala b/chiselFrontend/src/main/scala/chisel3/core/package.scala
index 46db337b..ac69ca33 100644
--- a/chiselFrontend/src/main/scala/chisel3/core/package.scala
+++ b/chiselFrontend/src/main/scala/chisel3/core/package.scala
@@ -1,133 +1,293 @@
// See LICENSE for license details.
-package chisel3 {
- import internal.Builder
-
- package object core {
- import internal.firrtl.{Width, BinaryPoint}
-
- /**
- * 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.
- *
- * Implementation note: the empty parameter list (like `U()`) is necessary to prevent
- * interpreting calls that have a non-Width parameter as a chained apply, otherwise things like
- * `0.asUInt(16)` (instead of `16.W`) compile without error and produce undesired results.
- */
- implicit class fromBigIntToLiteral(bigint: BigInt) {
- /** Int to Bool conversion, allowing compact syntax like 1.B and 0.B
- */
- def B: Bool = bigint match { // scalastyle:ignore method.name
- case bigint if bigint == 0 => Bool.Lit(false)
- case bigint if bigint == 1 => Bool.Lit(true)
- case bigint => Builder.error(s"Cannot convert $bigint to Bool, must be 0 or 1"); Bool.Lit(false)
- }
- /** Int to UInt conversion, recommended style for constants.
- */
- def U: UInt = UInt.Lit(bigint, Width()) // scalastyle:ignore method.name
- /** Int to SInt conversion, recommended style for constants.
- */
- def S: SInt = SInt.Lit(bigint, Width()) // scalastyle:ignore method.name
- /** Int to UInt conversion with specified width, recommended style for constants.
- */
- def U(width: Width): UInt = UInt.Lit(bigint, width) // scalastyle:ignore method.name
- /** Int to SInt conversion with specified width, recommended style for constants.
- */
- def S(width: Width): SInt = SInt.Lit(bigint, width) // scalastyle:ignore method.name
-
- /** Int to UInt conversion, recommended style for variables.
- */
- def asUInt(): UInt = UInt.Lit(bigint, Width())
- /** Int to SInt conversion, recommended style for variables.
- */
- def asSInt(): SInt = SInt.Lit(bigint, Width())
- /** Int to UInt conversion with specified width, recommended style for variables.
- */
- def asUInt(width: Width): UInt = UInt.Lit(bigint, width)
- /** Int to SInt conversion with specified width, recommended style for variables.
- */
- def asSInt(width: Width): SInt = SInt.Lit(bigint, width)
- }
-
- implicit class fromIntToLiteral(int: Int) extends fromBigIntToLiteral(int)
- implicit class fromLongToLiteral(long: Long) extends fromBigIntToLiteral(long)
-
- implicit class fromStringToLiteral(str: String) {
- /** String to UInt parse, recommended style for constants.
- */
- def U: UInt = str.asUInt() // scalastyle:ignore method.name
- /** String to UInt parse with specified width, recommended style for constants.
- */
- def U(width: Width): UInt = str.asUInt(width) // scalastyle:ignore method.name
-
- /** String to UInt parse, recommended style for variables.
- */
- def asUInt(): UInt = {
- val bigInt = parse(str)
- UInt.Lit(bigInt, Width(bigInt.bitLength max 1))
- }
- /** String to UInt parse with specified width, recommended style for variables.
- */
- def asUInt(width: Width): UInt = UInt.Lit(parse(str), width)
-
- protected 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)
- }
- }
-
- implicit class fromBooleanToLiteral(boolean: Boolean) {
- /** Boolean to Bool conversion, recommended style for constants.
- */
- def B: Bool = Bool.Lit(boolean) // scalastyle:ignore method.name
-
- /** Boolean to Bool conversion, recommended style for variables.
- */
- def asBool(): Bool = Bool.Lit(boolean)
- }
-
- //scalastyle:off method.name
- implicit class fromDoubleToLiteral(double: Double) {
- @deprecated("Use notation <double>.F(<binary_point>.BP) instead", "chisel3")
- def F(binaryPoint: Int): FixedPoint = FixedPoint.fromDouble(double, binaryPoint = binaryPoint)
- def F(binaryPoint: BinaryPoint): FixedPoint = {
- FixedPoint.fromDouble(double, Width(), binaryPoint)
- }
- def F(width: Width, binaryPoint: BinaryPoint): FixedPoint = {
- FixedPoint.fromDouble(double, width, binaryPoint)
- }
- }
-
- implicit class fromIntToWidth(int: Int) {
- def W: Width = Width(int) // scalastyle:ignore method.name
- }
-
- implicit class fromIntToBinaryPoint(int: Int) {
- def BP: BinaryPoint = BinaryPoint(int) // scalastyle:ignore method.name
- }
-
- // These provide temporary compatibility for those who foolishly imported from chisel3.core
- @deprecated("Avoid importing from chisel3.core, these are not public APIs and may change at any time. " +
- " Use chisel3.experimental.RawModule instead.", "since the beginning of time")
- type UserModule = chisel3.core.RawModule
- @deprecated("Avoid importing from chisel3.core, these are not public APIs and may change at any time. " +
- "Use chisel3.experimental.MultiIOModule instead.", "since the beginning of time")
- type ImplicitModule = chisel3.core.MultiIOModule
- }
+package chisel3
+
+package object core {
+
+ /**
+ * These definitions exist to deal with those clients that relied on chisel3.core
+ * They will be deprecated in the future.
+ */
+ @deprecated("Use the version in chisel3._", "3.3")
+ val CompileOptions = chisel3.CompileOptions
+
+ @deprecated("Use the version in chisel3._", "3.3")
+ val Input = chisel3.Input
+ @deprecated("Use the version in chisel3._", "3.3")
+ val Output = chisel3.Output
+ @deprecated("Use the version in chisel3._", "3.3")
+ val Flipped = chisel3.Flipped
+ @deprecated("Use the version in chisel3._", "3.3")
+ val chiselTypeOf = chisel3.chiselTypeOf
+
+ @deprecated("Use the version in chisel3._", "3.3")
+ type Data = chisel3.Data
+
+ @deprecated("Use the version in chisel3._", "3.3")
+ val WireDefault = chisel3.WireDefault
+
+ @deprecated("Use the version in chisel3._", "3.3")
+ val Clock = chisel3.Clock
+ @deprecated("Use the version in chisel3._", "3.3")
+ type Clock = chisel3.Clock
+
+ @deprecated("Use the version in chisel3._", "3.3")
+ type Reset = chisel3.Reset
+
+ @deprecated("Use the version in chisel3._", "3.3")
+ type Aggregate = chisel3.Aggregate
+
+ @deprecated("Use the version in chisel3._", "3.3")
+ val Vec = chisel3.Vec
+ @deprecated("Use the version in chisel3._", "3.3")
+ val VecInit = chisel3.VecInit
+ @deprecated("Use the version in chisel3._", "3.3")
+ type Vec[T <: Data] = chisel3.Vec[T]
+ @deprecated("Use the version in chisel3._", "3.3")
+ type VecLike[T <: Data] = chisel3.VecLike[T]
+ @deprecated("Use the version in chisel3._", "3.3")
+ type Bundle = chisel3.Bundle
+ @deprecated("Use the version in chisel3._", "3.3")
+ type IgnoreSeqInBundle = chisel3.IgnoreSeqInBundle
+ @deprecated("Use the version in chisel3._", "3.3")
+ type Record = chisel3.Record
+
+ @deprecated("Use the version in chisel3._", "3.3")
+ val assert = chisel3.assert
+
+ @deprecated("Use the version in chisel3._", "3.3")
+ type Element = chisel3.Element
+ @deprecated("Use the version in chisel3._", "3.3")
+ type Bits = chisel3.Bits
+
+ // These provide temporary compatibility for those who foolishly imported from chisel3.core
+ @deprecated("Avoid importing from chisel3.core, these are not public APIs and may change at any time. " +
+ " Use chisel3.experimental.RawModule instead.", "since the beginning of time")
+ type RawModule = chisel3.experimental.RawModule
+ @deprecated("Avoid importing from chisel3.core, these are not public APIs and may change at any time. " +
+ "Use chisel3.experimental.MultiIOModule instead.", "since the beginning of time")
+ type MultiIOModule = chisel3.experimental.MultiIOModule
+ @deprecated("Avoid importing from chisel3.core, these are not public APIs and may change at any time. " +
+ " Use chisel3.experimental.RawModule instead.", "since the beginning of time")
+ type UserModule = chisel3.experimental.RawModule
+ @deprecated("Avoid importing from chisel3.core, these are not public APIs and may change at any time. " +
+ "Use chisel3.experimental.MultiIOModule instead.", "since the beginning of time")
+ type ImplicitModule = chisel3.experimental.MultiIOModule
+
+ @deprecated("Use the version in chisel3._", "3.3")
+ val Bits = chisel3.Bits
+ @deprecated("Use the version in chisel3._", "3.3")
+ type Num[T <: chisel3.Data] = chisel3.Num[T]
+ @deprecated("Use the version in chisel3._", "3.3")
+ type UInt = chisel3.UInt
+ @deprecated("Use the version in chisel3._", "3.3")
+ val UInt = chisel3.UInt
+ @deprecated("Use the version in chisel3._", "3.3")
+ type SInt = chisel3.SInt
+ @deprecated("Use the version in chisel3._", "3.3")
+ val SInt = chisel3.SInt
+ @deprecated("Use the version in chisel3._", "3.3")
+ type Bool = chisel3.Bool
+ @deprecated("Use the version in chisel3._", "3.3")
+ val Bool = chisel3.Bool
+ @deprecated("Use the version in chisel3._", "3.3")
+ val Mux = chisel3.Mux
+
+ @deprecated("Use the version in chisel3._", "3.3")
+ type BlackBox = chisel3.BlackBox
+
+ @deprecated("Use the version in chisel3._", "3.3")
+ val Mem = chisel3.Mem
+ @deprecated("Use the version in chisel3._", "3.3")
+ type MemBase[T <: chisel3.Data] = chisel3.MemBase[T]
+ @deprecated("Use the version in chisel3._", "3.3")
+ type Mem[T <: chisel3.Data] = chisel3.Mem[T]
+ @deprecated("Use the version in chisel3._", "3.3")
+ val SyncReadMem = chisel3.SyncReadMem
+ @deprecated("Use the version in chisel3._", "3.3")
+ type SyncReadMem[T <: chisel3.Data] = chisel3.SyncReadMem[T]
+
+ @deprecated("Use the version in chisel3._", "3.3")
+ val Module = chisel3.Module
+ @deprecated("Use the version in chisel3._", "3.3")
+ type Module = chisel3.Module
+
+ @deprecated("Use the version in chisel3._", "3.3")
+ val printf = chisel3.printf
+
+ @deprecated("Use the version in chisel3._", "3.3")
+ val RegNext = chisel3.RegNext
+ @deprecated("Use the version in chisel3._", "3.3")
+ val RegInit = chisel3.RegInit
+ @deprecated("Use the version in chisel3._", "3.3")
+ val Reg = chisel3.Reg
+
+ @deprecated("Use the version in chisel3._", "3.3")
+ val when = chisel3.when
+ @deprecated("Use the version in chisel3._", "3.3")
+ type WhenContext = chisel3.WhenContext
+
+ @deprecated("Use the version in chisel3._", "3.3")
+ type Printable = chisel3.Printable
+ @deprecated("Use the version in chisel3._", "3.3")
+ val Printable = chisel3.Printable
+ @deprecated("Use the version in chisel3._", "3.3")
+ type Printables = chisel3.Printables
+ @deprecated("Use the version in chisel3._", "3.3")
+ val Printables = chisel3.Printables
+ @deprecated("Use the version in chisel3._", "3.3")
+ type PString = chisel3.PString
+ @deprecated("Use the version in chisel3._", "3.3")
+ val PString = chisel3.PString
+ @deprecated("Use the version in chisel3._", "3.3")
+ type FirrtlFormat = chisel3.FirrtlFormat
+ @deprecated("Use the version in chisel3._", "3.3")
+ val FirrtlFormat = chisel3.FirrtlFormat
+ @deprecated("Use the version in chisel3._", "3.3")
+ type Decimal = chisel3.Decimal
+ @deprecated("Use the version in chisel3._", "3.3")
+ val Decimal = chisel3.Decimal
+ @deprecated("Use the version in chisel3._", "3.3")
+ type Hexadecimal = chisel3.Hexadecimal
+ val Hexadecimal = chisel3.Hexadecimal
+ @deprecated("Use the version in chisel3._", "3.3")
+ type Binary = chisel3.Binary
+ @deprecated("Use the version in chisel3._", "3.3")
+ val Binary = chisel3.Binary
+ @deprecated("Use the version in chisel3._", "3.3")
+ type Character = chisel3.Character
+ @deprecated("Use the version in chisel3._", "3.3")
+ val Character = chisel3.Character
+ @deprecated("Use the version in chisel3._", "3.3")
+ type Name = chisel3.Name
+ @deprecated("Use the version in chisel3._", "3.3")
+ val Name = chisel3.Name
+ @deprecated("Use the version in chisel3._", "3.3")
+ type FullName = chisel3.FullName
+ @deprecated("Use the version in chisel3._", "3.3")
+ val FullName = chisel3.FullName
+ @deprecated("Use the version in chisel3._", "3.3")
+ val Percent = chisel3.Percent
+
+ @deprecated("Use the version in chisel3.experimental._", "3.3")
+ type Param = chisel3.experimental.Param
+ @deprecated("Use the version in chisel3.experimental._", "3.3")
+ type IntParam = chisel3.experimental.IntParam
+ @deprecated("Use the version in chisel3.experimental._", "3.3")
+ val IntParam = chisel3.experimental.IntParam
+ @deprecated("Use the version in chisel3.experimental._", "3.3")
+ type DoubleParam = chisel3.experimental.DoubleParam
+ @deprecated("Use the version in chisel3.experimental._", "3.3")
+ val DoubleParam = chisel3.experimental.DoubleParam
+ @deprecated("Use the version in chisel3.experimental._", "3.3")
+ type StringParam = chisel3.experimental.StringParam
+ @deprecated("Use the version in chisel3.experimental._", "3.3")
+ val StringParam = chisel3.experimental.StringParam
+ @deprecated("Use the version in chisel3.experimental._", "3.3")
+ type RawParam = chisel3.experimental.RawParam
+ @deprecated("Use the version in chisel3.experimental._", "3.3")
+ val RawParam = chisel3.experimental.RawParam
+
+ @deprecated("Use the version in chisel3.experimental._", "3.3")
+ type Analog = chisel3.experimental.Analog
+ @deprecated("Use the version in chisel3.experimental._", "3.3")
+ val Analog = chisel3.experimental.Analog
+
+ @deprecated("Use the version in chisel3._", "3.3")
+ implicit class fromIntToWidth(int: Int) extends chisel3.fromIntToWidth(int)
+
+ @deprecated("Use the version in chisel3.experimental._", "3.3")
+ val attach = chisel3.experimental.attach
+
+ @deprecated("Use the version in chisel3.experimental._", "3.3")
+ type EnumType = chisel3.experimental.EnumType
+ @deprecated("Use the version in chisel3.experimental._", "3.3")
+ type EnumFactory = chisel3.experimental.EnumFactory
+ @deprecated("Use the version in chisel3.experimental._", "3.3")
+ val EnumAnnotations = chisel3.experimental.EnumAnnotations
+
+ @deprecated("Use the version in chisel3._", "3.3")
+ val withClockAndReset = chisel3.withClockAndReset
+ @deprecated("Use the version in chisel3._", "3.3")
+ val withClock = chisel3.withClock
+ @deprecated("Use the version in chisel3._", "3.3")
+ val withReset = chisel3.withReset
+
+ @deprecated("Use the version in chisel3.experimental._", "3.3")
+ val dontTouch = chisel3.experimental.dontTouch
+
+ @deprecated("Use the version in chisel3.experimental._", "3.3")
+ type BaseModule = chisel3.experimental.BaseModule
+ @deprecated("Use the version in chisel3.experimental._", "3.3")
+ type ExtModule = chisel3.experimental.ExtModule
+
+ @deprecated("Use the version in chisel3.experimental._", "3.3")
+ val IO = chisel3.experimental.IO
+
+ @deprecated("Use the version in chisel3.experimental._", "3.3")
+ type FixedPoint = chisel3.experimental.FixedPoint
+ @deprecated("Use the version in chisel3.experimental._", "3.3")
+ val FixedPoint = chisel3.experimental.FixedPoint
+ @deprecated("Use the version in chisel3.experimental._", "3.3")
+ implicit class fromDoubleToLiteral(double: Double) extends experimental.FixedPoint.Implicits.fromDoubleToLiteral(double)
+ @deprecated("Use the version in chisel3.experimental._", "3.3")
+ implicit class fromIntToBinaryPoint(int: Int) extends experimental.FixedPoint.Implicits.fromIntToBinaryPoint(int)
+
+ @deprecated("Use the version in chisel3.experimental._", "3.3")
+ type ChiselAnnotation = chisel3.experimental.ChiselAnnotation
+ @deprecated("Use the version in chisel3.experimental._", "3.3")
+ val ChiselAnnotation = chisel3.experimental.ChiselAnnotation
+ @deprecated("Use the version in chisel3.experimental._", "3.3")
+ type RunFirrtlTransform = chisel3.experimental.RunFirrtlTransform
+
+ @deprecated("Use the version in chisel3.experimental._", "3.3")
+ val annotate = chisel3.experimental.annotate
+
+ @deprecated("Use the version in chisel3.experimental._", "3.3")
+ val DataMirror = chisel3.experimental.DataMirror
+ @deprecated("Use the version in chisel3._", "3.3")
+ type ActualDirection = chisel3.ActualDirection
+ @deprecated("Use the version in chisel3._", "3.3")
+ val ActualDirection = chisel3.ActualDirection
+
+ @deprecated("Use the version in chisel3.internal._", "3.3")
+ val requireIsHardware = chisel3.internal.requireIsHardware
+ @deprecated("Use the version in chisel3.internal._", "3.3")
+ val requireIsChiselType = chisel3.internal.requireIsChiselType
+ @deprecated("Use the version in chisel3.internal._", "3.3")
+ val BiConnect = chisel3.internal.BiConnect
+ @deprecated("Use the version in chisel3.internal._", "3.3")
+ val MonoConnect = chisel3.internal.MonoConnect
+ @deprecated("Use the version in chisel3.internal._", "3.3")
+ val BindingDirection = chisel3.internal.BindingDirection
+ @deprecated("Use the version in chisel3.internal._", "3.3")
+ type Binding = chisel3.internal.Binding
+ @deprecated("Use the version in chisel3.internal._", "3.3")
+ type TopBinding = chisel3.internal.TopBinding
+ @deprecated("Use the version in chisel3.internal._", "3.3")
+ type UnconstrainedBinding = chisel3.internal.UnconstrainedBinding
+ @deprecated("Use the version in chisel3.internal._", "3.3")
+ type ConstrainedBinding = chisel3.internal.ConstrainedBinding
+ @deprecated("Use the version in chisel3.internal._", "3.3")
+ type ReadOnlyBinding = chisel3.internal.ReadOnlyBinding
+ @deprecated("Use the version in chisel3.internal._", "3.3")
+ type OpBinding = chisel3.internal.OpBinding
+ @deprecated("Use the version in chisel3.internal._", "3.3")
+ type MemoryPortBinding = chisel3.internal.MemoryPortBinding
+ @deprecated("Use the version in chisel3.internal._", "3.3")
+ type PortBinding = chisel3.internal.PortBinding
+ @deprecated("Use the version in chisel3.internal._", "3.3")
+ type RegBinding = chisel3.internal.RegBinding
+ @deprecated("Use the version in chisel3.internal._", "3.3")
+ type WireBinding = chisel3.internal.WireBinding
+ @deprecated("Use the version in chisel3.internal._", "3.3")
+ type ChildBinding = chisel3.internal.ChildBinding
+ @deprecated("Use the version in chisel3.internal._", "3.3")
+ type DontCareBinding = chisel3.internal.DontCareBinding
+ @deprecated("Use the version in chisel3.internal._", "3.3")
+ type LitBinding = chisel3.internal.LitBinding
+ @deprecated("Use the version in chisel3.internal._", "3.3")
+ type ElementLitBinding = chisel3.internal.ElementLitBinding
+ @deprecated("Use the version in chisel3.internal._", "3.3")
+ type BundleLitBinding = chisel3.internal.BundleLitBinding
}