diff options
282 files changed, 9882 insertions, 6877 deletions
diff --git a/.github/configs/mergify_config.yml b/.github/configs/mergify_config.yml new file mode 100644 index 00000000..dbed4fe8 --- /dev/null +++ b/.github/configs/mergify_config.yml @@ -0,0 +1,7 @@ +# Configuration for generating .mergify.yml +conditions: + - status-success=all tests passed +branches: + - 3.2.x + - 3.3.x + - 3.4.x diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ce18fab0..dc7376a3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -43,9 +43,12 @@ jobs: java-version: ${{ matrix.jvm }} - name: Cache Scala uses: coursier/cache-action@v5 + - name: Check Formatting (Scala 2.12 only) + if: startsWith(matrix.scala, '2.12') + run: sbt ++${{ matrix.scala }} scalafmtCheckAll - name: Documentation (Scala 2.12 only) if: startsWith(matrix.scala, '2.12') - run: sbt ++${{ matrix.scala }} docs/mdoc + run: sbt ++${{ matrix.scala }} docs/mdoc unidoc - name: Test run: sbt ++${{ matrix.scala }} test - name: Binary compatibility diff --git a/.mergify.yml b/.mergify.yml index d3534b36..4ae8b5cd 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -1,3 +1,7 @@ +queue_rules: +- name: default + conditions: + - status-success=all tests passed pull_request_rules: - name: automatic squash-and-merge on CI success and review conditions: @@ -9,10 +13,10 @@ pull_request_rules: - label!="DO NOT MERGE" - label!="bp-conflict" actions: - merge: + queue: + name: default method: squash - strict: smart - strict_method: merge + update_method: merge - name: backport to 3.4.x conditions: - merged @@ -73,10 +77,10 @@ pull_request_rules: - label!="DO NOT MERGE" - label!="bp-conflict" actions: - merge: + queue: + name: default method: squash - strict: smart - strict_method: merge + update_method: merge - name: automatic squash-and-mege of 3.3.x backport PRs conditions: - status-success=all tests passed @@ -86,10 +90,10 @@ pull_request_rules: - label!="DO NOT MERGE" - label!="bp-conflict" actions: - merge: + queue: + name: default method: squash - strict: smart - strict_method: merge + update_method: merge - name: automatic squash-and-mege of 3.4.x backport PRs conditions: - status-success=all tests passed @@ -99,8 +103,8 @@ pull_request_rules: - label!="DO NOT MERGE" - label!="bp-conflict" actions: - merge: + queue: + name: default method: squash - strict: smart - strict_method: merge + update_method: merge diff --git a/.scalafmt.conf b/.scalafmt.conf new file mode 100644 index 00000000..f74e5504 --- /dev/null +++ b/.scalafmt.conf @@ -0,0 +1,26 @@ +version = 2.6.4 + +maxColumn = 120 +align = most +continuationIndent.defnSite = 2 +assumeStandardLibraryStripMargin = true +docstrings = ScalaDoc +lineEndings = preserve +includeCurlyBraceInSelectChains = false +danglingParentheses = true + +align.tokens.add = [ + { + code = ":" + } +] + +newlines.alwaysBeforeCurlyBraceLambdaParams = false +newlines.alwaysBeforeMultilineDef = false +newlines.implicitParamListModifierForce = [before] + +verticalMultiline.atDefnSite = true + +optIn.annotationNewlines = true + +rewrite.rules = [SortImports, PreferCurlyFors, AvoidInfix] @@ -19,7 +19,7 @@ Looking forward to CCC 2022! See you then! [](https://gitter.im/freechipsproject/chisel3?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)  -[](https://github.com/chipsalliance/chisel3/releases/latest) +[](https://github.com/chipsalliance/chisel3/releases/latest) [**Chisel**](https://www.chisel-lang.org) is a hardware design language that facilitates **advanced circuit generation and design reuse for both ASIC and FPGA digital logic designs**. Chisel adds hardware construction primitives to the [Scala](https://www.scala-lang.org) programming language, providing designers with the power of a modern programming language to write complex, parameterizable circuit generators that produce synthesizable Verilog. @@ -93,7 +93,7 @@ import chisel3.stage.{ChiselStage, ChiselGeneratorAnnotation} Alternatively, you may generate some Verilog directly for inspection: ```scala -val verilogString = (new chisel3.stage.ChiselStage).emitVerilog(new FirFilter(8, Seq(0.U, 1.U))) +val verilogString = chisel3.emitVerilog(new FirFilter(8, Seq(0.U, 1.U))) println(verilogString) ``` @@ -120,12 +120,11 @@ If you insist on setting up your own project from scratch, your project needs to For example, in SBT this could be expressed as: ```scala // build.sbt -scalaVersion := "2.12.13" -addCompilerPlugin("edu.berkeley.cs" % "chisel3-plugin" % "3.4.4" cross CrossVersion.full) -libraryDependencies += "edu.berkeley.cs" %% "chisel3" % "3.4.4" -scalacOptions += "-Xsource:2.11" +scalaVersion := "2.13.7" +addCompilerPlugin("edu.berkeley.cs" % "chisel3-plugin" % "3.5.0-RC2" cross CrossVersion.full) +libraryDependencies += "edu.berkeley.cs" %% "chisel3" % "3.5.0-RC2" // We also recommend using chiseltest for writing unit tests -libraryDependencies += "edu.berkeley.cs" %% "chiseltest" % "0.3.4" % "test" +libraryDependencies += "edu.berkeley.cs" %% "chiseltest" % "0.5.0-RC2" % "test" ``` ### Guide For New Contributors If you are trying to make a contribution to this project, please read [CONTRIBUTING.md](https://github.com/Burnleydev1/chisel3/blob/recent_PR/CONTRIBUTING.md) @@ -145,7 +144,7 @@ These simulation-based verification tools are available for Chisel: - [**ScalaDoc**](https://www.chisel-lang.org/api/latest/chisel3/index.html), a listing, description, and examples of the functionality exposed by Chisel - [**Gitter**](https://gitter.im/freechipsproject/chisel3), where you can ask questions or discuss anything Chisel - [**Website**](https://www.chisel-lang.org) ([source](https://github.com/freechipsproject/www.chisel-lang.org/)) -- [**Scastie (3.5.0-RC1)**](https://scastie.scala-lang.org/KtzZQ3nFTea9KoNh0tRqtg) +- [**Scastie (3.5.0-RC2)**](https://scastie.scala-lang.org/R6wV80vUTr2CwhvouEdidg) - [**asic-world**](http://www.asic-world.com/verilog/veritut.html) If you aren't familiar with verilog, this is a good tutorial. If you are migrating from Chisel2, see [the migration guide](https://www.chisel-lang.org/chisel3/chisel3-vs-chisel2.html). @@ -196,7 +195,7 @@ The repository version can be found in the [build.sbt](build.sbt) file. As of the time of writing it was: ``` -version := "3.4-SNAPSHOT" +version := "3.5-SNAPSHOT" ``` To publish your version of Chisel to the local Ivy (sbt's dependency manager) repository, run: @@ -211,7 +210,7 @@ If you need to un-publish your local copy of Chisel, remove the directory genera In order to have your projects use this version of Chisel, you should update the `libraryDependencies` setting in your project's build.sbt file to: ``` -libraryDependencies += "edu.berkeley.cs" %% "chisel3" % "3.4-SNAPSHOT" +libraryDependencies += "edu.berkeley.cs" %% "chisel3" % "3.5-SNAPSHOT" ``` ### Building Chisel with FIRRTL in the same SBT Project @@ -274,24 +273,15 @@ Code that touches lots of APIs that are private to the `chisel3` package should ### Which version should I use? -The chisel eco-system (`chisel3`, `firrtl`, `dsptools`, `firrtl-interpreter`, `treadle`, `diagrammer`) use a form of semantic versioning: - major versions are identified by two leading numbers, separated by a dot (i.e., `3.2`), minor versions by a single number following the major version, separated by a dot. - We maintain API compatibility within a major version (i.e., `3.2.12` should be API-compatible with `3.2.0`), but do not guarantee API compatibility between major versions - (i.e., APIs may change between `3.1.8` and `3.2.0`). - We may introduce new definitions or add additional parameters to existing definitions in a minor release, but we do our best to maintain compatibility with previous minor releases of a major release - code that worked in `3.2.0` should continue to work un-modified in `3.2.10`. - -We encourage chisel users (rather than chisel developers), to use release versions of chisel. - The chisel web site (and GitHub repository) should indicate the current release version. - If you encounter an issue with a released version of chisel, please file an issue on GitHub mentioning the chisel version and provide a simple test case (if possible). - Try to reproduce the issue with the associated latest minor release (to verify that the issue hasn't been addressed). - -If you're developing a chisel library (or `chisel` itself), you'll probably want to work closer to the tip of the development trunk. - By default, the master branches of the chisel repositories are configured to build and publish their version of the code as `Z.Y-SNAPSHOT`. - We try to publish an updated SNAPSHOT every two weeks. - There is no guarantee of API compatibility between SNAPSHOT versions, but we publish date-stamped `Z.Y-yyyymmdd-SNAPSHOT` versions which will not change. - The code in `Z.Y-SNAPSHOT` should match the code in the most recent `Z.Y-yyyymmdd-SNAPSHOT` version, the differences being the chisel library dependencies: - `Z.Y-SNAPSHOT`s depend on `V.U-SNAPSHOT`s and `Z.Y-yyyymmdd-SNAPSHOT`s will depend on `V.U-yyyymmdd-SNAPSHOT`s. - **NOTE**: Prior to the `v3.2-20191030-SNAPSHOT` version, we used `Z.Y-mmddyy-SNAPSHOT` to tag and name published SNAPSHOTs. - -If you're developing a library (or another chisel tool), you should probably work with date-stamped SNAPSHOTs until your library or tool is ready to be published (to ensure a consistent API). - Prior to publishing, you should verify your code against generic (no date-stamp) SNAPSHOTs, or locally published clones of the current master branches of chisel dependencies. +We encourage Chisel users (as opposed to Chisel developers), to use the latest release version of Chisel. +This [chisel-template](https://github.com/freechipsproject/chisel-template) repository is kept up-to-date, depending on the most recent version of Chisel. +The recommended version is also captured near the top of this README, and in the [Github releases](https://github.com/chipsalliance/chisel3/releases) section of this repo. +If you encounter an issue with a released version of Chisel, please file an issue on GitHub mentioning the Chisel version and provide a simple test case (if possible). +Try to reproduce the issue with the associated latest minor release (to verify that the issue hasn't been addressed). + +For more information on our versioning policy and what versions of the various Chisel ecosystem projects work together, see [Chisel Project Versioning](https://www.chisel-lang.org/chisel3/docs/appendix/versioning.html). + +If you're developing a Chisel library (or `chisel3` itself), you'll probably want to work closer to the tip of the development trunk. +By default, the master branches of the chisel repositories are configured to build and publish their version of the code as `Z.Y-SNAPSHOT`. +Updated SNAPSHOTs are publised on every push to master. +You are encouraged to do your development against the latest SNAPSHOT, but note that neither API nor ABI compatibility is guaranteed so your code may break at any time. @@ -218,7 +218,13 @@ lazy val chisel = (project in file(".")). } s"https://github.com/chipsalliance/chisel3/tree/$branch€{FILE_PATH_EXT}#L€{FILE_LINE}" } - ) + ) ++ + // Suppress compiler plugin for source files in core + // We don't need this in regular compile because we just don't add the chisel3-plugin to core's scalacOptions + // This works around an issue where unidoc uses the exact same arguments for all source files. + // This is probably fundamental to how ScalaDoc works so there may be no solution other than this workaround. + // See https://github.com/sbt/sbt-unidoc/issues/107 + (core / Compile / sources).value.map("-P:chiselplugin:INTERNALskipFile:" + _) ) // tests elaborating and executing/formally verifying a Chisel circuit with chiseltest @@ -1,6 +1,7 @@ import mill._ import mill.scalalib._ import mill.scalalib.publish._ +import mill.scalalib.scalafmt._ import coursier.maven.MavenRepository import $ivy.`com.lihaoyi::mill-contrib-buildinfo:$MILL_VERSION` import mill.contrib.buildinfo.BuildInfo @@ -29,7 +30,7 @@ def getTestVersion(dep: String, org: String = "edu.berkeley.cs") = { } // Since chisel contains submodule core and macros, a CommonModule is needed -trait CommonModule extends CrossSbtModule with PublishModule { +trait CommonModule extends CrossSbtModule with PublishModule with ScalafmtModule { def firrtlModule: Option[PublishModule] = None def firrtlIvyDeps = if (firrtlModule.isEmpty) Agg( diff --git a/core/src/main/scala/chisel3/Aggregate.scala b/core/src/main/scala/chisel3/Aggregate.scala index db354e1f..15cdf428 100644 --- a/core/src/main/scala/chisel3/Aggregate.scala +++ b/core/src/main/scala/chisel3/Aggregate.scala @@ -3,7 +3,7 @@ package chisel3 import chisel3.experimental.VecLiterals.AddVecLiteralConstructor -import chisel3.experimental.dataview.{InvalidViewException, isView, reifySingleData} +import chisel3.experimental.dataview.{isView, reifySingleData, InvalidViewException} import scala.collection.immutable.{SeqMap, VectorMap} import scala.collection.mutable.{HashSet, LinkedHashMap} @@ -34,13 +34,16 @@ sealed abstract class Aggregate extends Data { // show groups of names of fields with duplicate id's // The sorts make the displayed order of fields deterministic and matching the order of occurrence in the Bundle. // It's a bit convoluted but happens rarely and makes the error message easier to understand - val dupNames = duplicates.toSeq.sortBy(_._id).map { duplicate => - b.elements - .collect { case x if x._2._id == duplicate._id => x } - .toSeq.sortBy(_._2._id) - .map(_._1).reverse - .mkString("(", ",", ")") - }.mkString(",") + val dupNames = duplicates.toSeq + .sortBy(_._id) + .map { duplicate => + b.elements.collect { case x if x._2._id == duplicate._id => x }.toSeq + .sortBy(_._2._id) + .map(_._1) + .reverse + .mkString("(", ",", ")") + } + .mkString(",") throw new AliasedAggregateFieldException( s"${b.className} contains aliased fields named ${dupNames}" ) @@ -59,9 +62,10 @@ sealed abstract class Aggregate extends Data { direction = ActualDirection.fromChildren(childDirections, resolvedDirection) match { case Some(dir) => dir case None => - val childWithDirections = getElements zip getElements.map(_.direction) + val childWithDirections = getElements.zip(getElements.map(_.direction)) throw MixedDirectionAggregateException( - s"Aggregate '$this' can't have elements that are both directioned and undirectioned: $childWithDirections") + s"Aggregate '$this' can't have elements that are both directioned and undirectioned: $childWithDirections" + ) } } @@ -76,7 +80,7 @@ sealed abstract class Aggregate extends Data { (accumulator, elt.litOption) match { case (Some(accumulator), Some(eltLit)) => val width = elt.width.get - val masked = ((BigInt(1) << width) - 1) & eltLit // also handles the negative case with two's complement + val masked = ((BigInt(1) << width) - 1) & eltLit // also handles the negative case with two's complement Some((accumulator << width) + masked) case (None, _) => None case (_, None) => None @@ -85,8 +89,7 @@ sealed abstract class Aggregate extends Data { topBindingOpt match { case Some(BundleLitBinding(_)) | Some(VecLitBinding(_)) => - getElements - .reverse + getElements.reverse .foldLeft[Option[BigInt]](Some(BigInt(0)))(shiftAdd) case _ => None } @@ -112,8 +115,12 @@ sealed abstract class Aggregate extends Data { SeqUtils.do_asUInt(flatten.map(_.asUInt())) } - private[chisel3] override def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo, - compileOptions: CompileOptions): Unit = { + private[chisel3] override def connectFromBits( + that: Bits + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Unit = { var i = 0 val bits = if (that.isLit) that else WireDefault(UInt(this.width), that) // handles width padding for (x <- flatten) { @@ -132,6 +139,7 @@ sealed abstract class Aggregate extends Data { } 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 @@ -144,12 +152,18 @@ trait VecFactory extends SourceInfoDoc { } /** Truncate an index to implement modulo-power-of-2 addressing. */ - private[chisel3] def truncateIndex(idx: UInt, n: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = { - val w = (n-1).bitLength + private[chisel3] def truncateIndex( + idx: UInt, + n: BigInt + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): UInt = { + 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) + else if (idx.width.known) idx(w - 1, 0) + else (idx | 0.U(w.W))(w - 1, 0) } } @@ -179,14 +193,14 @@ trait VecFactory extends SourceInfoDoc { * - 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 */ -sealed class Vec[T <: Data] private[chisel3] (gen: => T, val length: Int) - extends Aggregate with VecLike[T] { +sealed class Vec[T <: Data] private[chisel3] (gen: => T, val length: Int) extends Aggregate with VecLike[T] { override def toString: String = { topBindingOpt match { case Some(VecLitBinding(vecLitBinding)) => - val contents = vecLitBinding.zipWithIndex.map { case ((data, lit), index) => - s"$index=$lit" + val contents = vecLitBinding.zipWithIndex.map { + case ((data, lit), index) => + s"$index=$lit" }.mkString(", ") s"${sample_element.cloneType}[$length]($contents)" case _ => stringAccessor(s"${sample_element.cloneType}[$length]") @@ -196,7 +210,7 @@ sealed class Vec[T <: Data] private[chisel3] (gen: => T, val length: Int) private[chisel3] override def typeEquivalent(that: Data): Boolean = that match { case that: Vec[T] => this.length == that.length && - (this.sample_element typeEquivalent that.sample_element) + (this.sample_element.typeEquivalent(that.sample_element)) case _ => false } @@ -206,7 +220,7 @@ sealed class Vec[T <: Data] private[chisel3] (gen: => T, val length: Int) val resolvedDirection = SpecifiedDirection.fromParent(parentDirection, specifiedDirection) sample_element.bind(SampleElementBinding(this), resolvedDirection) - for (child <- getElements) { // assume that all children are the same + for (child <- getElements) { // assume that all children are the same child.bind(ChildBinding(this), resolvedDirection) } @@ -226,12 +240,12 @@ sealed class Vec[T <: Data] private[chisel3] (gen: => T, val length: Int) } /** - * 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. - */ + * 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 @@ -245,29 +259,33 @@ sealed class Vec[T <: Data] private[chisel3] (gen: => T, val length: Int) * * @note the length of this Vec must match the length of the input Seq */ - def <> (that: Seq[T])(implicit sourceInfo: SourceInfo, moduleCompileOptions: CompileOptions): Unit = { + 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) + 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] + def <>(that: Vec[T])(implicit sourceInfo: SourceInfo, moduleCompileOptions: CompileOptions): Unit = + this.bulkConnect(that.asInstanceOf[Data]) /** Strong bulk connect, assigning elements in this Vec from elements in a Seq. * * @note the length of this Vec must match the length of the input Seq */ - def := (that: Seq[T])(implicit sourceInfo: SourceInfo, moduleCompileOptions: CompileOptions): Unit = { - require(this.length == that.length, s"Cannot assign to a Vec of length ${this.length} from a Seq of different length ${that.length}") - for ((a, b) <- this zip that) + def :=(that: Seq[T])(implicit sourceInfo: SourceInfo, moduleCompileOptions: CompileOptions): Unit = { + require( + this.length == that.length, + s"Cannot assign to a Vec of length ${this.length} from a Seq of different 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 + def :=(that: Vec[T])(implicit sourceInfo: SourceInfo, moduleCompileOptions: CompileOptions): Unit = this.connect(that) /** Creates a dynamically indexed read or write accessor into the array. */ @@ -284,8 +302,9 @@ sealed class Vec[T <: Data] private[chisel3] (gen: => T, val length: Int) // Views complicate things a bit, but views that correspond exactly to an identical Vec can just forward the // dynamic indexing to the target Vec // In theory, we could still do this forwarding if the sample element were different by deriving a DataView - case Some(target: Vec[T @unchecked]) if this.length == target.length && - this.sample_element.typeEquivalent(target.sample_element) => + case Some(target: Vec[T @unchecked]) + if this.length == target.length && + this.sample_element.typeEquivalent(target.sample_element) => return target.do_apply(p) case _ => throw InvalidViewException("Dynamic indexing of Views is not yet supported") } @@ -296,7 +315,7 @@ sealed class Vec[T <: Data] private[chisel3] (gen: => T, val length: Int) // 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.Input => SpecifiedDirection.Input case ActualDirection.Output => SpecifiedDirection.Output case ActualDirection.Bidirectional(ActualDirection.Default) | ActualDirection.Unspecified => SpecifiedDirection.Unspecified @@ -331,7 +350,7 @@ sealed class Vec[T <: Data] private[chisel3] (gen: => T, val length: Int) def toPrintable: Printable = { val elts = if (length == 0) List.empty[Printable] - else self flatMap (e => List(e.toPrintable, PString(", "))) dropRight 1 + else self.flatMap(e => List(e.toPrintable, PString(", "))).dropRight(1) PString("Vec(") + Printables(elts) + PString(")") } @@ -354,14 +373,17 @@ sealed class Vec[T <: Data] private[chisel3] (gen: => T, val length: Int) */ def reduceTree(redOp: (T, T) => T, layerOp: (T) => T): T = macro VecTransform.reduceTree - def do_reduceTree(redOp: (T, T) => T, layerOp: (T) => T = (x: T) => x) - (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) : T = { + def do_reduceTree( + redOp: (T, T) => T, + layerOp: (T) => T = (x: T) => x + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): T = { require(!isEmpty, "Cannot apply reduction on a vec of size 0") - var curLayer : Seq[T] = this + var curLayer: Seq[T] = this while (curLayer.length > 1) { - curLayer = curLayer.grouped(2).map( x => - if (x.length == 1) layerOp(x(0)) else redOp(x(0), x(1)) - ).toSeq + curLayer = curLayer.grouped(2).map(x => if (x.length == 1) layerOp(x(0)) else redOp(x(0), x(1))).toSeq } curLayer(0) } @@ -380,16 +402,21 @@ sealed class Vec[T <: Data] private[chisel3] (gen: => T, val length: Int) * ) * }}} */ - private[chisel3] def _makeLit(elementInitializers: (Int, T)*)(implicit sourceInfo: SourceInfo, - compileOptions: CompileOptions): this.type = { + private[chisel3] def _makeLit( + elementInitializers: (Int, T)* + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): this.type = { def checkLiteralConstruction(): Unit = { - val dupKeys = elementInitializers.map { x => x._1 }.groupBy(x => x).flatMap { case (k, v) => - if (v.length > 1) { - Some(k, v.length) - } else { - None - } + val dupKeys = elementInitializers.map { x => x._1 }.groupBy(x => x).flatMap { + case (k, v) => + if (v.length > 1) { + Some(k, v.length) + } else { + None + } } if (dupKeys.nonEmpty) { throw new VecLiteralException( @@ -438,79 +465,96 @@ sealed class Vec[T <: Data] private[chisel3] (gen: => T, val length: Int) // Create the Vec literal binding from litArgs of arguments val vecLitLinkedMap = new mutable.LinkedHashMap[Data, LitArg]() - elementInitializers.sortBy { case (a, _) => a }.foreach { case (fieldIndex, value) => - val field = clone.apply(fieldIndex) - val fieldName = cloneFields.getOrElse(field, - throw new VecLiteralException(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 VecLiteralException(s"field $fieldIndex specified with non-literal value $value") - } + elementInitializers.sortBy { case (a, _) => a }.foreach { + case (fieldIndex, value) => + val field = clone.apply(fieldIndex) + val fieldName = cloneFields.getOrElse( + field, + throw new VecLiteralException( + 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'" + ) + ) - field match { // Get the litArg(s) for this field - case bitField: Bits => - if (!field.typeEquivalent(bitField)) { - throw new VecLiteralException( - s"VecLit: Literal specified at index $fieldIndex ($value) does not match Vec type $sample_element" - ) - } - if (bitField.getWidth > field.getWidth) { - throw new VecLiteralException( - s"VecLit: Literal specified at index $fieldIndex ($value) is too wide for Vec type $sample_element" - ) - } - val litArg = valueBinding match { - case ElementLitBinding(litArg) => litArg - case BundleLitBinding(litMap) => litMap.getOrElse(value, - throw new BundleLiteralException(s"Field $fieldName specified with unspecified value") - ) - case VecLitBinding(litMap) => litMap.getOrElse(value, - throw new VecLiteralException(s"Field $fieldIndex specified with unspecified value")) - } - val adjustedLitArg = litArg.cloneWithWidth(sample_element.width) - vecLitLinkedMap(bitField) = adjustedLitArg + val valueBinding = value.topBindingOpt match { + case Some(litBinding: LitBinding) => litBinding + case _ => throw new VecLiteralException(s"field $fieldIndex specified with non-literal value $value") + } - case recordField: Record => - if (!(recordField.typeEquivalent(value))) { - throw new VecLiteralException(s"field $fieldIndex $recordField specified with non-type-equivalent value $value") - } - // Copy the source BundleLitBinding with fields (keys) remapped to the clone - val remap = getMatchedFields(value, recordField).toMap - valueBinding.asInstanceOf[BundleLitBinding].litMap.map { case (valueField, valueValue) => - vecLitLinkedMap(remap(valueField)) = valueValue - } + field match { // Get the litArg(s) for this field + case bitField: Bits => + if (!field.typeEquivalent(bitField)) { + throw new VecLiteralException( + s"VecLit: Literal specified at index $fieldIndex ($value) does not match Vec type $sample_element" + ) + } + if (bitField.getWidth > field.getWidth) { + throw new VecLiteralException( + s"VecLit: Literal specified at index $fieldIndex ($value) is too wide for Vec type $sample_element" + ) + } + val litArg = valueBinding match { + case ElementLitBinding(litArg) => litArg + case BundleLitBinding(litMap) => + litMap.getOrElse( + value, + throw new BundleLiteralException(s"Field $fieldName specified with unspecified value") + ) + case VecLitBinding(litMap) => + litMap.getOrElse( + value, + throw new VecLiteralException(s"Field $fieldIndex specified with unspecified value") + ) + } + val adjustedLitArg = litArg.cloneWithWidth(sample_element.width) + vecLitLinkedMap(bitField) = adjustedLitArg + + case recordField: Record => + if (!(recordField.typeEquivalent(value))) { + throw new VecLiteralException( + s"field $fieldIndex $recordField specified with non-type-equivalent value $value" + ) + } + // Copy the source BundleLitBinding with fields (keys) remapped to the clone + val remap = getMatchedFields(value, recordField).toMap + valueBinding.asInstanceOf[BundleLitBinding].litMap.map { + case (valueField, valueValue) => + vecLitLinkedMap(remap(valueField)) = valueValue + } - case vecField: Vec[_] => - if (!(vecField typeEquivalent value)) { - throw new VecLiteralException(s"field $fieldIndex $vecField specified with non-type-equivalent value $value") - } - // Copy the source VecLitBinding with vecFields (keys) remapped to the clone - val remap = getMatchedFields(value, vecField).toMap - value.topBinding.asInstanceOf[VecLitBinding].litMap.map { case (valueField, valueValue) => - vecLitLinkedMap(remap(valueField)) = valueValue - } + case vecField: Vec[_] => + if (!(vecField.typeEquivalent(value))) { + throw new VecLiteralException( + s"field $fieldIndex $vecField specified with non-type-equivalent value $value" + ) + } + // Copy the source VecLitBinding with vecFields (keys) remapped to the clone + val remap = getMatchedFields(value, vecField).toMap + value.topBinding.asInstanceOf[VecLitBinding].litMap.map { + case (valueField, valueValue) => + vecLitLinkedMap(remap(valueField)) = valueValue + } - case enumField: EnumType => { - if (!(enumField typeEquivalent value)) { - throw new VecLiteralException(s"field $fieldIndex $enumField specified with non-type-equivalent enum value $value") - } - val litArg = valueBinding match { - case ElementLitBinding(litArg) => litArg - case _ => - throw new VecLiteralException(s"field $fieldIndex $enumField could not bematched with $valueBinding") + case enumField: EnumType => { + if (!(enumField.typeEquivalent(value))) { + throw new VecLiteralException( + s"field $fieldIndex $enumField specified with non-type-equivalent enum value $value" + ) + } + val litArg = valueBinding match { + case ElementLitBinding(litArg) => litArg + case _ => + throw new VecLiteralException(s"field $fieldIndex $enumField could not bematched with $valueBinding") + } + vecLitLinkedMap(field) = litArg } - vecLitLinkedMap(field) = litArg - } - case _ => throw new VecLiteralException(s"unsupported field $fieldIndex of type $field") - } + case _ => throw new VecLiteralException(s"unsupported field $fieldIndex of type $field") + } } - clone.bind(VecLitBinding(VectorMap(vecLitLinkedMap.toSeq:_*))) + clone.bind(VecLitBinding(VectorMap(vecLitLinkedMap.toSeq: _*))) clone } } @@ -519,7 +563,12 @@ object VecInit extends SourceInfoDoc { /** Gets the correct connect operation (directed hardware assign or bulk connect) for element in Vec. */ - private def getConnectOpFromDirectionality[T <: Data](proto: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): (T, T) => Unit = proto.direction match { + private def getConnectOpFromDirectionality[T <: Data]( + proto: T + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): (T, T) => Unit = proto.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 @@ -557,8 +606,8 @@ object VecInit extends SourceInfoDoc { val vec = Wire(Vec(elts.length, cloneSupertype(elts, "Vec"))) val op = getConnectOpFromDirectionality(vec.head) - - (vec zip elts).foreach{ x => + + (vec.zip(elts)).foreach { x => op(x._1, x._2) } vec @@ -589,7 +638,13 @@ object VecInit extends SourceInfoDoc { 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] = + def do_tabulate[T <: Data]( + n: Int + )(gen: (Int) => T + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Vec[T] = apply((0 until n).map(i => gen(i))) /** Creates a new 2D [[Vec]] of length `n by m` composed of the results of the given @@ -604,24 +659,31 @@ object VecInit extends SourceInfoDoc { def tabulate[T <: Data](n: Int, m: Int)(gen: (Int, Int) => T): Vec[Vec[T]] = macro VecTransform.tabulate2D /** @group SourceInfoTransformMacro */ - def do_tabulate[T <: Data](n: Int, m: Int)(gen: (Int, Int) => T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Vec[Vec[T]] = { + def do_tabulate[T <: Data]( + n: Int, + m: Int + )(gen: (Int, Int) => T + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Vec[Vec[T]] = { // TODO make this lazy (requires LazyList and cross compilation, beyond the scope of this PR) val elts = Seq.tabulate(n, m)(gen) val flatElts = elts.flatten require(flatElts.nonEmpty, "Vec hardware values are not allowed to be empty") flatElts.foreach(requireIsHardware(_, "vec element")) - + val tpe = cloneSupertype(flatElts, "Vec.tabulate") val myVec = Wire(Vec(n, Vec(m, tpe))) val op = getConnectOpFromDirectionality(myVec.head.head) - for ( - (xs1D, ys1D) <- myVec zip elts; - (x, y) <- xs1D zip ys1D - ) { - op(x, y) + for { + (xs1D, ys1D) <- myVec.zip(elts) + (x, y) <- xs1D.zip(ys1D) + } { + op(x, y) } - myVec + myVec } /** Creates a new 3D [[Vec]] of length `n by m by p` composed of the results of the given @@ -633,39 +695,48 @@ object VecInit extends SourceInfoDoc { * @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, m: Int, p: Int)(gen: (Int, Int, Int) => T): Vec[Vec[Vec[T]]] = macro VecTransform.tabulate3D + def tabulate[T <: Data](n: Int, m: Int, p: Int)(gen: (Int, Int, Int) => T): Vec[Vec[Vec[T]]] = + macro VecTransform.tabulate3D /** @group SourceInfoTransformMacro */ - def do_tabulate[T <: Data](n: Int, m: Int, p: Int)(gen: (Int, Int, Int) => T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Vec[Vec[Vec[T]]] = { - // TODO make this lazy (requires LazyList and cross compilation, beyond the scope of this PR) + def do_tabulate[T <: Data]( + n: Int, + m: Int, + p: Int + )(gen: (Int, Int, Int) => T + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Vec[Vec[Vec[T]]] = { + // TODO make this lazy (requires LazyList and cross compilation, beyond the scope of this PR) val elts = Seq.tabulate(n, m, p)(gen) val flatElts = elts.flatten.flatten require(flatElts.nonEmpty, "Vec hardware values are not allowed to be empty") flatElts.foreach(requireIsHardware(_, "vec element")) - + val tpe = cloneSupertype(flatElts, "Vec.tabulate") val myVec = Wire(Vec(n, Vec(m, Vec(p, tpe)))) val op = getConnectOpFromDirectionality(myVec.head.head.head) - - for ( - (xs2D, ys2D) <- myVec zip elts; - (xs1D, ys1D) <- xs2D zip ys2D; - (x, y) <- xs1D zip ys1D - ) { - op(x, y) + + for { + (xs2D, ys2D) <- myVec.zip(elts) + (xs1D, ys1D) <- xs2D.zip(ys2D) + (x, y) <- xs1D.zip(ys1D) + } { + op(x, y) } myVec } /** Creates a new [[Vec]] of length `n` composed of the result of the given - * function applied to an element of data type T. - * - * @param n number of elements in the vector - * @param gen function that takes in an element T and returns an output - * element of the same type - */ + * function applied to an element of data type T. + * + * @param n number of elements in the vector + * @param gen function that takes in an element T and returns an output + * element of the same type + */ def fill[T <: Data](n: Int)(gen: => T): Vec[T] = macro VecTransform.fill /** @group SourceInfoTransformMacro */ @@ -673,49 +744,71 @@ object VecInit extends SourceInfoDoc { apply(Seq.fill(n)(gen)) /** Creates a new 2D [[Vec]] of length `n by m` composed of the result of the given - * function applied to an element of data type T. - * - * @param n number of inner vectors (rows) in the outer vector - * @param m number of elements in each inner vector (column) - * @param gen function that takes in an element T and returns an output - * element of the same type - */ + * function applied to an element of data type T. + * + * @param n number of inner vectors (rows) in the outer vector + * @param m number of elements in each inner vector (column) + * @param gen function that takes in an element T and returns an output + * element of the same type + */ def fill[T <: Data](n: Int, m: Int)(gen: => T): Vec[Vec[T]] = macro VecTransform.fill2D /** @group SourceInfoTransformMacro */ - def do_fill[T <: Data](n: Int, m: Int)(gen: => T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Vec[Vec[T]] = { + def do_fill[T <: Data]( + n: Int, + m: Int + )(gen: => T + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Vec[Vec[T]] = { do_tabulate(n, m)((_, _) => gen) } /** Creates a new 3D [[Vec]] of length `n by m by p` composed of the result of the given - * function applied to an element of data type T. - * - * @param n number of 2D vectors inside outer vector - * @param m number of 1D vectors in each 2D vector - * @param p number of elements in each 1D vector - * @param gen function that takes in an element T and returns an output - * element of the same type - */ + * function applied to an element of data type T. + * + * @param n number of 2D vectors inside outer vector + * @param m number of 1D vectors in each 2D vector + * @param p number of elements in each 1D vector + * @param gen function that takes in an element T and returns an output + * element of the same type + */ def fill[T <: Data](n: Int, m: Int, p: Int)(gen: => T): Vec[Vec[Vec[T]]] = macro VecTransform.fill3D /** @group SourceInfoTransformMacro */ - def do_fill[T <: Data](n: Int, m: Int, p: Int)(gen: => T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Vec[Vec[Vec[T]]] = { + def do_fill[T <: Data]( + n: Int, + m: Int, + p: Int + )(gen: => T + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Vec[Vec[Vec[T]]] = { do_tabulate(n, m, p)((_, _, _) => gen) } - + /** Creates a new [[Vec]] of length `n` composed of the result of the given - * function applied to an element of data type T. - * - * @param start First element in the Vec - * @param len Lenth of elements in the Vec - * @param f Function that applies the element T from previous index and returns the output - * element to the next index - */ + * function applied to an element of data type T. + * + * @param start First element in the Vec + * @param len Lenth of elements in the Vec + * @param f Function that applies the element T from previous index and returns the output + * element to the next index + */ def iterate[T <: Data](start: T, len: Int)(f: (T) => T): Vec[T] = macro VecTransform.iterate - + /** @group SourceInfoTransformMacro */ - def do_iterate[T <: Data](start: T, len: Int)(f: (T) => T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Vec[T] = - apply(Seq.iterate(start, len)(f)) + def do_iterate[T <: Data]( + start: T, + len: Int + )(f: (T) => T + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Vec[T] = + apply(Seq.iterate(start, len)(f)) } /** A trait for [[Vec]]s containing common hardware generators for collection @@ -737,7 +830,7 @@ trait VecLike[T <: Data] extends IndexedSeq[T] with HasId with SourceInfoDoc { /** @group SourceInfoTransformMacro */ def do_forall(p: T => Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = - (this map p).fold(true.B)(_ && _) + (this.map(p)).fold(true.B)(_ && _) /** Outputs true if p outputs true for at least one element. */ @@ -745,7 +838,7 @@ trait VecLike[T <: Data] extends IndexedSeq[T] with HasId with SourceInfoDoc { /** @group SourceInfoTransformMacro */ def do_exists(p: T => Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = - (this map p).fold(false.B)(_ || _) + (this.map(p)).fold(false.B)(_ || _) /** Outputs true if the vector contains at least one element equal to x (using * the === operator). @@ -762,12 +855,12 @@ trait VecLike[T <: Data] extends IndexedSeq[T] with HasId with SourceInfoDoc { /** @group SourceInfoTransformMacro */ def do_count(p: T => Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = - SeqUtils.count(this map p) + 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) + 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. */ @@ -816,19 +909,19 @@ abstract class Record(private[chisel3] implicit val compileOptions: CompileOptio // 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)) } + for ((name, elt) <- elements) { elt.setRef(this, _namespace.name(name, leadingDigitOk = true)) } } private[chisel3] override def bind(target: Binding, parentDirection: SpecifiedDirection): Unit = { try { super.bind(target, parentDirection) - } catch { // nasty compatibility mode shim, where anything flies + } catch { // nasty compatibility mode shim, where anything flies case e: 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) + case SpecifiedDirection.Flip => ActualDirection.Bidirectional(ActualDirection.Flipped) + case _ => ActualDirection.Bidirectional(ActualDirection.Default) } } setElementRefs() @@ -861,67 +954,85 @@ abstract class Record(private[chisel3] implicit val compileOptions: CompileOptio 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") - } + 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") - ) - case VecLitBinding(litMap) => litMap.getOrElse(value, - throw new VecLiteralException(s"Vec literal $fieldName specified with out literal values") - ) + 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") + ) + case VecLitBinding(litMap) => + litMap.getOrElse( + value, + throw new VecLiteralException(s"Vec literal $fieldName specified with out literal values") + ) - } - Seq(field -> litArg) + } + 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 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 vecField: Vec[_] => - if (!(vecField typeEquivalent value)) { - throw new BundleLiteralException(s"field $fieldName $vecField specified with non-type-equivalent value $value") - } - // Copy the source BundleLitBinding with fields (keys) remapped to the clone - val remap = getMatchedFields(value, vecField).toMap - value.topBinding.asInstanceOf[VecLitBinding].litMap.map { case (valueField, valueValue) => - remap(valueField) -> valueValue - } + case vecField: Vec[_] => + if (!(vecField.typeEquivalent(value))) { + throw new BundleLiteralException( + s"field $fieldName $vecField specified with non-type-equivalent value $value" + ) + } + // Copy the source BundleLitBinding with fields (keys) remapped to the clone + val remap = getMatchedFields(value, vecField).toMap + value.topBinding.asInstanceOf[VecLitBinding].litMap.map { + case (valueField, valueValue) => + remap(valueField) -> valueValue + } - case field: EnumType => { - if (!(field typeEquivalent value)) { - throw new BundleLiteralException(s"field $fieldName $field specified with non-type-equivalent enum value $value") - } - val litArg = valueBinding match { - case ElementLitBinding(litArg) => litArg - case _ => - throw new BundleLiteralException(s"field $fieldName $field could not be matched with $valueBinding") + case field: EnumType => { + if (!(field.typeEquivalent(value))) { + throw new BundleLiteralException( + s"field $fieldName $field specified with non-type-equivalent enum value $value" + ) + } + val litArg = valueBinding match { + case ElementLitBinding(litArg) => litArg + case _ => + throw new BundleLiteralException(s"field $fieldName $field could not be matched with $valueBinding") + } + Seq(field -> litArg) } - Seq(field -> litArg) + case _ => throw new BundleLiteralException(s"unsupported field $fieldName of type $field") } - case _ => throw new BundleLiteralException(s"unsupported field $fieldName of type $field") - } } // don't convert to a Map yet to preserve duplicate keys @@ -952,8 +1063,9 @@ abstract class Record(private[chisel3] implicit val compileOptions: CompileOptio override def toString: String = { topBindingOpt match { case Some(BundleLitBinding(_)) => - val contents = elements.toList.reverse.map { case (name, data) => - s"$name=$data" + val contents = elements.toList.reverse.map { + case (name, data) => + s"$name=$data" }.mkString(", ") s"$className($contents)" case _ => stringAccessor(s"$className") @@ -968,10 +1080,12 @@ abstract class Record(private[chisel3] implicit val compileOptions: CompileOptio private[chisel3] 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)} + this.elements.size == that.elements.size && + this.elements.forall { + case (name, model) => + that.elements.contains(name) && + (that.elements(name).typeEquivalent(model)) + } case _ => false } @@ -990,11 +1104,14 @@ abstract class Record(private[chisel3] implicit val compileOptions: CompileOptio private[chisel3] def toPrintableHelper(elts: Seq[(String, Data)]): Printable = { 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 ", " + else + elts.flatMap { + case (name, data) => + List(PString(s"$name -> "), data.toPrintable, PString(", ")) + }.dropRight(1) // Remove trailing ", " PString(s"$className(") + Printables(xs) + PString(")") } + /** Default "pretty-print" implementation * Analogous to printing a Map * Results in "`\$className(elt0.name -> elt0.value, ...)`" @@ -1060,15 +1177,18 @@ package experimental { * }}} */ abstract class Bundle(implicit compileOptions: CompileOptions) extends Record { - assert(_usingPlugin, "The Chisel compiler plugin is now required for compiling Chisel code. " + - "Please see https://github.com/chipsalliance/chisel3#build-your-own-chisel-projects." + assert( + _usingPlugin, + "The Chisel compiler plugin is now required for compiling Chisel code. " + + "Please see https://github.com/chipsalliance/chisel3#build-your-own-chisel-projects." ) 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 + 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 @@ -1093,7 +1213,7 @@ abstract class Bundle(implicit compileOptions: CompileOptions) extends Record { getBundleField(m) match { case Some(d: Data) => requireIsChiselType(d) - + if (nameMap contains m.getName) { require(nameMap(m.getName) eq d) } else { @@ -1102,21 +1222,25 @@ abstract class Bundle(implicit compileOptions: CompileOptions) extends Record { 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 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 } } } } - VectorMap(nameMap.toSeq sortWith { case ((an, a), (bn, b)) => (a._id > b._id) || ((a eq b) && (an > bn)) }: _*) + VectorMap(nameMap.toSeq.sortWith { case ((an, a), (bn, b)) => (a._id > b._id) || ((a eq b) && (an > bn)) }: _*) } /** @@ -1145,10 +1269,10 @@ abstract class Bundle(implicit compileOptions: CompileOptions) extends Record { if (clone.elements(name) eq field) { throw new AutoClonetypeException( s"Automatically cloned $clone has field '$name' aliased with base $this." + - " In the future, this will be solved automatically by the compiler plugin." + - " For now, ensure Chisel types used in the Bundle definition are passed through constructor arguments," + - " or wrapped in Input(...), Output(...), or Flipped(...) if appropriate." + - " As a last resort, you can override cloneType manually." + " In the future, this will be solved automatically by the compiler plugin." + + " For now, ensure Chisel types used in the Bundle definition are passed through constructor arguments," + + " or wrapped in Input(...), Output(...), or Flipped(...) if appropriate." + + " As a last resort, you can override cloneType manually." ) } } @@ -1166,7 +1290,9 @@ abstract class Bundle(implicit compileOptions: CompileOptions) extends Record { * @note This is overridden by the compiler plugin (this implementation is never called) */ protected def _cloneTypeImpl: Bundle = { - throwException(s"Internal Error! This should have been implemented by the chisel3-plugin. Please file an issue against chisel3") + throwException( + s"Internal Error! This should have been implemented by the chisel3-plugin. Please file an issue against chisel3" + ) } /** Default "pretty-print" implementation @@ -1177,4 +1303,3 @@ abstract class Bundle(implicit compileOptions: CompileOptions) extends Record { */ override def toPrintable: Printable = toPrintableHelper(elements.toList.reverse) } - diff --git a/core/src/main/scala/chisel3/Annotation.scala b/core/src/main/scala/chisel3/Annotation.scala index 545ea480..e08557eb 100644 --- a/core/src/main/scala/chisel3/Annotation.scala +++ b/core/src/main/scala/chisel3/Annotation.scala @@ -15,6 +15,7 @@ import firrtl.transforms.{DontTouchAnnotation, NoDedupAnnotation} * Defines a conversion to a corresponding FIRRTL Annotation */ trait ChiselAnnotation { + /** Conversion to FIRRTL Annotation */ def toFirrtl: Annotation } @@ -54,7 +55,7 @@ object annotate { * m.io.out * } * - *class AdderTester extends Module + * class AdderTester extends Module * with ConstantPropagationTest { * val io = IO(new Bundle { * val a = Input(UInt(32.W)) @@ -73,12 +74,13 @@ object annotate { */ object doNotDedup { + /** Marks a module to be ignored in Dedup Transform in Firrtl * * @param module The module to be marked * @return Unmodified signal `module` */ - def apply[T <: RawModule](module: T)(implicit compileOptions: CompileOptions): Unit = { + def apply[T <: RawModule](module: T)(implicit compileOptions: CompileOptions): Unit = { annotate(new ChiselAnnotation { def toFirrtl = NoDedupAnnotation(module.toNamed) }) } } diff --git a/core/src/main/scala/chisel3/Attach.scala b/core/src/main/scala/chisel3/Attach.scala index 0e005690..5c9cfe53 100644 --- a/core/src/main/scala/chisel3/Attach.scala +++ b/core/src/main/scala/chisel3/Attach.scala @@ -43,4 +43,3 @@ object attach { } } } - diff --git a/core/src/main/scala/chisel3/Bits.scala b/core/src/main/scala/chisel3/Bits.scala index 5ab04d13..8a616d02 100644 --- a/core/src/main/scala/chisel3/Bits.scala +++ b/core/src/main/scala/chisel3/Bits.scala @@ -8,13 +8,11 @@ import chisel3.experimental.{FixedPoint, Interval} import chisel3.internal._ import chisel3.internal.Builder.pushOp import chisel3.internal.firrtl._ -import chisel3.internal.sourceinfo.{SourceInfo, SourceInfoTransform, SourceInfoWhiteboxTransform, - UIntTransform} +import chisel3.internal.sourceinfo.{SourceInfo, SourceInfoTransform, SourceInfoWhiteboxTransform, UIntTransform} import chisel3.internal.firrtl.PrimOp._ import _root_.firrtl.{ir => firrtlir} import _root_.firrtl.{constraint => firrtlconstraint} - /** Exists to unify common interfaces of [[Bits]] and [[Reset]]. * * @note This is a workaround because macros cannot override abstract methods. @@ -27,7 +25,10 @@ private[chisel3] sealed trait ToBoolable extends Element { */ final def asBool: Bool = macro SourceInfoWhiteboxTransform.noArg - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) final def asBool(dummy: Int*): Bool = macro SourceInfoWhiteboxTransform.noArgDummy /** @group SourceInfoTransformMacro */ @@ -82,7 +83,7 @@ sealed abstract class Bits(private[chisel3] val width: Width) extends Element wi /** @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 KnownWidth(x) => require(x >= n, s"Can't head($n) for width $x < $n") case UnknownWidth() => } binop(sourceInfo, UInt(Width(n)), HeadOp, n) @@ -217,7 +218,7 @@ sealed abstract class Bits(private[chisel3] val width: Width) extends Element wi /** @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) + case _ => binop(sourceInfo, cloneTypeWidth(this.width.max(Width(that))), PadOp, that) } /** Bitwise inversion operator @@ -227,11 +228,14 @@ sealed abstract class Bits(private[chisel3] val width: Width) extends Element wi */ final def unary_~ : Bits = macro SourceInfoWhiteboxTransform.noArg - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) final def unary_~(dummy: Int*): Bits = macro SourceInfoWhiteboxTransform.noArgDummy /** @group SourceInfoTransformMacro */ - def do_unary_~ (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bits + def do_unary_~(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bits /** Static left shift operator * @@ -242,10 +246,10 @@ sealed abstract class Bits(private[chisel3] val width: Width) extends Element wi */ // REVIEW TODO: redundant // REVIEW TODO: should these return this.type or Bits? - final def << (that: BigInt): Bits = macro SourceInfoWhiteboxTransform.thatArg + final def <<(that: BigInt): Bits = macro SourceInfoWhiteboxTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_<< (that: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bits + def do_<<(that: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bits /** Static left shift operator * @@ -254,10 +258,10 @@ sealed abstract class Bits(private[chisel3] val width: Width) extends Element wi * $sumWidthInt * @group Bitwise */ - final def << (that: Int): Bits = macro SourceInfoWhiteboxTransform.thatArg + final def <<(that: Int): Bits = macro SourceInfoWhiteboxTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_<< (that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bits + def do_<<(that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bits /** Dynamic left shift operator * @@ -266,10 +270,10 @@ sealed abstract class Bits(private[chisel3] val width: Width) extends Element wi * @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 + final def <<(that: UInt): Bits = macro SourceInfoWhiteboxTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_<< (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bits + def do_<<(that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bits /** Static right shift operator * @@ -279,10 +283,10 @@ sealed abstract class Bits(private[chisel3] val width: Width) extends Element wi * @group Bitwise */ // REVIEW TODO: redundant - final def >> (that: BigInt): Bits = macro SourceInfoWhiteboxTransform.thatArg + final def >>(that: BigInt): Bits = macro SourceInfoWhiteboxTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_>> (that: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bits + def do_>>(that: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bits /** Static right shift operator * @@ -291,10 +295,10 @@ sealed abstract class Bits(private[chisel3] val width: Width) extends Element wi * $unchangedWidth * @group Bitwise */ - final def >> (that: Int): Bits = macro SourceInfoWhiteboxTransform.thatArg + final def >>(that: Int): Bits = macro SourceInfoWhiteboxTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_>> (that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bits + def do_>>(that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bits /** Dynamic right shift operator * @@ -304,15 +308,18 @@ sealed abstract class Bits(private[chisel3] val width: Width) extends Element wi * $unchangedWidth * @group Bitwise */ - final def >> (that: UInt): Bits = macro SourceInfoWhiteboxTransform.thatArg + final def >>(that: UInt): Bits = macro SourceInfoWhiteboxTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_>> (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bits + 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 asBools: Seq[Bool] = macro SourceInfoTransform.noArg - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) final def asBools(dummy: Int*): Seq[Bool] = macro SourceInfoWhiteboxTransform.noArgDummy /** @group SourceInfoTransformMacro */ @@ -326,7 +333,10 @@ sealed abstract class Bits(private[chisel3] val width: Width) extends Element wi */ final def asSInt: SInt = macro SourceInfoTransform.noArg - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) final def asSInt(dummy: Int*): SInt = macro SourceInfoWhiteboxTransform.noArgDummy /** @group SourceInfoTransformMacro */ @@ -341,7 +351,12 @@ sealed abstract class Bits(private[chisel3] val width: Width) extends Element wi final def asFixedPoint(that: BinaryPoint): FixedPoint = macro SourceInfoTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_asFixedPoint(that: BinaryPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = { + def do_asFixedPoint( + that: BinaryPoint + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): FixedPoint = { throwException(s"Cannot call .asFixedPoint on $this") } @@ -360,7 +375,7 @@ sealed abstract class Bits(private[chisel3] val width: Width) extends Element wi 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") + case _ => throwException(s"can't covert ${this.getClass.getSimpleName}$width to Bool") } } @@ -371,10 +386,10 @@ sealed abstract class Bits(private[chisel3] val width: Width) extends Element wi * $sumWidth * @group Bitwise */ - final def ## (that: Bits): UInt = macro SourceInfoTransform.thatArg + final def ##(that: Bits): UInt = macro SourceInfoTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_## (that: Bits)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = { + 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)) } @@ -401,7 +416,7 @@ sealed class UInt private[chisel3] (width: Width) extends Bits(width) with Num[U override def toString: String = { litOption match { case Some(value) => s"UInt$width($value)" - case _ => stringAccessor(s"UInt$width") + case _ => stringAccessor(s"UInt$width") } } @@ -420,7 +435,10 @@ sealed class UInt private[chisel3] (width: Width) extends Bits(width) with Num[U */ final def unary_- : UInt = macro SourceInfoTransform.noArg - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) final def unary_-(dummy: Int*): UInt = macro SourceInfoTransform.noArgDummy /** Unary negation (constant width) @@ -431,21 +449,25 @@ sealed class UInt private[chisel3] (width: Width) extends Bits(width) with Num[U */ final def unary_-% : UInt = macro SourceInfoTransform.noArg - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) final def unary_%(dummy: Int*): UInt = macro SourceInfoTransform.noArgDummy /** @group SourceInfoTransformMacro */ - def do_unary_- (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) : UInt = 0.U - this + 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 + 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 = + 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 min that.width), RemOp, that) - override def do_* (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = + override def do_%(that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = + binop(sourceInfo, UInt(this.width.min(that.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 @@ -456,9 +478,10 @@ sealed class UInt private[chisel3] (width: Width) extends Bits(width) with Num[U * $singleCycleMul * @group Arithmetic */ - final def * (that: SInt): SInt = macro SourceInfoTransform.thatArg + final def *(that: SInt): SInt = macro SourceInfoTransform.thatArg + /** @group SourceInfoTransformMacro */ - def do_* (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = that * this + def do_*(that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = that * this /** Addition operator (expanding width) * @@ -467,7 +490,7 @@ sealed class UInt private[chisel3] (width: Width) extends Bits(width) with Num[U * $maxWidthPlusOne * @group Arithmetic */ - final def +& (that: UInt): UInt = macro SourceInfoTransform.thatArg + final def +&(that: UInt): UInt = macro SourceInfoTransform.thatArg /** Addition operator (constant width) * @@ -476,7 +499,7 @@ sealed class UInt private[chisel3] (width: Width) extends Bits(width) with Num[U * $maxWidth * @group Arithmetic */ - final def +% (that: UInt): UInt = macro SourceInfoTransform.thatArg + final def +%(that: UInt): UInt = macro SourceInfoTransform.thatArg /** Subtraction operator (increasing width) * @@ -485,7 +508,7 @@ sealed class UInt private[chisel3] (width: Width) extends Bits(width) with Num[U * $maxWidthPlusOne * @group Arithmetic */ - final def -& (that: UInt): UInt = macro SourceInfoTransform.thatArg + final def -&(that: UInt): UInt = macro SourceInfoTransform.thatArg /** Subtraction operator (constant width) * @@ -494,20 +517,23 @@ sealed class UInt private[chisel3] (width: Width) extends Bits(width) with Num[U * $maxWidth * @group Arithmetic */ - final def -% (that: UInt): UInt = macro SourceInfoTransform.thatArg + 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) + 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 = + 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 + 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) + def do_-%(that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = + (this.subtractAsSInt(that)).tail(1) /** Bitwise and operator * @@ -516,7 +542,7 @@ sealed class UInt private[chisel3] (width: Width) extends Bits(width) with Num[U * $maxWidth * @group Bitwise */ - final def & (that: UInt): UInt = macro SourceInfoTransform.thatArg + final def &(that: UInt): UInt = macro SourceInfoTransform.thatArg /** Bitwise or operator * @@ -525,7 +551,7 @@ sealed class UInt private[chisel3] (width: Width) extends Bits(width) with Num[U * $maxWidth * @group Bitwise */ - final def | (that: UInt): UInt = macro SourceInfoTransform.thatArg + final def |(that: UInt): UInt = macro SourceInfoTransform.thatArg /** Bitwise exclusive or (xor) operator * @@ -534,23 +560,25 @@ sealed class UInt private[chisel3] (width: Width) extends Bits(width) with Num[U * $maxWidth * @group Bitwise */ - final def ^ (that: UInt): UInt = macro SourceInfoTransform.thatArg + final def ^(that: UInt): UInt = macro SourceInfoTransform.thatArg // override def abs: UInt = macro SourceInfoTransform.noArgDummy 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) + 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) + 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) + 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 = + def do_unary_~(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = unop(sourceInfo, UInt(width = width), BitNotOp) // REVIEW TODO: Can these be defined on Bits? @@ -561,7 +589,10 @@ sealed class UInt private[chisel3] (width: Width) extends Bits(width) with Num[U */ final def orR: Bool = macro SourceInfoTransform.noArg - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) final def orR(dummy: Int*): Bool = macro SourceInfoTransform.noArgDummy /** And reduction operator @@ -571,7 +602,10 @@ sealed class UInt private[chisel3] (width: Width) extends Bits(width) with Num[U */ final def andR: Bool = macro SourceInfoTransform.noArg - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) final def andR(dummy: Int*): Bool = macro SourceInfoTransform.noArgDummy /** Exclusive or (xor) reduction operator @@ -581,20 +615,29 @@ sealed class UInt private[chisel3] (width: Width) extends Bits(width) with Num[U */ final def xorR: Bool = macro SourceInfoTransform.noArg - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) final def xorR(dummy: Int*): Bool = macro SourceInfoTransform.noArgDummy /** @group SourceInfoTransformMacro */ def do_orR(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = redop(sourceInfo, OrReduceOp) + /** @group SourceInfoTransformMacro */ def do_andR(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = redop(sourceInfo, AndReduceOp) + /** @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) + 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) /** Dynamic not equals operator * @@ -602,7 +645,7 @@ sealed class UInt private[chisel3] (width: Width) extends Bits(width) with Num[U * @return a hardware [[Bool]] asserted if this $coll is not equal to `that` * @group Comparison */ - final def =/= (that: UInt): Bool = macro SourceInfoTransform.thatArg + final def =/=(that: UInt): Bool = macro SourceInfoTransform.thatArg /** Dynamic equals operator * @@ -610,12 +653,15 @@ sealed class UInt private[chisel3] (width: Width) extends Bits(width) with Num[U * @return a hardware [[Bool]] asserted if this $coll is equal to `that` * @group Comparison */ - final def === (that: UInt): Bool = macro SourceInfoTransform.thatArg + final def ===(that: UInt): Bool = macro SourceInfoTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_=/= (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, NotEqualOp, that) + 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) + def do_===(that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = + compop(sourceInfo, EqualOp, that) /** Unary not * @@ -624,70 +670,78 @@ sealed class UInt private[chisel3] (width: Width) extends Bits(width) with Num[U */ final def unary_! : Bool = macro SourceInfoTransform.noArg - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") - final def unary_! (dummy: Int*): Bool = macro SourceInfoTransform.noArgDummy + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) + final def unary_!(dummy: Int*): Bool = macro SourceInfoTransform.noArgDummy /** @group SourceInfoTransformMacro */ - def do_unary_! (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) : Bool = this === 0.U(1.W) + 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 = + 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 = + 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 = + 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 = + 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 = + 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 = + override def do_>>(that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = binop(sourceInfo, UInt(this.width), DynamicShiftRightOp, that) /** - * Circular shift to the left - * @param that number of bits to rotate - * @return UInt of same width rotated left n bits - */ - final def rotateLeft(that: Int): UInt = macro SourceInfoWhiteboxTransform.thatArg + * Circular shift to the left + * @param that number of bits to rotate + * @return UInt of same width rotated left n bits + */ + final def rotateLeft(that: Int): UInt = macro SourceInfoWhiteboxTransform.thatArg def do_rotateLeft(n: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = width match { - case _ if (n == 0) => this + case _ if (n == 0) => this case KnownWidth(w) if (w <= 1) => this - case KnownWidth(w) if n >= w => do_rotateLeft(n % w) - case _ if (n < 0) => do_rotateRight(-n) - case _ => tail(n) ## head(n) + case KnownWidth(w) if n >= w => do_rotateLeft(n % w) + case _ if (n < 0) => do_rotateRight(-n) + case _ => tail(n) ## head(n) } /** - * Circular shift to the right - * @param that number of bits to rotate - * @return UInt of same width rotated right n bits - */ - final def rotateRight(that: Int): UInt = macro SourceInfoWhiteboxTransform.thatArg + * Circular shift to the right + * @param that number of bits to rotate + * @return UInt of same width rotated right n bits + */ + final def rotateRight(that: Int): UInt = macro SourceInfoWhiteboxTransform.thatArg def do_rotateRight(n: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = width match { - case _ if (n <= 0) => do_rotateLeft(-n) + case _ if (n <= 0) => do_rotateLeft(-n) case KnownWidth(w) if (w <= 1) => this - case KnownWidth(w) if n >= w => do_rotateRight(n % w) - case _ => this(n - 1, 0) ## (this >> n) + case KnownWidth(w) if n >= w => do_rotateRight(n % w) + case _ => this(n - 1, 0) ## (this >> n) } - final def rotateRight(that: UInt): UInt = macro SourceInfoWhiteboxTransform.thatArg + final def rotateRight(that: UInt): UInt = macro SourceInfoWhiteboxTransform.thatArg - private def dynamicShift(n: UInt, staticShift: (UInt,Int) => UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) : UInt = - n.asBools().zipWithIndex.foldLeft(this){ - case (in, (en, sh)) => Mux(en, staticShift(in, 1 << sh), in) + private def dynamicShift( + n: UInt, + staticShift: (UInt, Int) => UInt + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): UInt = + n.asBools().zipWithIndex.foldLeft(this) { + case (in, (en, sh)) => Mux(en, staticShift(in, 1 << sh), in) } def do_rotateRight(n: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = dynamicShift(n, _ rotateRight _) - final def rotateLeft(that: UInt): UInt = macro SourceInfoWhiteboxTransform.thatArg + final def rotateLeft(that: UInt): UInt = macro SourceInfoWhiteboxTransform.thatArg def do_rotateLeft(n: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = dynamicShift(n, _ rotateLeft _) - /** Conditionally set or clear a bit * * @param off a dynamic offset @@ -712,7 +766,10 @@ sealed class UInt private[chisel3] (width: Width) extends Bits(width) with Num[U */ final def zext: SInt = macro SourceInfoTransform.noArg - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) final def zext(dummy: Int*): SInt = macro SourceInfoTransform.noArgDummy /** @group SourceInfoTransformMacro */ @@ -722,44 +779,58 @@ sealed class UInt private[chisel3] (width: Width) extends Bits(width) with Num[U 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 = { + 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") + throwException( + s"cannot call $this.asFixedPoint(binaryPoint=$binaryPoint), you must specify a known binaryPoint" + ) } } - override def do_asInterval(range: IntervalRange = IntervalRange.Unknown) - (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Interval = { + override def do_asInterval( + range: IntervalRange = IntervalRange.Unknown + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Interval = { (range.lower, range.upper, range.binaryPoint) match { case (lx: firrtlconstraint.IsKnown, ux: firrtlconstraint.IsKnown, KnownBinaryPoint(bp)) => // No mechanism to pass open/close to firrtl so need to handle directly val l = lx match { - case firrtlir.Open(x) => x + BigDecimal(1) / BigDecimal(BigInt(1) << bp) + case firrtlir.Open(x) => x + BigDecimal(1) / BigDecimal(BigInt(1) << bp) case firrtlir.Closed(x) => x } val u = ux match { - case firrtlir.Open(x) => x - BigDecimal(1) / BigDecimal(BigInt(1) << bp) + case firrtlir.Open(x) => x - BigDecimal(1) / BigDecimal(BigInt(1) << bp) case firrtlir.Closed(x) => x } val minBI = (l * BigDecimal(BigInt(1) << bp)).setScale(0, BigDecimal.RoundingMode.FLOOR).toBigIntExact.get val maxBI = (u * BigDecimal(BigInt(1) << bp)).setScale(0, BigDecimal.RoundingMode.FLOOR).toBigIntExact.get pushOp(DefPrim(sourceInfo, Interval(range), AsIntervalOp, ref, ILit(minBI), ILit(maxBI), ILit(bp))) case _ => - throwException( - s"cannot call $this.asInterval($range), you must specify a known binaryPoint and range") + throwException(s"cannot call $this.asInterval($range), you must specify a known binaryPoint and range") } } - private[chisel3] override def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo, - compileOptions: CompileOptions): Unit = { + private[chisel3] 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) + binop(sourceInfo, SInt((this.width.max(that.width)) + 1), SubOp, that) } /** A data type for signed integers, represented as a binary bitvector. Defines arithmetic operations between other @@ -774,12 +845,12 @@ sealed class SInt private[chisel3] (width: Width) extends Bits(width) with Num[S override def toString: String = { litOption match { case Some(value) => s"SInt$width($value)" - case _ => stringAccessor(s"SInt$width") + case _ => stringAccessor(s"SInt$width") } } private[chisel3] override def typeEquivalent(that: Data): Boolean = - this.getClass == that.getClass && this.width == that.width // TODO: should this be true for unspecified widths? + this.getClass == that.getClass && this.width == that.width // TODO: should this be true for unspecified widths? private[chisel3] override def cloneTypeWidth(w: Width): this.type = new SInt(w).asInstanceOf[this.type] @@ -792,7 +863,10 @@ sealed class SInt private[chisel3] (width: Width) extends Bits(width) with Num[S */ final def unary_- : SInt = macro SourceInfoTransform.noArg - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) final def unary_-(dummy: Int*): SInt = macro SourceInfoTransform.noArgDummy /** Unary negation (constant width) @@ -803,26 +877,31 @@ sealed class SInt private[chisel3] (width: Width) extends Bits(width) with Num[S */ final def unary_-% : SInt = macro SourceInfoTransform.noArg - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) final def unary_-%(dummy: Int*): SInt = macro SourceInfoTransform.noArgDummy /** @group SourceInfoTransformMacro */ - def do_unary_- (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = 0.S - this + def do_unary_-(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = 0.S - this + /** @group SourceInfoTransformMacro */ - def do_unary_-% (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = 0.S -% this + def do_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 = + 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 = + override def do_-(that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = this -% that - override def do_* (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = + 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 = + override def do_/(that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = binop(sourceInfo, SInt(this.width + 1), DivideOp, that) - override def do_% (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = - binop(sourceInfo, SInt(this.width min that.width), RemOp, that) + override def do_%(that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = + binop(sourceInfo, SInt(this.width.min(that.width)), RemOp, that) /** Multiplication operator * @@ -832,9 +911,10 @@ sealed class SInt private[chisel3] (width: Width) extends Bits(width) with Num[S * $singleCycleMul * @group Arithmetic */ - final def * (that: UInt): SInt = macro SourceInfoTransform.thatArg + final def *(that: UInt): SInt = macro SourceInfoTransform.thatArg + /** @group SourceInfoTransformMacro */ - def do_* (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = { + 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 @@ -847,7 +927,7 @@ sealed class SInt private[chisel3] (width: Width) extends Bits(width) with Num[S * $maxWidthPlusOne * @group Arithmetic */ - final def +& (that: SInt): SInt = macro SourceInfoTransform.thatArg + final def +&(that: SInt): SInt = macro SourceInfoTransform.thatArg /** Addition operator (constant width) * @@ -856,7 +936,7 @@ sealed class SInt private[chisel3] (width: Width) extends Bits(width) with Num[S * $maxWidth * @group Arithmetic */ - final def +% (that: SInt): SInt = macro SourceInfoTransform.thatArg + final def +%(that: SInt): SInt = macro SourceInfoTransform.thatArg /** Subtraction operator (increasing width) * @@ -865,7 +945,7 @@ sealed class SInt private[chisel3] (width: Width) extends Bits(width) with Num[S * $maxWidthPlusOne * @group Arithmetic */ - final def -& (that: SInt): SInt = macro SourceInfoTransform.thatArg + final def -&(that: SInt): SInt = macro SourceInfoTransform.thatArg /** Subtraction operator (constant width) * @@ -874,19 +954,22 @@ sealed class SInt private[chisel3] (width: Width) extends Bits(width) with Num[S * $maxWidth * @group Arithmetic */ - final def -% (that: SInt): SInt = macro SourceInfoTransform.thatArg + 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) + 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 = + 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) + 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 = + def do_-%(that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = (this -& that).tail(1).asSInt /** Bitwise and operator @@ -896,7 +979,7 @@ sealed class SInt private[chisel3] (width: Width) extends Bits(width) with Num[S * $maxWidth * @group Bitwise */ - final def & (that: SInt): SInt = macro SourceInfoTransform.thatArg + final def &(that: SInt): SInt = macro SourceInfoTransform.thatArg /** Bitwise or operator * @@ -905,7 +988,7 @@ sealed class SInt private[chisel3] (width: Width) extends Bits(width) with Num[S * $maxWidth * @group Bitwise */ - final def | (that: SInt): SInt = macro SourceInfoTransform.thatArg + final def |(that: SInt): SInt = macro SourceInfoTransform.thatArg /** Bitwise exclusive or (xor) operator * @@ -914,26 +997,32 @@ sealed class SInt private[chisel3] (width: Width) extends Bits(width) with Num[S * $maxWidth * @group Bitwise */ - final def ^ (that: SInt): SInt = macro SourceInfoTransform.thatArg + 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 + 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 + 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 + 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 = + 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) + 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) /** Dynamic not equals operator * @@ -941,7 +1030,7 @@ sealed class SInt private[chisel3] (width: Width) extends Bits(width) with Num[S * @return a hardware [[Bool]] asserted if this $coll is not equal to `that` * @group Comparison */ - final def =/= (that: SInt): Bool = macro SourceInfoTransform.thatArg + final def =/=(that: SInt): Bool = macro SourceInfoTransform.thatArg /** Dynamic equals operator * @@ -949,12 +1038,15 @@ sealed class SInt private[chisel3] (width: Width) extends Bits(width) with Num[S * @return a hardware [[Bool]] asserted if this $coll is equal to `that` * @group Comparison */ - final def === (that: SInt): Bool = macro SourceInfoTransform.thatArg + final def ===(that: SInt): Bool = macro SourceInfoTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_=/= (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, NotEqualOp, that) + 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) + def do_===(that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = + compop(sourceInfo, EqualOp, that) // final def abs(): UInt = macro SourceInfoTransform.noArgDummy @@ -962,42 +1054,55 @@ sealed class SInt private[chisel3] (width: Width) extends Bits(width) with Num[S Mux(this < 0.S, -this, this) } - override def do_<< (that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = + 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 = + 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 = + 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 = + 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 = + 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 = + 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_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 = { + 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") + throwException( + s"cannot call $this.asFixedPoint(binaryPoint=$binaryPoint), you must specify a known binaryPoint" + ) } } - override def do_asInterval(range: IntervalRange = IntervalRange.Unknown) - (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Interval = { + override def do_asInterval( + range: IntervalRange = IntervalRange.Unknown + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Interval = { (range.lower, range.upper, range.binaryPoint) match { case (lx: firrtlconstraint.IsKnown, ux: firrtlconstraint.IsKnown, KnownBinaryPoint(bp)) => // No mechanism to pass open/close to firrtl so need to handle directly val l = lx match { - case firrtlir.Open(x) => x + BigDecimal(1) / BigDecimal(BigInt(1) << bp) + case firrtlir.Open(x) => x + BigDecimal(1) / BigDecimal(BigInt(1) << bp) case firrtlir.Closed(x) => x } val u = ux match { - case firrtlir.Open(x) => x - BigDecimal(1) / BigDecimal(BigInt(1) << bp) + case firrtlir.Open(x) => x - BigDecimal(1) / BigDecimal(BigInt(1) << bp) case firrtlir.Closed(x) => x } //TODO: (chick) Need to determine, what asInterval needs, and why it might need min and max as args -- CAN IT BE UNKNOWN? @@ -1006,21 +1111,29 @@ sealed class SInt private[chisel3] (width: Width) extends Bits(width) with Num[S val maxBI = (u * BigDecimal(BigInt(1) << bp)).setScale(0, BigDecimal.RoundingMode.FLOOR).toBigIntExact.get pushOp(DefPrim(sourceInfo, Interval(range), AsIntervalOp, ref, ILit(minBI), ILit(maxBI), ILit(bp))) case _ => - throwException( - s"cannot call $this.asInterval($range), you must specify a known binaryPoint and range") + throwException(s"cannot call $this.asInterval($range), you must specify a known binaryPoint and range") } } - private[chisel3] override def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) { + private[chisel3] override def connectFromBits( + that: Bits + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ) { this := that.asSInt } } sealed trait Reset extends Element with ToBoolable { + /** Casts this $coll to an [[AsyncReset]] */ final def asAsyncReset: AsyncReset = macro SourceInfoWhiteboxTransform.noArg - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) final def asAsyncReset(dummy: Int*): AsyncReset = macro SourceInfoTransform.noArgDummy /** @group SourceInfoTransformMacro */ @@ -1049,10 +1162,16 @@ final class ResetType(private[chisel3] val width: Width = Width(1)) extends Elem /** Not really supported */ def toPrintable: Printable = PString("Reset") - override def do_asUInt(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions): UInt = pushOp(DefPrim(sourceInfo, UInt(this.width), AsUIntOp, ref)) + override def do_asUInt(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions): UInt = pushOp( + DefPrim(sourceInfo, UInt(this.width), AsUIntOp, ref) + ) - private[chisel3] override def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo, - compileOptions: CompileOptions): Unit = { + private[chisel3] override def connectFromBits( + that: Bits + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Unit = { this := that } @@ -1091,11 +1210,17 @@ sealed class AsyncReset(private[chisel3] val width: Width = Width(1)) extends El /** Not really supported */ def toPrintable: Printable = PString("AsyncReset") - override def do_asUInt(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions): UInt = pushOp(DefPrim(sourceInfo, UInt(this.width), AsUIntOp, ref)) + override def do_asUInt(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions): UInt = pushOp( + DefPrim(sourceInfo, UInt(this.width), AsUIntOp, ref) + ) // TODO Is this right? - private[chisel3] override def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo, - compileOptions: CompileOptions): Unit = { + private[chisel3] override def connectFromBits( + that: Bits + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Unit = { this := that.asBool.asAsyncReset } @@ -1121,7 +1246,7 @@ sealed class Bool() extends UInt(1.W) with Reset { override def toString: String = { litToBooleanOption match { case Some(value) => s"Bool($value)" - case _ => stringAccessor("Bool") + case _ => stringAccessor("Bool") } } @@ -1134,7 +1259,7 @@ sealed class Bool() extends UInt(1.W) with Reset { 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") + case intVal => throwException(s"Boolean with unexpected literal value $intVal") } /** Convert to a [[scala.Boolean]] */ @@ -1149,7 +1274,7 @@ sealed class Bool() extends UInt(1.W) with Reset { * @return the bitwise and of this $coll and `that` * @group Bitwise */ - final def & (that: Bool): Bool = macro SourceInfoTransform.thatArg + final def &(that: Bool): Bool = macro SourceInfoTransform.thatArg /** Bitwise or operator * @@ -1157,7 +1282,7 @@ sealed class Bool() extends UInt(1.W) with Reset { * @return the bitwise or of this $coll and `that` * @group Bitwise */ - final def | (that: Bool): Bool = macro SourceInfoTransform.thatArg + final def |(that: Bool): Bool = macro SourceInfoTransform.thatArg /** Bitwise exclusive or (xor) operator * @@ -1165,20 +1290,22 @@ sealed class Bool() extends UInt(1.W) with Reset { * @return the bitwise xor of this $coll and `that` * @group Bitwise */ - final def ^ (that: Bool): Bool = macro SourceInfoTransform.thatArg + final def ^(that: Bool): Bool = macro SourceInfoTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_& (that: Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = + 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 = + 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 = + 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 = + override def do_unary_~(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = unop(sourceInfo, Bool(), BitNotOp) /** Logical or operator @@ -1188,10 +1315,10 @@ sealed class Bool() extends UInt(1.W) with Reset { * @note this is equivalent to [[Bool!.|(that:chisel3\.Bool)* Bool.|)]] * @group Logical */ - def || (that: Bool): Bool = macro SourceInfoTransform.thatArg + def ||(that: Bool): Bool = macro SourceInfoTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_|| (that: Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = this | that + def do_||(that: Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = this | that /** Logical and operator * @@ -1200,19 +1327,24 @@ sealed class Bool() extends UInt(1.W) with Reset { * @note this is equivalent to [[Bool!.&(that:chisel3\.Bool)* Bool.&]] * @group Logical */ - def && (that: Bool): Bool = macro SourceInfoTransform.thatArg + def &&(that: Bool): Bool = macro SourceInfoTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_&& (that: Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = this & that + def do_&&(that: Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = this & that /** Reinterprets this $coll as a clock */ def asClock: Clock = macro SourceInfoTransform.noArg - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) def asClock(dummy: Int*): Clock = macro SourceInfoTransform.noArgDummy /** @group SourceInfoTransformMacro */ - def do_asClock(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Clock = pushOp(DefPrim(sourceInfo, Clock(), AsClockOp, ref)) + def do_asClock(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Clock = pushOp( + DefPrim(sourceInfo, Clock(), AsClockOp, ref) + ) /** @group SourceInfoTransformMacro */ def do_asAsyncReset(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): AsyncReset = @@ -1261,6 +1393,7 @@ package experimental { */ def litToBigDecimal: BigDecimal = litToBigDecimalOption.get } + /** 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. * @@ -1275,28 +1408,32 @@ package experimental { * @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] with HasBinaryPoint { + sealed class FixedPoint private (width: Width, val binaryPoint: BinaryPoint) + extends Bits(width) + with Num[FixedPoint] + with HasBinaryPoint { override def toString: String = { litToDoubleOption match { case Some(value) => s"FixedPoint$width$binaryPoint($value)" - case _ => stringAccessor(s"FixedPoint$width$binaryPoint") + case _ => stringAccessor(s"FixedPoint$width$binaryPoint") } } private[chisel3] 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 that: FixedPoint => + this.width == that.width && this.binaryPoint == that.binaryPoint // TODO: should this be true for unspecified widths? case _ => false } private[chisel3] 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 - } + override def connect(that: Data)(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions): Unit = + that match { + case _: FixedPoint | DontCare => super.connect(that) + case _ => this.badConnect(that) + } /** Unary negation (expanding width) * @@ -1306,7 +1443,10 @@ package experimental { */ final def unary_- : FixedPoint = macro SourceInfoTransform.noArg - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) final def unary_-(dummy: Int*): FixedPoint = macro SourceInfoTransform.noArgDummy /** Unary negation (constant width) @@ -1316,28 +1456,34 @@ package experimental { * @group Arithmetic */ final def unary_-% : FixedPoint = macro SourceInfoTransform.noArg - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) final def unary_-%(dummy: Int*): FixedPoint = macro SourceInfoTransform.noArgDummy /** @group SourceInfoTransformMacro */ - def do_unary_- (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = FixedPoint.fromBigInt(0) - this + def do_unary_-(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + FixedPoint.fromBigInt(0) - this + /** @group SourceInfoTransformMacro */ - def do_unary_-% (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = FixedPoint.fromBigInt(0) -% this + def do_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 = + 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 = + override def do_-(that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = this -% that - override def do_* (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + 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 = + 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 = + 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]] @@ -1346,9 +1492,10 @@ package experimental { * $singleCycleMul * @group Arithmetic */ - final def * (that: UInt): FixedPoint = macro SourceInfoTransform.thatArg + final def *(that: UInt): FixedPoint = macro SourceInfoTransform.thatArg + /** @group SourceInfoTransformMacro */ - def do_* (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + def do_*(that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = binop(sourceInfo, FixedPoint(this.width + that.width, binaryPoint), TimesOp, that) /** Multiplication operator @@ -1359,9 +1506,10 @@ package experimental { * $singleCycleMul * @group Arithmetic */ - final def * (that: SInt): FixedPoint = macro SourceInfoTransform.thatArg + final def *(that: SInt): FixedPoint = macro SourceInfoTransform.thatArg + /** @group SourceInfoTransformMacro */ - def do_* (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + def do_*(that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = binop(sourceInfo, FixedPoint(this.width + that.width, binaryPoint), TimesOp, that) /** Addition operator (expanding width) @@ -1371,7 +1519,7 @@ package experimental { * $maxWidthPlusOne * @group Arithmetic */ - final def +& (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg + final def +&(that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg /** Addition operator (constant width) * @@ -1380,7 +1528,7 @@ package experimental { * $maxWidth * @group Arithmetic */ - final def +% (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg + final def +%(that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg /** Subtraction operator (increasing width) * @@ -1389,7 +1537,7 @@ package experimental { * $maxWidthPlusOne * @group Arithmetic */ - final def -& (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg + final def -&(that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg /** Subtraction operator (constant width) * @@ -1398,44 +1546,45 @@ package experimental { * $maxWidth * @group Arithmetic */ - final def -% (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg + final def -%(that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_+& (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = { + 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 + 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 + 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) + 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 = { + 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 + 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 + 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) + def do_-%(that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + (this -& that).tail(1).asFixedPoint(this.binaryPoint.max(that.binaryPoint)) /** Bitwise and operator * @@ -1444,7 +1593,7 @@ package experimental { * $maxWidth * @group Bitwise */ - final def & (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg + final def &(that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg /** Bitwise or operator * @@ -1453,7 +1602,7 @@ package experimental { * $maxWidth * @group Bitwise */ - final def | (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg + final def |(that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg /** Bitwise exclusive or (xor) operator * @@ -1462,38 +1611,45 @@ package experimental { * $maxWidth * @group Bitwise */ - final def ^ (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg + final def ^(that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_& (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + 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 = + 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 = + 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) - } + 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 = + def do_unary_~(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = throwException(s"Not is illegal on $this") - 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) + 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 + final def !=(that: FixedPoint): Bool = macro SourceInfoTransform.thatArg /** Dynamic not equals operator * @@ -1501,7 +1657,7 @@ package experimental { * @return a hardware [[Bool]] asserted if this $coll is not equal to `that` * @group Comparison */ - final def =/= (that: FixedPoint): Bool = macro SourceInfoTransform.thatArg + final def =/=(that: FixedPoint): Bool = macro SourceInfoTransform.thatArg /** Dynamic equals operator * @@ -1509,14 +1665,19 @@ package experimental { * @return a hardware [[Bool]] asserted if this $coll is equal to `that` * @group Comparison */ - final def === (that: FixedPoint): Bool = macro SourceInfoTransform.thatArg + final def ===(that: FixedPoint): Bool = macro SourceInfoTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_!= (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, NotEqualOp, that) + 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) + 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_===(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. @@ -1524,59 +1685,88 @@ package experimental { Mux(this < 0.F(0.BP), 0.F(0.BP) - this, this) } - override def do_<< (that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + 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 = + 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 = + 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 = + 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 = + 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 = { + 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") + throwException( + s"cannot call $this.asFixedPoint(binaryPoint=$binaryPoint), you must specify a known binaryPoint" + ) } } - def do_asInterval(binaryPoint: BinaryPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Interval = { - throwException(s"cannot call $this.asInterval(binaryPoint=$binaryPoint), you must specify a range") - } - - override def do_asInterval(range: IntervalRange = IntervalRange.Unknown) - (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Interval = { - (range.lower, range.upper, range.binaryPoint) match { - case (lx: firrtlconstraint.IsKnown, ux: firrtlconstraint.IsKnown, KnownBinaryPoint(bp)) => - // No mechanism to pass open/close to firrtl so need to handle directly - val l = lx match { - case firrtlir.Open(x) => x + BigDecimal(1) / BigDecimal(BigInt(1) << bp) - case firrtlir.Closed(x) => x - } - val u = ux match { - case firrtlir.Open(x) => x - BigDecimal(1) / BigDecimal(BigInt(1) << bp) - case firrtlir.Closed(x) => x - } - val minBI = (l * BigDecimal(BigInt(1) << bp)).setScale(0, BigDecimal.RoundingMode.FLOOR).toBigIntExact.get - val maxBI = (u * BigDecimal(BigInt(1) << bp)).setScale(0, BigDecimal.RoundingMode.FLOOR).toBigIntExact.get - pushOp(DefPrim(sourceInfo, Interval(range), AsIntervalOp, ref, ILit(minBI), ILit(maxBI), ILit(bp))) - case _ => - throwException( - s"cannot call $this.asInterval($range), you must specify a known binaryPoint and range") + def do_asInterval( + binaryPoint: BinaryPoint + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Interval = { + throwException(s"cannot call $this.asInterval(binaryPoint=$binaryPoint), you must specify a range") + } + + override def do_asInterval( + range: IntervalRange = IntervalRange.Unknown + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Interval = { + (range.lower, range.upper, range.binaryPoint) match { + case (lx: firrtlconstraint.IsKnown, ux: firrtlconstraint.IsKnown, KnownBinaryPoint(bp)) => + // No mechanism to pass open/close to firrtl so need to handle directly + val l = lx match { + case firrtlir.Open(x) => x + BigDecimal(1) / BigDecimal(BigInt(1) << bp) + case firrtlir.Closed(x) => x + } + val u = ux match { + case firrtlir.Open(x) => x - BigDecimal(1) / BigDecimal(BigInt(1) << bp) + case firrtlir.Closed(x) => x + } + val minBI = (l * BigDecimal(BigInt(1) << bp)).setScale(0, BigDecimal.RoundingMode.FLOOR).toBigIntExact.get + val maxBI = (u * BigDecimal(BigInt(1) << bp)).setScale(0, BigDecimal.RoundingMode.FLOOR).toBigIntExact.get + pushOp(DefPrim(sourceInfo, Interval(range), AsIntervalOp, ref, ILit(minBI), ILit(maxBI), ILit(bp))) + case _ => + throwException(s"cannot call $this.asInterval($range), you must specify a known binaryPoint and range") + } } - } - private[chisel3] override def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) { + private[chisel3] 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) @@ -1610,36 +1800,43 @@ package experimental { 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) { + if (width == -1) { apply(value, Width(), BinaryPoint(binaryPoint)) - } - else { + } 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 */ def fromDouble(value: Double, width: Width, binaryPoint: BinaryPoint): FixedPoint = { fromBigInt( - toBigInt(value, binaryPoint.get), width = width, binaryPoint = binaryPoint + toBigInt(value, binaryPoint.get), + width = width, + binaryPoint = binaryPoint ) } + /** Create an FixedPoint literal with inferred width from BigDecimal. * Use PrivateObject to force users to specify width and binaryPoint by name */ def fromBigDecimal(value: BigDecimal, width: Width, binaryPoint: BinaryPoint): FixedPoint = { fromBigInt( - toBigInt(value, binaryPoint.get), width = width, binaryPoint = binaryPoint + toBigInt(value, binaryPoint.get), + width = width, + binaryPoint = binaryPoint ) } @@ -1651,8 +1848,6 @@ package experimental { lit.bindLitArg(newLiteral) } - - object Implicits { implicit class fromDoubleToLiteral(double: Double) { @@ -1695,12 +1890,14 @@ package experimental { * @param range a range specifies min, max and binary point */ sealed class Interval private[chisel3] (val range: chisel3.internal.firrtl.IntervalRange) - extends Bits(range.getWidth) with Num[Interval] with HasBinaryPoint { + extends Bits(range.getWidth) + with Num[Interval] + with HasBinaryPoint { override def toString: String = { litOption match { case Some(value) => s"Interval$width($value)" - case _ => stringAccessor(s"Interval$width") + case _ => stringAccessor(s"Interval$width") } } @@ -1714,27 +1911,27 @@ package experimental { val int = """([+\-]?[0-9]\d*)""".r def dec2string(v: BigDecimal): String = v.toString match { case zdec1(x, y, z) => x + y - case zdec2(x, y) => x - case other => other + case zdec2(x, y) => x + case other => other } val lowerString = range.lower match { case firrtlir.Open(l) => s"(${dec2string(l)}, " case firrtlir.Closed(l) => s"[${dec2string(l)}, " case firrtlir.UnknownBound => s"[?, " - case _ => s"[?, " + case _ => s"[?, " } val upperString = range.upper match { case firrtlir.Open(u) => s"${dec2string(u)})" case firrtlir.Closed(u) => s"${dec2string(u)}]" case firrtlir.UnknownBound => s"?]" - case _ => s"?]" + case _ => s"?]" } val bounds = lowerString + upperString val pointString = range.binaryPoint match { - case KnownBinaryPoint(i) => "." + i.toString - case _ => "" + case KnownBinaryPoint(i) => "." + i.toString + case _ => "" } "Interval" + bounds + pointString } @@ -1746,19 +1943,25 @@ package experimental { override def connect(that: Data)(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions): Unit = { that match { - case _: Interval|DontCare => super.connect(that) - case _ => this badConnect that + case _: Interval | DontCare => super.connect(that) + case _ => this.badConnect(that) } } final def unary_- : Interval = macro SourceInfoTransform.noArg - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) final def unary_-(dummy: Int*): Interval = macro SourceInfoTransform.noArgDummy final def unary_-% : Interval = macro SourceInfoTransform.noArg - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) final def unary_-%(dummy: Int*): Interval = macro SourceInfoTransform.noArgDummy /** @group SourceInfoTransformMacro */ @@ -1772,6 +1975,7 @@ package experimental { /** add (default - growing) operator */ override def do_+(that: Interval)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Interval = this +& that + /** subtract (default - growing) operator */ override def do_-(that: Interval)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Interval = this -& that @@ -1785,10 +1989,13 @@ package experimental { /** add (width +1) operator */ final def +&(that: Interval): Interval = macro SourceInfoTransform.thatArg + /** add (no growth) operator */ final def +%(that: Interval): Interval = macro SourceInfoTransform.thatArg + /** subtract (width +1) operator */ final def -&(that: Interval): Interval = macro SourceInfoTransform.thatArg + /** subtract (no growth) operator */ final def -%(that: Interval): Interval = macro SourceInfoTransform.thatArg @@ -1859,21 +2066,28 @@ package experimental { } /** Returns this wire bitwise-inverted. */ - def do_unary_~ (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Interval = + def do_unary_~(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Interval = throwException(s"Not is illegal on $this") - override def do_< (that: Interval)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, LessOp, that) - override def do_> (that: Interval)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, GreaterOp, that) - override def do_<= (that: Interval)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, LessEqOp, that) - override def do_>= (that: Interval)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, GreaterEqOp, that) - - final def != (that: Interval): Bool = macro SourceInfoTransform.thatArg - final def =/= (that: Interval): Bool = macro SourceInfoTransform.thatArg - final def === (that: Interval): Bool = macro SourceInfoTransform.thatArg - - def do_!= (that: Interval)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, NotEqualOp, that) - def do_=/= (that: Interval)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, NotEqualOp, that) - def do_=== (that: Interval)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, EqualOp, that) + override def do_<(that: Interval)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = + compop(sourceInfo, LessOp, that) + override def do_>(that: Interval)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = + compop(sourceInfo, GreaterOp, that) + override def do_<=(that: Interval)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = + compop(sourceInfo, LessEqOp, that) + override def do_>=(that: Interval)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = + compop(sourceInfo, GreaterEqOp, that) + + final def !=(that: Interval): Bool = macro SourceInfoTransform.thatArg + final def =/=(that: Interval): Bool = macro SourceInfoTransform.thatArg + final def ===(that: Interval): Bool = macro SourceInfoTransform.thatArg + + def do_!=(that: Interval)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = + compop(sourceInfo, NotEqualOp, that) + def do_=/=(that: Interval)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = + compop(sourceInfo, NotEqualOp, that) + def do_===(that: Interval)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = + compop(sourceInfo, EqualOp, that) // final def abs(): UInt = macro SourceInfoTransform.noArgDummy @@ -1881,24 +2095,24 @@ package experimental { Mux(this < Interval.Zero, (Interval.Zero - this), this) } - override def do_<< (that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Interval = + override def do_<<(that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Interval = binop(sourceInfo, Interval(this.range << that), ShiftLeftOp, that) - override def do_<< (that: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Interval = + override def do_<<(that: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Interval = do_<<(that.toInt) - override def do_<< (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Interval = { + override def do_<<(that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Interval = { binop(sourceInfo, Interval(this.range << that), DynamicShiftLeftOp, that) } - override def do_>> (that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Interval = { + override def do_>>(that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Interval = { binop(sourceInfo, Interval(this.range >> that), ShiftRightOp, that) } - override def do_>> (that: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Interval = + override def do_>>(that: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Interval = do_>>(that.toInt) - override def do_>> (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Interval = { + override def do_>>(that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Interval = { binop(sourceInfo, Interval(this.range >> that), DynamicShiftRightOp, that) } @@ -1965,13 +2179,12 @@ package experimental { final def squeeze(that: IntervalRange): Interval = macro SourceInfoTransform.thatArg def do_squeeze(that: IntervalRange)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Interval = { val intervalLitOpt = Interval.getSmallestLegalLit(that) - val intervalLit = intervalLitOpt.getOrElse( + val intervalLit = intervalLitOpt.getOrElse( throwException(s"$this.squeeze($that) requires an Interval range with known lower and upper bounds") ) do_squeeze(intervalLit) } - /** * Wrap the value of this [[Interval]] into the range of a different Interval with a presumably smaller range. * Ignores binary point of argument @@ -2104,14 +2317,20 @@ package experimental { pushOp(DefPrim(sourceInfo, SInt(this.width), AsSIntOp, ref)) } - override def do_asFixedPoint(binaryPoint: BinaryPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = { + 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") + s"cannot call $this.asFixedPoint(binaryPoint=$binaryPoint), you must specify a known binaryPoint" + ) } } @@ -2132,8 +2351,12 @@ package experimental { throwException("fromBits INVALID for intervals") } - private[chisel3] override def connectFromBits(that: Bits) - (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) { + private[chisel3] override def connectFromBits( + that: Bits + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ) { this := that.asInterval(this.range) } } @@ -2146,6 +2369,7 @@ package experimental { * IMPORTANT: The API provided here is experimental and may change in the future. */ object Interval extends NumObject { + /** Create an Interval type with inferred width and binary point. */ def apply(): Interval = Interval(range"[?,?]") @@ -2153,7 +2377,7 @@ package experimental { def apply(binaryPoint: BinaryPoint): Interval = { val binaryPointString = binaryPoint match { case KnownBinaryPoint(value) => s"$value" - case _ => s"" + case _ => s"" } Interval(range"[?,?].$binaryPointString") } @@ -2201,27 +2425,39 @@ package experimental { /** Create an Interval literal with inferred width from Double. * Use PrivateObject to force users to specify width and binaryPoint by name */ - def fromDouble(value: Double, dummy: PrivateType = PrivateObject, - width: Width, binaryPoint: BinaryPoint): Interval = { + def fromDouble( + value: Double, + dummy: PrivateType = PrivateObject, + width: Width, + binaryPoint: BinaryPoint + ): Interval = { fromBigInt( - toBigInt(value, binaryPoint), width = width, binaryPoint = binaryPoint + toBigInt(value, binaryPoint), + width = width, + binaryPoint = binaryPoint ) } /** Create an Interval literal with inferred width from Double. * Use PrivateObject to force users to specify width and binaryPoint by name */ - def fromBigDecimal(value: Double, dummy: PrivateType = PrivateObject, - width: Width, binaryPoint: BinaryPoint): Interval = { + def fromBigDecimal( + value: Double, + dummy: PrivateType = PrivateObject, + width: Width, + binaryPoint: BinaryPoint + ): Interval = { fromBigInt( - toBigInt(value, binaryPoint), width = width, binaryPoint = binaryPoint + toBigInt(value, binaryPoint), + width = width, + binaryPoint = binaryPoint ) } protected[chisel3] def Lit(value: BigInt, width: Width, binaryPoint: BinaryPoint): Interval = { width match { case KnownWidth(w) => - if(value >= 0 && value.bitLength >= w || value < 0 && value.bitLength > w) { + if (value >= 0 && value.bitLength >= w || value < 0 && value.bitLength > w) { throw new ChiselException( s"Error literal interval value $value is too many bits for specified width $w" ) @@ -2243,7 +2479,7 @@ package experimental { case (firrtlir.Open(l), firrtlir.Closed(u)) => l < bigDecimal && bigDecimal <= u case (firrtlir.Open(l), firrtlir.Open(u)) => l < bigDecimal && bigDecimal < u } - if(! inRange) { + if (!inRange) { throw new ChiselException( s"Error literal interval value $bigDecimal is not contained in specified range $range" ) @@ -2338,9 +2574,7 @@ package experimental { } implicit class fromDoubleToLiteralInterval(double: Double) - extends fromBigDecimalToLiteralInterval(BigDecimal(double)) + extends fromBigDecimalToLiteralInterval(BigDecimal(double)) } } } - - diff --git a/core/src/main/scala/chisel3/BlackBox.scala b/core/src/main/scala/chisel3/BlackBox.scala index ec5de0cd..89c4ccd3 100644 --- a/core/src/main/scala/chisel3/BlackBox.scala +++ b/core/src/main/scala/chisel3/BlackBox.scala @@ -23,6 +23,7 @@ package experimental { 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 @@ -85,7 +86,7 @@ package experimental { closeUnboundIds(names) - val firrtlPorts = getModulePorts map {port => Port(port, port.specifiedDirection)} + val firrtlPorts = getModulePorts.map { port => Port(port, port.specifiedDirection) } val component = DefBlackBox(this, name, firrtlPorts, SpecifiedDirection.Unspecified, params) _component = Some(component) _component @@ -137,19 +138,24 @@ package experimental { * @note The parameters API is experimental and may change */ @nowarn("msg=class Port") // delete when Port becomes private -abstract class BlackBox(val params: Map[String, Param] = Map.empty[String, Param])(implicit compileOptions: CompileOptions) extends BaseBlackBox { +abstract class BlackBox( + val params: Map[String, Param] = Map.empty[String, Param] +)( + implicit compileOptions: CompileOptions) + extends BaseBlackBox { // Find a Record port named "io" for purposes of stripping the prefix private[chisel3] lazy val _io: Record = - this.findPort("io") - .collect { case r: Record => r } // Must be a Record - .getOrElse(null) // null handling occurs in generateComponent + this + .findPort("io") + .collect { case r: Record => r } // Must be a Record + .getOrElse(null) // null handling occurs in generateComponent // Allow access to bindings from the compatibility package protected def _compatIoPortBound() = portsContains(_io) private[chisel3] override def generateComponent(): Option[Component] = { - _compatAutoWrapPorts() // pre-IO(...) compatibility hack + _compatAutoWrapPorts() // pre-IO(...) compatibility hack // Restrict IO to just io, clock, and reset require(_io != null, "BlackBox must have a port named 'io' of type Record!") @@ -159,7 +165,7 @@ abstract class BlackBox(val params: Map[String, Param] = Map.empty[String, Param require(!_closed, "Can't generate module more than once") _closed = true - val namedPorts = _io.elements.toSeq.reverse // ListMaps are stored in reverse order + val namedPorts = _io.elements.toSeq.reverse // ListMaps are stored in reverse order // 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 @@ -179,7 +185,7 @@ abstract class BlackBox(val params: Map[String, Param] = Map.empty[String, Param id._onModuleClose } - val firrtlPorts = namedPorts map {namedPort => Port(namedPort._2, namedPort._2.specifiedDirection)} + val firrtlPorts = namedPorts.map { namedPort => Port(namedPort._2, namedPort._2.specifiedDirection) } val component = DefBlackBox(this, name, firrtlPorts, _io.specifiedDirection, params) _component = Some(component) _component diff --git a/core/src/main/scala/chisel3/BoolFactory.scala b/core/src/main/scala/chisel3/BoolFactory.scala index 787f1e5e..1d96659f 100644 --- a/core/src/main/scala/chisel3/BoolFactory.scala +++ b/core/src/main/scala/chisel3/BoolFactory.scala @@ -4,14 +4,14 @@ package chisel3 import chisel3.internal.firrtl.{ULit, Width} - 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)) diff --git a/core/src/main/scala/chisel3/Clock.scala b/core/src/main/scala/chisel3/Clock.scala index e4be6558..68174d7c 100644 --- a/core/src/main/scala/chisel3/Clock.scala +++ b/core/src/main/scala/chisel3/Clock.scala @@ -21,10 +21,11 @@ sealed class Clock(private[chisel3] val width: Width = Width(1)) extends Element private[chisel3] def typeEquivalent(that: Data): Boolean = this.getClass == that.getClass - override def connect(that: Data)(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions): Unit = that match { - case _: Clock => super.connect(that)(sourceInfo, connectCompileOptions) - case _ => super.badConnect(that)(sourceInfo) - } + override def connect(that: Data)(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions): Unit = + that match { + case _: Clock => super.connect(that)(sourceInfo, connectCompileOptions) + case _ => super.badConnect(that)(sourceInfo) + } override def litOption: Option[BigInt] = None @@ -34,14 +35,23 @@ sealed class Clock(private[chisel3] val width: Width = Width(1)) extends Element /** Returns the contents of the clock wire as a [[Bool]]. */ final def asBool: Bool = macro SourceInfoTransform.noArg - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) final def asBool(dummy: Int*): Bool = macro SourceInfoTransform.noArgDummy def do_asBool(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = this.asUInt.asBool - override def do_asUInt(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions): UInt = pushOp(DefPrim(sourceInfo, UInt(this.width), AsUIntOp, ref)) - private[chisel3] override def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo, - compileOptions: CompileOptions): Unit = { + override def do_asUInt(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions): UInt = pushOp( + DefPrim(sourceInfo, UInt(this.width), AsUIntOp, ref) + ) + private[chisel3] override def connectFromBits( + that: Bits + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Unit = { this := that.asBool.asClock } } diff --git a/core/src/main/scala/chisel3/CompileOptions.scala b/core/src/main/scala/chisel3/CompileOptions.scala index 3dcc25a8..db773d6e 100644 --- a/core/src/main/scala/chisel3/CompileOptions.scala +++ b/core/src/main/scala/chisel3/CompileOptions.scala @@ -36,7 +36,7 @@ object CompileOptions { } object ExplicitCompileOptions { - case class CompileOptionsClass ( + 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. @@ -52,12 +52,12 @@ object ExplicitCompileOptions { // Require an explicit DontCare assignment to generate a firrtl DefInvalid val explicitInvalidate: Boolean, // Should the reset type of Module be a Bool or a Reset - val inferModuleReset: Boolean - ) extends CompileOptions + val inferModuleReset: Boolean) + extends CompileOptions // Collection of "not strict" connection compile options. // These provide compatibility with existing code. - implicit val NotStrict = new CompileOptionsClass ( + implicit val NotStrict = new CompileOptionsClass( connectFieldsMustMatch = false, declaredTypeMustBeUnbound = false, dontTryConnectionsSwapped = false, @@ -68,13 +68,13 @@ object ExplicitCompileOptions { ) // Collection of "strict" connection compile options, preferred for new code. - implicit val Strict = new CompileOptionsClass ( + implicit val Strict = new CompileOptionsClass( connectFieldsMustMatch = true, declaredTypeMustBeUnbound = true, dontTryConnectionsSwapped = true, dontAssumeDirectionality = true, checkSynthesizable = true, explicitInvalidate = true, - inferModuleReset = true + inferModuleReset = true ) } diff --git a/core/src/main/scala/chisel3/Data.scala b/core/src/main/scala/chisel3/Data.scala index 2bca5f98..9e9f5dbb 100644 --- a/core/src/main/scala/chisel3/Data.scala +++ b/core/src/main/scala/chisel3/Data.scala @@ -18,24 +18,28 @@ import scala.util.Try */ 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 + case Flip => Unspecified + case Output => Input + case Input => Output } /** Returns the effective SpecifiedDirection of this node given the parent's effective SpecifiedDirection @@ -43,13 +47,18 @@ object SpecifiedDirection { */ def fromParent(parentDirection: SpecifiedDirection, thisDirection: SpecifiedDirection): SpecifiedDirection = (parentDirection, thisDirection) match { - case (SpecifiedDirection.Output, _) => SpecifiedDirection.Output - case (SpecifiedDirection.Input, _) => SpecifiedDirection.Input + case (SpecifiedDirection.Output, _) => SpecifiedDirection.Output + case (SpecifiedDirection.Input, _) => SpecifiedDirection.Input case (SpecifiedDirection.Unspecified, thisDirection) => thisDirection - case (SpecifiedDirection.Flip, thisDirection) => SpecifiedDirection.flip(thisDirection) + case (SpecifiedDirection.Flip, thisDirection) => SpecifiedDirection.flip(thisDirection) } - private[chisel3] def specifiedDirection[T<:Data](source: T)(dir: SpecifiedDirection)(implicit compileOptions: CompileOptions): T = { + private[chisel3] def specifiedDirection[T <: Data]( + source: T + )(dir: SpecifiedDirection + )( + implicit compileOptions: CompileOptions + ): T = { if (compileOptions.checkSynthesizable) { requireIsChiselType(source) } @@ -67,6 +76,7 @@ object SpecifiedDirection { sealed abstract class ActualDirection object ActualDirection { + /** The object does not exist / is empty and hence has no direction */ case object Empty extends ActualDirection @@ -74,9 +84,11 @@ object 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 @@ -89,19 +101,21 @@ object 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 + 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 + 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 + 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) @@ -109,14 +123,20 @@ object ActualDirection { 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))) { + } 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") + case SpecifiedDirection.Flip => Some(ActualDirection.Bidirectional(ActualDirection.Flipped)) + case _ => throw new RuntimeException("Unexpected forced Input / Output") } } else { None @@ -130,7 +150,7 @@ package experimental { /** Experimental hardware construction reflection API */ object DataMirror { - def widthOf(target: Data): Width = target.width + 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") @@ -151,7 +171,7 @@ package experimental { * @param x First Chisel type * @param y Second Chisel type * @return true if the two Chisel types are equal. - **/ + */ def checkTypeEquivalence(x: Data, y: Data): Boolean = x.typeEquivalent(y) /** Returns the ports of a module @@ -210,11 +230,12 @@ package experimental { 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) } + 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 + modulePorts(target).flatMap { + case (name, data) => + getPortNames(name, data).toList } } @@ -222,7 +243,7 @@ package experimental { object internal { 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 = { + def chiselTypeClone[T <: Data](target: Data): T = { target.cloneTypeFull.asInstanceOf[T] } } @@ -236,48 +257,59 @@ package experimental { * - Otherwise: fail */ private[chisel3] object cloneSupertype { - def apply[T <: Data](elts: Seq[T], createdType: String)(implicit sourceInfo: SourceInfo, - compileOptions: CompileOptions): T = { + 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() + 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: Interval, elt2: Interval) => - val range = if(elt1.range.width == elt1.range.width.max(elt2.range.width)) elt1.range else elt2.range - Interval(range) - case (elt1, elt2) => - throw new AssertionError( - s"can't create $createdType with heterogeneous types ${elt1.getClass} and ${elt2.getClass}") - }).asInstanceOf[T] } + case (elt1: Interval, elt2: Interval) => + val range = if (elt1.range.width == elt1.range.width.max(elt2.range.width)) elt1.range else elt2.range + Interval(range) + case (elt1, elt2) => + throw new AssertionError( + s"can't create $createdType with heterogeneous types ${elt1.getClass} and ${elt2.getClass}" + ) + }).asInstanceOf[T] + } model.cloneTypeFull - } - else { + } 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}") + 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 } @@ -288,14 +320,16 @@ private[chisel3] object cloneSupertype { private[chisel3] object getRecursiveFields { def apply(data: Data, path: String): Seq[(Data, String)] = data match { case data: Record => - data.elements.map { case (fieldName, fieldData) => - getRecursiveFields(fieldData, s"$path.$fieldName") + data.elements.map { + case (fieldName, fieldData) => + getRecursiveFields(fieldData, s"$path.$fieldName") }.fold(Seq(data -> path)) { _ ++ _ } case data: Vec[_] => - data.getElements.zipWithIndex.map { case (fieldData, fieldIndex) => - getRecursiveFields(fieldData, path = s"$path($fieldIndex)") + data.getElements.zipWithIndex.map { + case (fieldData, fieldIndex) => + getRecursiveFields(fieldData, path = s"$path($fieldIndex)") }.fold(Seq(data -> path)) { _ ++ _ } @@ -305,13 +339,15 @@ private[chisel3] object getRecursiveFields { def lazily(data: Data, path: String): Seq[(Data, String)] = data match { case data: Record => LazyList(data -> path) ++ - data.elements.view.flatMap { case (fieldName, fieldData) => - getRecursiveFields(fieldData, s"$path.$fieldName") + data.elements.view.flatMap { + case (fieldName, fieldData) => + getRecursiveFields(fieldData, s"$path.$fieldName") } case data: Vec[_] => LazyList(data -> path) ++ - data.getElements.view.zipWithIndex.flatMap { case (fieldData, fieldIndex) => - getRecursiveFields(fieldData, path = s"$path($fieldIndex)") + data.getElements.view.zipWithIndex.flatMap { + case (fieldData, fieldIndex) => + getRecursiveFields(fieldData, path = s"$path($fieldIndex)") } case data: Element => LazyList(data -> path) } @@ -322,21 +358,29 @@ private[chisel3] object getRecursiveFields { private[chisel3] object getMatchedFields { def apply(x: Data, y: Data): Seq[(Data, Data)] = (x, y) match { case (x: Element, y: Element) => - require(x typeEquivalent y) + 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)) { - _ ++ _ - } + (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)) { + _ ++ _ + } case (x: Vec[_], y: Vec[_]) => - (x.getElements zip y.getElements).map { case (xElt, yElt) => - getMatchedFields(xElt, yElt) - }.fold(Seq(x -> y)) { - _ ++ _ - } + (x.getElements + .zip(y.getElements)) + .map { + case (xElt, yElt) => + getMatchedFields(xElt, yElt) + } + .fold(Seq(x -> y)) { + _ ++ _ + } } } @@ -350,25 +394,25 @@ object chiselTypeOf { } /** -* 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 -*/ + * 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 = { + def apply[T <: Data](source: T)(implicit compileOptions: CompileOptions): T = { SpecifiedDirection.specifiedDirection(source)(SpecifiedDirection.Input) } } object Output { - def apply[T<:Data](source: T)(implicit compileOptions: CompileOptions): T = { + def apply[T <: Data](source: T)(implicit compileOptions: CompileOptions): T = { SpecifiedDirection.specifiedDirection(source)(SpecifiedDirection.Output) } } object Flipped { - def apply[T<:Data](source: T)(implicit compileOptions: CompileOptions): T = { + def apply[T <: Data](source: T)(implicit compileOptions: CompileOptions): T = { SpecifiedDirection.specifiedDirection(source)(SpecifiedDirection.flip(source.specifiedDirection)) } } @@ -386,8 +430,8 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc { @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: Aggregate => elt.getElements.toIndexedSeq.flatMap { _.flatten } + case elt: Element => IndexedSeq(elt) case elt => throwException(s"Cannot flatten type ${elt.getClass}") } } @@ -396,13 +440,13 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc { topBindingOpt match { // Ports are special in that the autoSeed will keep the first name, not the last name case Some(PortBinding(m)) if hasAutoSeed && Builder.currentModule.contains(m) => this - case _ => super.autoSeed(name) + case _ => super.autoSeed(name) } } // 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 var _specifiedDirection: SpecifiedDirection = SpecifiedDirection.Unspecified private[chisel3] def specifiedDirection: SpecifiedDirection = _specifiedDirection private[chisel3] def specifiedDirection_=(direction: SpecifiedDirection) = { if (_specifiedDirection != SpecifiedDirection.Unspecified) { @@ -422,8 +466,8 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc { private[chisel3] def _assignCompatibilityExplicitDirection: Unit = { (this, _specifiedDirection) match { case (_: Analog, _) => // nothing to do - case (_, SpecifiedDirection.Unspecified) => _specifiedDirection = SpecifiedDirection.Output - case (_, SpecifiedDirection.Flip) => _specifiedDirection = SpecifiedDirection.Input + case (_, SpecifiedDirection.Unspecified) => _specifiedDirection = SpecifiedDirection.Output + case (_, SpecifiedDirection.Flip) => _specifiedDirection = SpecifiedDirection.Input case (_, SpecifiedDirection.Input | SpecifiedDirection.Output) => // nothing to do } } @@ -503,16 +547,16 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc { private[chisel3] def _bindingToString(topBindingOpt: TopBinding): String = topBindingOpt match { - case OpBinding(_, _) => "OpResult" - case MemoryPortBinding(_, _) => "MemPort" - case PortBinding(_) => "IO" - case RegBinding(_, _) => "Reg" - case WireBinding(_, _) => "Wire" - case DontCareBinding() => "(DontCare)" + case OpBinding(_, _) => "OpResult" + case MemoryPortBinding(_, _) => "MemPort" + case PortBinding(_) => "IO" + case RegBinding(_, _) => "Reg" + case WireBinding(_, _) => "Wire" + case DontCareBinding() => "(DontCare)" case ElementLitBinding(litArg) => "(unhandled literal)" - case BundleLitBinding(litMap) => "(unhandled bundle literal)" - case VecLitBinding(litMap) => "(unhandled vec literal)" - case _ => "" + case BundleLitBinding(litMap) => "(unhandled bundle literal)" + case VecLitBinding(litMap) => "(unhandled vec literal)" + case _ => "" } private[chisel3] def earlyName: String = Arg.earlyLocalName(this) @@ -526,13 +570,18 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc { private[chisel3] 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 = { + private[chisel3] def connect( + that: Data + )( + implicit sourceInfo: SourceInfo, + connectCompileOptions: CompileOptions + ): Unit = { 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 + case _ => // fine } try { MonoConnect.connect(sourceInfo, connectCompileOptions, this, that, Builder.referenceUserModule) @@ -543,10 +592,15 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc { ) } } else { - this legacyConnect that + this.legacyConnect(that) } } - private[chisel3] def bulkConnect(that: Data)(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions): Unit = { + private[chisel3] def bulkConnect( + that: Data + )( + implicit sourceInfo: SourceInfo, + connectCompileOptions: CompileOptions + ): Unit = { if (connectCompileOptions.checkSynthesizable) { requireIsHardware(this, s"data to be bulk-connected") requireIsHardware(that, s"data to be bulk-connected") @@ -554,7 +608,7 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc { case (_: ReadOnlyBinding, _: ReadOnlyBinding) => throwException(s"Both $this and $that are read-only") // DontCare cannot be a sink (LHS) case (_: DontCareBinding, _) => throw BiConnect.DontCareCantBeSink - case _ => // fine + case _ => // fine } try { BiConnect.connect(sourceInfo, connectCompileOptions, this, that, Builder.referenceUserModule) @@ -565,7 +619,7 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc { ) } } else { - this legacyConnect that + this.legacyConnect(that) } } @@ -578,7 +632,8 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc { val mod = topBindingOpt.flatMap(_.location) topBindingOpt match { case Some(tb: TopBinding) if (mod == Builder.currentModule) => - case Some(pb: PortBinding) if (mod.flatMap(Builder.retrieveParent(_,Builder.currentModule.get)) == Builder.currentModule) => + case Some(pb: PortBinding) + if (mod.flatMap(Builder.retrieveParent(_, Builder.currentModule.get)) == Builder.currentModule) => case Some(_: UnconstrainedBinding) => case _ => throwException(s"operand '$this' is not visible from the current module") @@ -593,7 +648,8 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc { requireIsHardware(this) requireVisible() topBindingOpt match { - case Some(binding: ReadOnlyBinding) => throwException(s"internal error: attempted to generate LHS ref to ReadOnlyBinding $binding") + case Some(binding: ReadOnlyBinding) => + throwException(s"internal error: attempted to generate LHS ref to ReadOnlyBinding $binding") case Some(binding: TopBinding) => Node(this) case opt => throwException(s"internal error: unknown binding $opt in generating LHS ref") } @@ -622,12 +678,12 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc { case Some(BundleLitBinding(litMap)) => litMap.get(this) match { case Some(litArg) => litArg - case _ => materializeWire() // FIXME FIRRTL doesn't have Bundle literal expressions + case _ => materializeWire() // FIXME FIRRTL doesn't have Bundle literal expressions } case Some(VecLitBinding(litMap)) => litMap.get(this) match { case Some(litArg) => litArg - case _ => materializeWire() // FIXME FIRRTL doesn't have Vec literal expressions + case _ => materializeWire() // FIXME FIRRTL doesn't have Vec literal expressions } case Some(DontCareBinding()) => materializeWire() // FIXME FIRRTL doesn't have a DontCare expression so materialize a Wire @@ -643,15 +699,14 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc { } } - // Recursively set the parent of the start Data and any children (eg. in an Aggregate) private[chisel3] def setAllParents(parent: Option[BaseModule]): Unit = { def rec(data: Data): Unit = { data._parent = parent data match { - case _: Element => - case agg: Aggregate => - agg.getElements.foreach(rec) + case _: Element => + case agg: Aggregate => + agg.getElements.foreach(rec) } } rec(this) @@ -675,7 +730,7 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc { * Directionality data is still preserved. */ private[chisel3] def cloneTypeFull: this.type = { - val clone = this.cloneType.asInstanceOf[this.type] // get a fresh object, without bindings + 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 @@ -688,7 +743,7 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc { * @param that the $coll to connect to * @group Connect */ - final def := (that: => Data)(implicit sourceInfo: SourceInfo, connectionCompileOptions: CompileOptions): Unit = { + final def :=(that: => Data)(implicit sourceInfo: SourceInfo, connectionCompileOptions: CompileOptions): Unit = { prefix(this) { this.connect(that)(sourceInfo, connectionCompileOptions) } @@ -701,7 +756,7 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc { * @param that the $coll to connect to * @group Connect */ - final def <> (that: => Data)(implicit sourceInfo: SourceInfo, connectionCompileOptions: CompileOptions): Unit = { + final def <>(that: => Data)(implicit sourceInfo: SourceInfo, connectionCompileOptions: CompileOptions): Unit = { prefix(this) { this.bulkConnect(that)(sourceInfo, connectionCompileOptions) } @@ -709,32 +764,42 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc { def isLit: Boolean = litOption.isDefined - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) def isLit(dummy: Int*): Boolean = isLit - /** - * 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. - */ + * 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] - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) def litOption(dummy: Int*): Option[BigInt] = litOption /** - * Returns the literal value if this is a literal that is representable as bits, otherwise crashes. - */ + * Returns the literal value if this is a literal that is representable as bits, otherwise crashes. + */ def litValue: BigInt = litOption.get - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) def litValue(dummy: Int*): BigInt = litValue /** 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 @@ -757,8 +822,12 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc { /** Assigns this node from Bits type. Internal implementation for asTypeOf. */ - private[chisel3] def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo, - compileOptions: CompileOptions): Unit + private[chisel3] def connectFromBits( + that: Bits + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Unit /** Reinterpret cast to UInt. * @@ -769,7 +838,10 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc { */ final def asUInt: UInt = macro SourceInfoTransform.noArg - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) final def asUInt(dummy: Int*): UInt = macro SourceInfoTransform.noArgDummy /** @group SourceInfoTransformMacro */ @@ -780,6 +852,7 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc { } trait WireFactory { + /** Construct a [[Wire]] from a type template * @param t The template from which to construct this wire */ @@ -819,7 +892,6 @@ trait WireFactory { * // Width of w4.unknown is inferred * // Width of w4.known is set to 8 * }}} - * */ object Wire extends WireFactory @@ -884,7 +956,13 @@ object Wire extends WireFactory */ object WireDefault { - private def applyImpl[T <: Data](t: T, init: Data)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T = { + private def applyImpl[T <: Data]( + t: T, + init: Data + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): T = { implicit val noSourceInfo = UnlocatableSourceInfo val x = Wire(t) requireIsHardware(init, "wire initializer") @@ -897,7 +975,13 @@ object WireDefault { * @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 = { + def apply[T <: Data]( + t: T, + init: DontCare.type + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): T = { applyImpl(t, init) } @@ -941,7 +1025,12 @@ final case object DontCare extends Element { def toPrintable: Printable = PString("DONTCARE") - private[chisel3] def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Unit = { + private[chisel3] def connectFromBits( + that: Bits + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Unit = { Builder.error("connectFromBits: DontCare cannot be a connection sink (LHS)") } diff --git a/core/src/main/scala/chisel3/Element.scala b/core/src/main/scala/chisel3/Element.scala index bc006922..401f2bdf 100644 --- a/core/src/main/scala/chisel3/Element.scala +++ b/core/src/main/scala/chisel3/Element.scala @@ -14,8 +14,8 @@ import chisel3.internal._ */ abstract class Element extends Data { private[chisel3] final def allElements: Seq[Element] = Seq(this) - def widthKnown: Boolean = width.known - def name: String = getRef.name + def widthKnown: Boolean = width.known + def name: String = getRef.name private[chisel3] override def bind(target: Binding, parentDirection: SpecifiedDirection): Unit = { _parent.foreach(_.addId(this)) @@ -26,27 +26,30 @@ abstract class Element extends Data { private[chisel3] 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 Some(VecLitBinding(litMap)) => litMap.get(this) match { - case Some(litArg) => Some(ElementLitBinding(litArg)) - case _ => Some(DontCareBinding()) - } - case Some(b @ AggregateViewBinding(viewMap, _)) => viewMap.get(this) match { - case Some(elt) => Some(ViewBinding(elt)) - case _ => throwException(s"Internal Error! $this missing from topBinding $b") - } + case Some(BundleLitBinding(litMap)) => + litMap.get(this) match { + case Some(litArg) => Some(ElementLitBinding(litArg)) + case _ => Some(DontCareBinding()) + } + case Some(VecLitBinding(litMap)) => + litMap.get(this) match { + case Some(litArg) => Some(ElementLitBinding(litArg)) + case _ => Some(DontCareBinding()) + } + case Some(b @ AggregateViewBinding(viewMap, _)) => + viewMap.get(this) match { + case Some(elt) => Some(ViewBinding(elt)) + case _ => throwException(s"Internal Error! $this missing from topBinding $b") + } case topBindingOpt => topBindingOpt } private[chisel3] def litArgOption: Option[LitArg] = topBindingOpt match { case Some(ElementLitBinding(litArg)) => Some(litArg) - case _ => None + case _ => None } - override def litOption: Option[BigInt] = litArgOption.map(_.num) + override def litOption: Option[BigInt] = litArgOption.map(_.num) private[chisel3] def litIsForcedWidth: Option[Boolean] = litArgOption.map(_.forcedWidth) private[chisel3] def legacyConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit = { diff --git a/core/src/main/scala/chisel3/Mem.scala b/core/src/main/scala/chisel3/Mem.scala index aeacf052..ff5072ad 100644 --- a/core/src/main/scala/chisel3/Mem.scala +++ b/core/src/main/scala/chisel3/Mem.scala @@ -9,8 +9,7 @@ import firrtl.{ir => fir} import chisel3.internal._ import chisel3.internal.Builder.pushCommand import chisel3.internal.firrtl._ -import chisel3.internal.sourceinfo.{SourceInfo, SourceInfoTransform, UnlocatableSourceInfo, MemTransform} - +import chisel3.internal.sourceinfo.{MemTransform, SourceInfo, SourceInfoTransform, UnlocatableSourceInfo} object Mem { @@ -29,11 +28,17 @@ object Mem { 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] = { + 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 mt = t.cloneTypeFull val mem = new Mem(mt, size) mt.bind(MemTypeBinding(mem)) pushCommand(DefMemory(sourceInfo, mem, mt, size)) @@ -45,7 +50,10 @@ object Mem { do_apply(BigInt(size), t)(sourceInfo, compileOptions) } -sealed abstract class MemBase[T <: Data](val t: T, val length: BigInt) extends HasId with NamedComponent with SourceInfoDoc { +sealed abstract class MemBase[T <: Data](val t: T, val length: BigInt) + extends HasId + with NamedComponent + with SourceInfoDoc { _parent.foreach(_.addId(this)) // REVIEW TODO: make accessors (static/dynamic, read/write) combinations consistent. @@ -107,7 +115,14 @@ sealed abstract class MemBase[T <: Data](val t: T, val length: BigInt) extends H * * @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 = { + 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]] @@ -117,17 +132,22 @@ sealed abstract class MemBase[T <: Data](val t: T, val length: BigInt) extends H 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 } + 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 = { + 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) + 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, Builder.currentWhen)) @@ -148,7 +168,6 @@ sealed class Mem[T <: Data] private (t: T, length: BigInt) extends MemBase(t, le object SyncReadMem { - type ReadUnderWrite = fir.ReadUnderWrite.Value val Undefined = fir.ReadUnderWrite.Undefined val ReadFirst = fir.ReadUnderWrite.Old @@ -171,11 +190,18 @@ object SyncReadMem { def apply[T <: Data](size: Int, t: T, ruw: ReadUnderWrite): SyncReadMem[T] = macro MemTransform.apply_ruw[T] /** @group SourceInfoTransformMacro */ - def do_apply[T <: Data](size: BigInt, t: T, ruw: ReadUnderWrite = Undefined)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SyncReadMem[T] = { + def do_apply[T <: Data]( + size: BigInt, + t: T, + ruw: ReadUnderWrite = Undefined + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): SyncReadMem[T] = { if (compileOptions.declaredTypeMustBeUnbound) { requireIsChiselType(t, "memory type") } - val mt = t.cloneTypeFull + val mt = t.cloneTypeFull val mem = new SyncReadMem(mt, size, ruw) mt.bind(MemTypeBinding(mem)) pushCommand(DefSeqMemory(sourceInfo, mem, mt, size, ruw)) @@ -184,12 +210,25 @@ object SyncReadMem { /** @group SourceInfoTransformMacro */ // Alternate signatures can't use default parameter values - def do_apply[T <: Data](size: Int, t: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SyncReadMem[T] = + def do_apply[T <: Data]( + size: Int, + t: T + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): SyncReadMem[T] = do_apply(BigInt(size), t)(sourceInfo, compileOptions) /** @group SourceInfoTransformMacro */ // Alternate signatures can't use default parameter values - def do_apply[T <: Data](size: Int, t: T, ruw: ReadUnderWrite)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SyncReadMem[T] = + def do_apply[T <: Data]( + size: Int, + t: T, + ruw: ReadUnderWrite + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): SyncReadMem[T] = do_apply(BigInt(size), t, ruw)(sourceInfo, compileOptions) } @@ -203,7 +242,8 @@ object SyncReadMem { * @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, val readUnderWrite: SyncReadMem.ReadUnderWrite) extends MemBase[T](t, n) { +sealed class SyncReadMem[T <: Data] private (t: T, n: BigInt, val readUnderWrite: SyncReadMem.ReadUnderWrite) + extends MemBase[T](t, n) { def read(x: UInt, en: Bool): T = macro SourceInfoTransform.xEnArg /** @group SourceInfoTransformMacro */ @@ -211,14 +251,14 @@ sealed class SyncReadMem[T <: Data] private (t: T, n: BigInt, val readUnderWrite val a = Wire(UInt()) a := DontCare var port: Option[T] = None - when (enable) { + when(enable) { a := addr port = Some(super.do_read(a)) } port.get } - /** @group SourceInfoTransformMacro*/ + /** @group SourceInfoTransformMacro */ override def do_read(idx: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) = do_read(addr = idx, enable = true.B) // note: we implement do_read(addr) for SyncReadMem in terms of do_read(addr, en) in order to ensure that diff --git a/core/src/main/scala/chisel3/Module.scala b/core/src/main/scala/chisel3/Module.scala index 7ba24585..3611f5dd 100644 --- a/core/src/main/scala/chisel3/Module.scala +++ b/core/src/main/scala/chisel3/Module.scala @@ -15,6 +15,7 @@ import _root_.firrtl.annotations.{IsModule, ModuleName, ModuleTarget} import _root_.firrtl.AnnotationSeq object Module extends SourceInfoDoc { + /** A wrapper method that all Module instantiations must be wrapped in * (necessary to help Chisel track internal state). * @@ -25,12 +26,12 @@ object Module extends SourceInfoDoc { 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 = { + 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 " + _)) + throwException( + "Error: Called Module() twice without instantiating a Module." + + sourceInfo.makeMessage(" See " + _) + ) } Builder.readyForModuleConstr = true @@ -38,7 +39,7 @@ object Module extends SourceInfoDoc { val parentWhenStack = Builder.whenStack // Save then clear clock and reset to prevent leaking scope, must be set again in the Module - val (saveClock, saveReset) = (Builder.currentClock, Builder.currentReset) + val (saveClock, saveReset) = (Builder.currentClock, Builder.currentReset) val savePrefix = Builder.getPrefix Builder.clearPrefix() Builder.currentClock = None @@ -49,19 +50,21 @@ object Module extends SourceInfoDoc { // - unset readyForModuleConstr // - reset whenStack to be empty // - set currentClockAndReset - val module: T = bc // bc is actually evaluated here + 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 " + _)) + 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.whenStack = parentWhenStack - Builder.currentClock = saveClock // Back to clock and reset scope + Builder.currentClock = saveClock // Back to clock and reset scope Builder.currentReset = saveReset // Only add the component if the module generates one @@ -84,17 +87,22 @@ object Module extends SourceInfoDoc { /** 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 - private[chisel3] def do_pseudo_apply[T <: BaseModule](bc: => T) - (implicit sourceInfo: SourceInfo, - compileOptions: CompileOptions): T = { + private[chisel3] def do_pseudo_apply[T <: BaseModule]( + bc: => T + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): T = { val parent = Builder.currentModule - val module: T = bc // bc is actually evaluated here + val module: T = bc // bc is actually evaluated here module } @@ -150,12 +158,12 @@ abstract class Module(implicit moduleCompileOptions: CompileOptions) extends Raw } } - package experimental { import chisel3.internal.requireIsChiselType // Fix ambiguous import object IO { + /** Constructs a port for the current Module * * This must wrap the datatype used to set the io field of any Module. @@ -170,20 +178,21 @@ package experimental { * requested (so that all calls to ports will return the same information). * Internal API. */ - def apply[T<:Data](iodef: T): T = { + 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 - } + 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 } @@ -192,9 +201,10 @@ package experimental { package internal { import chisel3.experimental.BaseModule - import chisel3.experimental.hierarchy.{IsInstantiable, Proto, Clone} + import chisel3.experimental.hierarchy.{Clone, IsInstantiable, Proto} object BaseModule { + /** Represents a clone of an underlying object. This is used to support CloneModuleAsRecord and Instance/Definition. * * @note We don't actually "clone" anything in the traditional sense but is a placeholder so we lazily clone internal state @@ -217,7 +227,7 @@ package internal { } // Private internal class to serve as a _parent for Data in cloned ports - private[chisel3] class ModuleClone[T <: BaseModule] (val getProto: T) extends PseudoModule with IsClone[T] { + private[chisel3] class ModuleClone[T <: BaseModule](val getProto: T) extends PseudoModule with IsClone[T] { override def toString = s"ModuleClone(${getProto})" def getPorts = _portsRecord // ClonePorts that hold the bound ports for this module @@ -226,7 +236,7 @@ package internal { // This is necessary for correctly supporting .toTarget on a Module Clone. If it is made from the // Instance/Definition API, it should return an instanceTarget. If made from CMAR, it should return a // ModuleTarget. - private[chisel3] var _madeFromDefinition: Boolean = false + private[chisel3] var _madeFromDefinition: Boolean = false // Don't generate a component, but point to the one for the cloned Module private[chisel3] def generateComponent(): Option[Component] = { require(!_closed, "Can't generate module more than once") @@ -248,14 +258,14 @@ package internal { private[chisel3] def setRefAndPortsRef(namespace: Namespace): Unit = { val record = _portsRecord // Use .forceName to re-use default name resolving behavior - record.forceName(None, default=this.desiredName, namespace) + record.forceName(None, default = this.desiredName, namespace) // Now take the Ref that forceName set and convert it to the correct Arg val instName = record.getRef match { case Ref(name) => name - case bad => throwException(s"Internal Error! Cloned-module Record $record has unexpected ref $bad") + case bad => throwException(s"Internal Error! Cloned-module Record $record has unexpected ref $bad") } // Set both the record and the module to have the same instance name - record.setRef(ModuleCloneIO(getProto, instName), force=true) // force because we did .forceName first + record.setRef(ModuleCloneIO(getProto, instName), force = true) // force because we did .forceName first this.setRef(Ref(instName)) } } @@ -269,7 +279,9 @@ package internal { * @note In addition, the instance name of an InstanceClone is going to be the SAME as the proto, but this is not true * for ModuleClone. */ - private[chisel3] final class InstanceClone[T <: BaseModule] (val getProto: T, val instName: () => String) extends PseudoModule with IsClone[T] { + private[chisel3] final class InstanceClone[T <: BaseModule](val getProto: T, val instName: () => String) + extends PseudoModule + with IsClone[T] { override def toString = s"InstanceClone(${getProto})" // No addition components are generated private[chisel3] def generateComponent(): Option[Component] = None @@ -291,7 +303,7 @@ package internal { * target whose root is the Definition. This DefinitionClone is used to represent the root parent of the * InstanceClone (which represents the returned module). */ - private[chisel3] class DefinitionClone[T <: BaseModule] (val getProto: T) extends PseudoModule with IsClone[T] { + private[chisel3] class DefinitionClone[T <: BaseModule](val getProto: T) extends PseudoModule with IsClone[T] { override def toString = s"DefinitionClone(${getProto})" // No addition components are generated private[chisel3] def generateComponent(): Option[Component] = None @@ -313,13 +325,18 @@ package internal { * @note These are not true Data (the Record doesn't correspond to anything in the emitted * FIRRTL yet its elements *do*) so have some very specialized behavior. */ - private[chisel3] class ClonePorts (elts: Data*)(implicit compileOptions: CompileOptions) extends Record { + 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 = { + private[chisel3] def cloneIORecord( + proto: BaseModule + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): ClonePorts = { require(proto.isClosed, "Can't clone a module before module close") // Fake Module to serve as the _parent of the cloned ports // We make this before clonePorts because we want it to come up first in naming in @@ -353,11 +370,12 @@ package experimental { object BaseModule { implicit class BaseModuleExtensions[T <: BaseModule](b: T) { - import chisel3.experimental.hierarchy.{Instance, Definition} - def toInstance: Instance[T] = new Instance(Proto(b)) + import chisel3.experimental.hierarchy.{Definition, Instance} + def toInstance: Instance[T] = new Instance(Proto(b)) def toDefinition: Definition[T] = new Definition(Proto(b)) } } + /** Abstract base class for Modules, an instantiable organizational unit for RTL. */ // TODO: seal this? @@ -461,30 +479,34 @@ package experimental { val baseName = this.getClass.getName /* A sequence of string filters applied to the name */ - val filters: Seq[String => String] = Seq( - ((a: String) => raw"\$$+anon".r.replaceAllIn(a, "_Anon")) // Merge the "$$anon" name with previous name - ) + val filters: Seq[String => String] = + Seq(((a: String) => raw"\$$+anon".r.replaceAllIn(a, "_Anon")) // Merge the "$$anon" name with previous name + ) filters - .foldLeft(baseName){ case (str, filter) => filter(str) } // 1. Apply filters to baseName - .split("\\.|\\$") // 2. Split string at '.' or '$' - .filterNot(_.forall(_.isDigit)) // 3. Drop purely numeric names - .last // 4. Use the last name + .foldLeft(baseName) { case (str, filter) => filter(str) } // 1. Apply filters to baseName + .split("\\.|\\$") // 2. Split string at '.' or '$' + .filterNot(_.forall(_.isDigit)) // 3. Drop purely numeric names + .last // 4. Use the last name } /** Legalized name of this module. */ - final lazy val name = try { - // PseudoModules are not "true modules" and thus should share - // their original modules names without uniquification - this match { - case _: PseudoModule => desiredName - case _ => Builder.globalNamespace.name(desiredName) + final lazy val name = + try { + // PseudoModules are not "true modules" and thus should share + // their original modules names without uniquification + this match { + case _: PseudoModule => desiredName + case _ => 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 + ) + case t: Throwable => throw t } - } 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) - case t: Throwable => throw t - } /** Returns a FIRRTL ModuleName that references this object * @@ -497,8 +519,10 @@ package experimental { * @note Should not be called until circuit elaboration is complete */ final def toTarget: ModuleTarget = this match { - case m: internal.BaseModule.InstanceClone[_] => throwException(s"Internal Error! It's not legal to call .toTarget on an InstanceClone. $m") - case m: internal.BaseModule.DefinitionClone[_] => throwException(s"Internal Error! It's not legal to call .toTarget on an DefinitionClone. $m") + case m: internal.BaseModule.InstanceClone[_] => + throwException(s"Internal Error! It's not legal to call .toTarget on an InstanceClone. $m") + case m: internal.BaseModule.DefinitionClone[_] => + throwException(s"Internal Error! It's not legal to call .toTarget on an DefinitionClone. $m") case _ => ModuleTarget(this.circuitName, this.name) } @@ -514,10 +538,13 @@ package experimental { * the correct [[InstanceTarget]]s whenever using the Definition/Instance API. */ private[chisel3] def getTarget: IsModule = this match { - case m: internal.BaseModule.InstanceClone[_] if m._parent.nonEmpty => m._parent.get.getTarget.instOf(instanceName, name) - case m: internal.BaseModule.ModuleClone[_] if m._madeFromDefinition => m._parent.get.getTarget.instOf(instanceName, name) + case m: internal.BaseModule.InstanceClone[_] if m._parent.nonEmpty => + m._parent.get.getTarget.instOf(instanceName, name) + case m: internal.BaseModule.ModuleClone[_] if m._madeFromDefinition => + m._parent.get.getTarget.instOf(instanceName, name) // Without this, we get the wrong CircuitName for the Definition - case m: internal.BaseModule.DefinitionClone[_] if m._circuit.nonEmpty => ModuleTarget(this._circuit.get.circuitName, this.name) + case m: internal.BaseModule.DefinitionClone[_] if m._circuit.nonEmpty => + ModuleTarget(this._circuit.get.circuitName, this.name) case _ => this.toTarget } @@ -528,7 +555,7 @@ package experimental { final def toAbsoluteTarget: IsModule = { _parent match { case Some(parent) => parent.toAbsoluteTarget.instOf(this.instanceName, name) - case None => + case None => // FIXME Special handling for Views - evidence of "weirdness" of .toAbsoluteTarget // In theory, .toAbsoluteTarget should not be necessary, .toTarget combined with the // target disambiguation in FIRRTL's deduplication transform should ensure that .toTarget @@ -619,17 +646,19 @@ package experimental { 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 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 } - case SpecifiedDirection.Input | SpecifiedDirection.Output => // forced assign, nothing to do - } } } @@ -669,10 +698,12 @@ package experimental { /** 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 - } + if (_parent == None) name + else + _component match { + case None => getRef.name + case Some(c) => getRef.fullName(c) + } } } diff --git a/core/src/main/scala/chisel3/ModuleAspect.scala b/core/src/main/scala/chisel3/ModuleAspect.scala index a528fa72..471ab980 100644 --- a/core/src/main/scala/chisel3/ModuleAspect.scala +++ b/core/src/main/scala/chisel3/ModuleAspect.scala @@ -12,8 +12,9 @@ import chisel3.internal.{Builder, PseudoModule} * @param module Module for which this object is an aspect of * @param moduleCompileOptions */ -abstract class ModuleAspect private[chisel3] (module: RawModule) - (implicit moduleCompileOptions: CompileOptions) extends RawModule with PseudoModule { +abstract class ModuleAspect private[chisel3] (module: RawModule)(implicit moduleCompileOptions: CompileOptions) + extends RawModule + with PseudoModule { Builder.addAspect(module, this) @@ -23,4 +24,3 @@ abstract class ModuleAspect private[chisel3] (module: RawModule) override val _namespace = module._namespace } - diff --git a/core/src/main/scala/chisel3/MultiClock.scala b/core/src/main/scala/chisel3/MultiClock.scala index 6a745f14..e96946f5 100644 --- a/core/src/main/scala/chisel3/MultiClock.scala +++ b/core/src/main/scala/chisel3/MultiClock.scala @@ -7,6 +7,7 @@ import chisel3.internal._ import scala.language.experimental.macros object withClockAndReset { + /** Creates a new Clock and Reset scope * * @param clock the new implicit Clock @@ -32,13 +33,14 @@ object withClockAndReset { } object withClock { + /** 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 = { + def apply[T](clock: Clock)(block: => T): T = { // Save parentScope val parentClock = Builder.currentClock Builder.currentClock = Some(clock) @@ -50,6 +52,7 @@ object withClock { } object withReset { + /** Creates a new Reset scope * * @param reset the new implicit Reset @@ -67,4 +70,3 @@ object withReset { } } - diff --git a/core/src/main/scala/chisel3/Mux.scala b/core/src/main/scala/chisel3/Mux.scala index 00f2a717..df56182e 100644 --- a/core/src/main/scala/chisel3/Mux.scala +++ b/core/src/main/scala/chisel3/Mux.scala @@ -6,11 +6,12 @@ import scala.language.experimental.macros import chisel3.internal._ import chisel3.internal.Builder.pushOp -import chisel3.internal.sourceinfo.{SourceInfo, MuxTransform} +import chisel3.internal.sourceinfo.{MuxTransform, SourceInfo} import chisel3.internal.firrtl._ import chisel3.internal.firrtl.PrimOp._ object Mux extends SourceInfoDoc { + /** Creates a mux, whose output is one of the inputs depending on the * value of the condition. * @@ -25,13 +26,19 @@ object Mux extends SourceInfoDoc { 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 = { + 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) + val conRef = con match { // this matches chisel semantics (DontCare as object) to firrtl semantics (invalidate) case DontCare => val dcWire = Wire(d) dcWire := DontCare diff --git a/core/src/main/scala/chisel3/Num.scala b/core/src/main/scala/chisel3/Num.scala index 219e18f4..c7e0721f 100644 --- a/core/src/main/scala/chisel3/Num.scala +++ b/core/src/main/scala/chisel3/Num.scala @@ -8,7 +8,6 @@ import chisel3.internal.firrtl.{BinaryPoint, KnownBinaryPoint} import scala.language.experimental.macros import chisel3.internal.sourceinfo.{SourceInfo, SourceInfoTransform} - // REVIEW TODO: Further discussion needed on what Num actually is. /** Abstract trait defining operations available on numeric-like hardware data types. @@ -43,10 +42,10 @@ trait Num[T <: Data] { * $maxWidth * @group Arithmetic */ - final def + (that: T): T = macro SourceInfoTransform.thatArg + final def +(that: T): T = macro SourceInfoTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_+ (that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T + def do_+(that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T /** Multiplication operator * @@ -56,10 +55,10 @@ trait Num[T <: Data] { * $singleCycleMul * @group Arithmetic */ - final def * (that: T): T = macro SourceInfoTransform.thatArg + final def *(that: T): T = macro SourceInfoTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_* (that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T + def do_*(that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T /** Division operator * @@ -69,10 +68,10 @@ trait Num[T <: Data] { * @todo full rules * @group Arithmetic */ - final def / (that: T): T = macro SourceInfoTransform.thatArg + final def /(that: T): T = macro SourceInfoTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_/ (that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T + def do_/(that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T /** Modulo operator * @@ -81,10 +80,10 @@ trait Num[T <: Data] { * $singleCycleDiv * @group Arithmetic */ - final def % (that: T): T = macro SourceInfoTransform.thatArg + final def %(that: T): T = macro SourceInfoTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_% (that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T + def do_%(that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T /** Subtraction operator * @@ -93,10 +92,10 @@ trait Num[T <: Data] { * $maxWidthPlusOne * @group Arithmetic */ - final def - (that: T): T = macro SourceInfoTransform.thatArg + final def -(that: T): T = macro SourceInfoTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_- (that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T + def do_-(that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T /** Less than operator * @@ -104,10 +103,10 @@ trait Num[T <: Data] { * @return a hardware [[Bool]] asserted if this $coll is less than `that` * @group Comparison */ - final def < (that: T): Bool = macro SourceInfoTransform.thatArg + final def <(that: T): Bool = macro SourceInfoTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_< (that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool + def do_<(that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool /** Less than or equal to operator * @@ -115,10 +114,10 @@ trait Num[T <: Data] { * @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 + final def <=(that: T): Bool = macro SourceInfoTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_<= (that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool + def do_<=(that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool /** Greater than operator * @@ -126,10 +125,10 @@ trait Num[T <: Data] { * @return a hardware [[Bool]] asserted if this $coll is greater than `that` * @group Comparison */ - final def > (that: T): Bool = macro SourceInfoTransform.thatArg + final def >(that: T): Bool = macro SourceInfoTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_> (that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool + def do_>(that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool /** Greater than or equal to operator * @@ -137,10 +136,10 @@ trait Num[T <: Data] { * @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 + final def >=(that: T): Bool = macro SourceInfoTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_>= (that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool + def do_>=(that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool /** Absolute value operator * @@ -150,7 +149,10 @@ trait Num[T <: Data] { */ final def abs: T = macro SourceInfoTransform.noArg - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) final def abs(dummy: Int*): T = macro SourceInfoTransform.noArgDummy /** @group SourceInfoTransformMacro */ @@ -189,7 +191,6 @@ object Num extends NumObject * BigInts and Double and BigDecimal * For backwards compatibility this is used with FixedPoint and Interval objects * but is better used with the Num Object - * */ trait NumObject { val MaxBitsBigIntToBigDecimal = 108 @@ -254,7 +255,7 @@ trait NumObject { * @return */ def toDouble(i: BigInt, binaryPoint: Int): Double = { - if(i.bitLength >= 54) { + if (i.bitLength >= 54) { throw new ChiselException( s"BigInt $i with bitlength ${i.bitLength} is too big, precision lost with > $MaxBitsBigIntToDouble bits" ) @@ -275,7 +276,8 @@ trait NumObject { case KnownBinaryPoint(n) => toDouble(value, n) case x => throw new ChiselException(s"Error converting BigDecimal $value to BigInt, binary point must be known, not $x") - } } + } + } /** * converts a bigInt with the given binaryPoint into the BigDecimal representation @@ -284,7 +286,7 @@ trait NumObject { * @return */ def toBigDecimal(value: BigInt, binaryPoint: Int): BigDecimal = { - if(value.bitLength > MaxBitsBigIntToBigDecimal) { + if (value.bitLength > MaxBitsBigIntToBigDecimal) { throw new ChiselException( s"BigInt $value with bitlength ${value.bitLength} is too big, precision lost with > $MaxBitsBigIntToBigDecimal bits" ) diff --git a/core/src/main/scala/chisel3/Printable.scala b/core/src/main/scala/chisel3/Printable.scala index 006286f9..c477716b 100644 --- a/core/src/main/scala/chisel3/Printable.scala +++ b/core/src/main/scala/chisel3/Printable.scala @@ -6,10 +6,7 @@ import chisel3.internal.firrtl.Component import scala.collection.mutable -import java.util.{ - MissingFormatArgumentException, - UnknownFormatConversionException -} +import java.util.{MissingFormatArgumentException, UnknownFormatConversionException} /** Superclass of things that can be printed in the resulting circuit * @@ -47,17 +44,21 @@ import java.util.{ // 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 = { @@ -68,11 +69,11 @@ object Printable { def errorMsg(index: Int) = s"""| fmt = "$fmt" | ${carrotAt(index)} - | data = ${data mkString ", "}""".stripMargin + | 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'" + // Exception wraps msg in s"Format Specifier '$msg'" throw new MissingFormatArgumentException(msg) } args.next() @@ -85,14 +86,14 @@ object Printable { 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 '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 += PString(str.dropRight(1)) // remove format % pables += arg str = "" percent = false @@ -105,9 +106,11 @@ object Printable { val msg = s"Trailing %\n" + errorMsg(fmt.size - 1) throw new UnknownFormatConversionException(msg) } - require(!args.hasNext, + require( + !args.hasNext, s"Too many arguments! More format specifier(s) expected!\n" + - errorMsg(fmt.size)) + errorMsg(fmt.size) + ) pables += PString(str) Printables(pables) @@ -117,15 +120,17 @@ object Printable { 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 + 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) + (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 @@ -137,7 +142,7 @@ object FirrtlFormat { final val legalSpecifiers = List('d', 'x', 'b', 'c') def unapply(x: Char): Option[Char] = - Option(x) filter (x => legalSpecifiers contains x) + Option(x).filter(x => legalSpecifiers contains x) /** Helper for constructing Firrtl Formats * Accepts data to simplify pack @@ -152,26 +157,33 @@ object FirrtlFormat { case "x" => Hexadecimal(bits) case "b" => Binary(bits) case "c" => Character(bits) - case c => throw new Exception(s"Illegal format specifier '$c'!") + 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/core/src/main/scala/chisel3/Printf.scala b/core/src/main/scala/chisel3/Printf.scala index be0146bb..bdcca8e1 100644 --- a/core/src/main/scala/chisel3/Printf.scala +++ b/core/src/main/scala/chisel3/Printf.scala @@ -12,10 +12,10 @@ import chisel3.internal.sourceinfo.SourceInfo * See apply methods for use */ object printf { + /** 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") + 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, s"char ${x} to Int ${x.toInt} must be >= 0") if (x == '"' || x == '\\') { @@ -25,15 +25,18 @@ object printf { } else if (x == '\t') { "\\t" } else { - require(x.toInt >= 32, s"char ${x} to Int ${x.toInt} must be >= 32") // TODO \xNN once FIRRTL issue #59 is resolved + require( + x.toInt >= 32, + s"char ${x} to Int ${x.toInt} must be >= 32" + ) // TODO \xNN once FIRRTL issue #59 is resolved x } } - formatIn map escaped mkString "" + formatIn.map(escaped).mkString("") } /** Named class for [[printf]]s. */ - final class Printf private[chisel3](val pable: Printable) extends VerificationStatement + final class Printf private[chisel3] (val pable: Printable) extends VerificationStatement /** Prints a message in simulation * @@ -73,7 +76,8 @@ object printf { * @param data format string varargs containing data to print */ def apply(fmt: String, data: Bits*)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Printf = - apply(Printable.pack(fmt, data:_*)) + 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 @@ -90,18 +94,29 @@ object printf { */ def apply(pable: Printable)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Printf = { var printfId: Printf = null - when (!Module.reset.asBool) { + when(!Module.reset.asBool) { printfId = printfWithoutReset(pable) } printfId } - private[chisel3] def printfWithoutReset(pable: Printable)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Printf = { + private[chisel3] def printfWithoutReset( + pable: Printable + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Printf = { val clock = Builder.forcedClock val printfId = new Printf(pable) pushCommand(chisel3.internal.firrtl.Printf(printfId, sourceInfo, clock.ref, pable)) printfId } - private[chisel3] def printfWithoutReset(fmt: String, data: Bits*)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Printf = - printfWithoutReset(Printable.pack(fmt, data:_*)) + private[chisel3] def printfWithoutReset( + fmt: String, + data: Bits* + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Printf = + printfWithoutReset(Printable.pack(fmt, data: _*)) } diff --git a/core/src/main/scala/chisel3/RawModule.scala b/core/src/main/scala/chisel3/RawModule.scala index e977d918..b81372d8 100644 --- a/core/src/main/scala/chisel3/RawModule.scala +++ b/core/src/main/scala/chisel3/RawModule.scala @@ -8,7 +8,7 @@ import scala.language.experimental.macros import scala.annotation.nowarn import chisel3.experimental.BaseModule import chisel3.internal._ -import chisel3.internal.BaseModule.{ModuleClone, InstanceClone} +import chisel3.internal.BaseModule.{InstanceClone, ModuleClone} import chisel3.internal.Builder._ import chisel3.internal.firrtl._ import chisel3.internal.sourceinfo.UnlocatableSourceInfo @@ -19,8 +19,7 @@ import _root_.firrtl.annotations.{IsModule, ModuleTarget} * multiple IO() declarations. */ @nowarn("msg=class Port") // delete when Port becomes private -abstract class RawModule(implicit moduleCompileOptions: CompileOptions) - extends BaseModule { +abstract class RawModule(implicit moduleCompileOptions: CompileOptions) extends BaseModule { // // RTL construction internals // @@ -49,19 +48,22 @@ abstract class RawModule(implicit moduleCompileOptions: CompileOptions) port._computeName(None, None).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!") + 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") + Builder.error( + s"Unable to name port $port in $this, " + + "try making it a public field of the Module" + ) port.setRef(ModuleIO(this, "<UNNAMED>")) } } } - private[chisel3] override def generateComponent(): Option[Component] = { require(!_closed, "Can't generate module more than once") _closed = true @@ -79,29 +81,29 @@ abstract class RawModule(implicit moduleCompileOptions: CompileOptions) // All suggestions are in, force names to every node. for (id <- getIds) { id match { - case id: ModuleClone[_] => id.setRefAndPortsRef(_namespace) // special handling + case id: ModuleClone[_] => id.setRefAndPortsRef(_namespace) // special handling case id: InstanceClone[_] => id.setAsInstanceRef() - case id: BaseModule => id.forceName(None, default=id.desiredName, _namespace) - case id: MemBase[_] => id.forceName(None, default="MEM", _namespace) - case id: stop.Stop => id.forceName(None, default="stop", _namespace) - case id: assert.Assert => id.forceName(None, default="assert", _namespace) - case id: assume.Assume => id.forceName(None, default="assume", _namespace) - case id: cover.Cover => id.forceName(None, default="cover", _namespace) - case id: printf.Printf => id.forceName(None, default="printf", _namespace) - case id: Data => + case id: BaseModule => id.forceName(None, default = id.desiredName, _namespace) + case id: MemBase[_] => id.forceName(None, default = "MEM", _namespace) + case id: stop.Stop => id.forceName(None, default = "stop", _namespace) + case id: assert.Assert => id.forceName(None, default = "assert", _namespace) + case id: assume.Assume => id.forceName(None, default = "assume", _namespace) + case id: cover.Cover => id.forceName(None, default = "cover", _namespace) + case id: printf.Printf => id.forceName(None, default = "printf", _namespace) + case id: Data => if (id.isSynthesizable) { id.topBinding match { case OpBinding(_, _) => - id.forceName(Some(""), default="T", _namespace) + id.forceName(Some(""), default = "T", _namespace) case MemoryPortBinding(_, _) => - id.forceName(None, default="MPORT", _namespace) + id.forceName(None, default = "MPORT", _namespace) case PortBinding(_) => - id.forceName(None, default="PORT", _namespace) + id.forceName(None, default = "PORT", _namespace) case RegBinding(_, _) => - id.forceName(None, default="REG", _namespace) + id.forceName(None, default = "REG", _namespace) case WireBinding(_, _) => - id.forceName(Some(""), default="WIRE", _namespace) - case _ => // don't name literals + id.forceName(Some(""), default = "WIRE", _namespace) + case _ => // don't name literals } } // else, don't name unbound types } @@ -110,19 +112,20 @@ abstract class RawModule(implicit moduleCompileOptions: CompileOptions) closeUnboundIds(names) - val firrtlPorts = getModulePorts map { port: Data => + 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 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 } @@ -134,7 +137,7 @@ abstract class RawModule(implicit moduleCompileOptions: CompileOptions) // unless the client wants explicit control over their generation. val invalidateCommands = { if (!compileOptions.explicitInvalidate) { - getModulePorts map { port => DefInvalid(UnlocatableSourceInfo, port.ref) } + getModulePorts.map { port => DefInvalid(UnlocatableSourceInfo, port.ref) } } else { Seq() } @@ -204,13 +207,15 @@ package object internal { .map(_.forceFinalName("io")) .orElse { // Fallback if reflection fails, user can wrap in IO(...) - self.findPort("io") - .collect { case r: Record => r } - }.getOrElse(throwException( - s"Compatibility mode Module '$this' must have a 'val io' Bundle. " + - "If there is such a field and you still see this error, autowrapping has failed (sorry!). " + - "Please wrap the Bundle declaration in IO(...)." - )) + self.findPort("io").collect { case r: Record => r } + } + .getOrElse( + throwException( + s"Compatibility mode Module '$this' must have a 'val io' Bundle. " + + "If there is such a field and you still see this error, autowrapping has failed (sorry!). " + + "Please wrap the Bundle declaration in IO(...)." + ) + ) } /** Legacy Module class that restricts IOs to just io, clock, and reset, and provides a constructor @@ -221,15 +226,19 @@ package object internal { */ abstract class LegacyModule(implicit moduleCompileOptions: CompileOptions) extends Module { // Provide a non-deprecated constructor - def this(override_clock: Option[Clock] = None, override_reset: Option[Bool]=None) - (implicit moduleCompileOptions: CompileOptions) = { + 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 } def this(_clock: Clock)(implicit moduleCompileOptions: CompileOptions) = this(Option(_clock), None)(moduleCompileOptions) - def this(_reset: Bool)(implicit moduleCompileOptions: CompileOptions) = + def this(_reset: Bool)(implicit moduleCompileOptions: CompileOptions) = this(None, Option(_reset))(moduleCompileOptions) def this(_clock: Clock, _reset: Bool)(implicit moduleCompileOptions: CompileOptions) = this(Option(_clock), Option(_reset))(moduleCompileOptions) @@ -240,12 +249,15 @@ package object internal { protected def _compatIoPortBound() = portsContains(_io) private[chisel3] override def generateComponent(): Option[Component] = { - _compatAutoWrapPorts() // pre-IO(...) compatibility hack + _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") + require( + (portsContains(clock)) && (portsContains(reset)), + "Internal error, module did not have clock or reset as IO" + ) require(portsSize == 3, "Module must only have io, clock, and reset as IO") super.generateComponent() @@ -265,8 +277,10 @@ package object internal { * '''Do not use this class in user code'''. Use whichever `BlackBox` is imported by your wildcard * import (preferably `import chisel3._`). */ - abstract class LegacyBlackBox(params: Map[String, Param] = Map.empty[String, Param]) - (implicit moduleCompileOptions: CompileOptions) + abstract class LegacyBlackBox( + params: Map[String, Param] = Map.empty[String, Param] + )( + implicit moduleCompileOptions: CompileOptions) extends chisel3.BlackBox(params) { override private[chisel3] lazy val _io: Record = reflectivelyFindValIO(this) @@ -305,5 +319,6 @@ package object internal { * * @note this is a val instead of an object because of the need to wrap in Module(...) */ - private[chisel3] val ViewParent = Module.do_apply(new ViewParentAPI)(UnlocatableSourceInfo, ExplicitCompileOptions.Strict) + private[chisel3] val ViewParent = + Module.do_apply(new ViewParentAPI)(UnlocatableSourceInfo, ExplicitCompileOptions.Strict) } diff --git a/core/src/main/scala/chisel3/Reg.scala b/core/src/main/scala/chisel3/Reg.scala index 122c5ebd..204beb79 100644 --- a/core/src/main/scala/chisel3/Reg.scala +++ b/core/src/main/scala/chisel3/Reg.scala @@ -27,9 +27,9 @@ import chisel3.internal.sourceinfo.SourceInfo * // 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 @@ -74,6 +74,7 @@ object Reg { * }}} */ object RegNext { + /** Returns a register ''with an unset width'' connected to the signal `next` and with no reset value. */ def apply[T <: Data](next: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T = { val model = (next match { @@ -94,7 +95,7 @@ object RegNext { case next: Bits => next.cloneTypeWidth(Width()) case next => next.cloneTypeFull }).asInstanceOf[T] - val reg = RegInit(model, init) // TODO: this makes NO sense + val reg = RegInit(model, init) // TODO: this makes NO sense requireIsHardware(next, "reg next") reg := next @@ -162,6 +163,7 @@ object RegNext { * }}} */ 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 diff --git a/core/src/main/scala/chisel3/SIntFactory.scala b/core/src/main/scala/chisel3/SIntFactory.scala index b34c7dde..3fafacda 100644 --- a/core/src/main/scala/chisel3/SIntFactory.scala +++ b/core/src/main/scala/chisel3/SIntFactory.scala @@ -5,8 +5,10 @@ package chisel3 import chisel3.internal.firrtl.{IntervalRange, SLit, Width} 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) diff --git a/core/src/main/scala/chisel3/SeqUtils.scala b/core/src/main/scala/chisel3/SeqUtils.scala index 5c86efd3..b1136120 100644 --- a/core/src/main/scala/chisel3/SeqUtils.scala +++ b/core/src/main/scala/chisel3/SeqUtils.scala @@ -10,6 +10,7 @@ import chisel3.internal.sourceinfo._ import chisel3.internal.plugin.autoNameRecursively 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. @@ -27,10 +28,10 @@ private[chisel3] object SeqUtils { in.head.asUInt } else { val lo = autoNameRecursively("lo")(prefix("lo") { - asUInt(in.slice(0, in.length/2)) + asUInt(in.slice(0, in.length / 2)) }) val hi = autoNameRecursively("hi")(prefix("hi") { - asUInt(in.slice(in.length/2, in.length)) + asUInt(in.slice(in.length / 2, in.length)) }) hi ## lo } @@ -45,7 +46,7 @@ private[chisel3] object SeqUtils { case 0 => 0.U case 1 => in.head case n => - val sum = count(in take n/2) +& count(in drop n/2) + val sum = count(in.take(n / 2)) +& count(in.drop(n / 2)) sum(BigInt(n).bitLength - 1, 0) } @@ -54,8 +55,12 @@ private[chisel3] object SeqUtils { 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 = { + def do_priorityMux[T <: Data]( + in: Seq[(Bool, T)] + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): T = { if (in.size == 1) { in.head._2 } else { @@ -72,13 +77,16 @@ private[chisel3] object SeqUtils { def oneHotMux[T <: Data](in: Iterable[(Bool, T)]): T = macro SourceInfoTransform.inArg /** @group SourceInfoTransformMacros */ - def do_oneHotMux[T <: Data](in: Iterable[(Bool, T)]) - (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T = { + 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") + } 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) @@ -89,8 +97,9 @@ private[chisel3] object SeqUtils { 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 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) @@ -99,20 +108,20 @@ private[chisel3] object SeqUtils { 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) + 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 { + } 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] } + inWidthMatched.zipWithIndex.foreach { case (e, idx) => e := possibleOuts(idx).asInstanceOf[FixedPoint] } buildAndOrMultiplexor(sels.zip(inWidthMatched)) } @@ -123,12 +132,12 @@ private[chisel3] object SeqUtils { val (sel, inData) = in.unzip val inElts = inData.map(_.asInstanceOf[Aggregate].getElements) // We want to iterate on the columns of inElts, so we transpose - out.getElements.zip(inElts.transpose).foreach { case (outElt, elts) => - outElt := oneHotMux(sel.zip(elts)) + out.getElements.zip(inElts.transpose).foreach { + case (outElt, elts) => + outElt := oneHotMux(sel.zip(elts)) } out.asInstanceOf[T] - } - else { + } else { throwException(s"Cannot Mux1H with aggregates with inferred widths") } diff --git a/core/src/main/scala/chisel3/StrongEnum.scala b/core/src/main/scala/chisel3/StrongEnum.scala index fa420e80..6f9cce55 100644 --- a/core/src/main/scala/chisel3/StrongEnum.scala +++ b/core/src/main/scala/chisel3/StrongEnum.scala @@ -10,11 +10,11 @@ import chisel3.internal.Builder.pushOp import chisel3.internal.firrtl.PrimOp._ import chisel3.internal.firrtl._ import chisel3.internal.sourceinfo._ -import chisel3.internal.{Binding, Builder, ChildBinding, ConstrainedBinding, InstanceId, throwException} +import chisel3.internal.{throwException, Binding, Builder, ChildBinding, ConstrainedBinding, InstanceId} import firrtl.annotations._ - object EnumAnnotations { + /** An annotation for strong enum instances that are ''not'' inside of Vecs * * @param target the enum instance being annotated @@ -31,7 +31,7 @@ object EnumAnnotations { /** 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() @@ -47,13 +47,14 @@ object EnumAnnotations { * @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] { + case class EnumVecAnnotation(target: Named, typeName: String, fields: Seq[Seq[String]]) + extends SingleTargetAnnotation[Named] { def duplicate(n: Named): EnumVecAnnotation = this.copy(target = n) } - case class EnumVecChiselAnnotation(target: InstanceId, typeName: String, fields: Seq[Seq[String]]) extends ChiselAnnotation { + case class EnumVecChiselAnnotation(target: InstanceId, typeName: String, fields: Seq[Seq[String]]) + extends ChiselAnnotation { override def toFirrtl: EnumVecAnnotation = EnumVecAnnotation(target.toNamed, typeName, fields) } @@ -70,7 +71,6 @@ object EnumAnnotations { } import EnumAnnotations._ - abstract class EnumType(private val factory: EnumFactory, selfAnnotating: Boolean = true) extends Element { // Use getSimpleName instead of enumTypeName because for debugging purposes @@ -78,10 +78,11 @@ abstract class EnumType(private val factory: EnumFactory, selfAnnotating: Boolea // Enum annotation), and it's more consistent with Bundle printing. override def toString: String = { litOption match { - case Some(value) => factory.nameOfValue(value) match { - case Some(name) => s"${factory.getClass.getSimpleName.init}($value=$name)" - case None => stringAccessor(s"${factory.getClass.getSimpleName.init}($value=(invalid))") - } + case Some(value) => + factory.nameOfValue(value) match { + case Some(name) => s"${factory.getClass.getSimpleName.init}($value=$name)" + case None => stringAccessor(s"${factory.getClass.getSimpleName.init}($value=(invalid))") + } case _ => stringAccessor(s"${factory.getClass.getSimpleName.init}") } } @@ -92,7 +93,7 @@ abstract class EnumType(private val factory: EnumFactory, selfAnnotating: Boolea requireIsHardware(this, "bits operated on") requireIsHardware(other, "bits operated on") - if(!this.typeEquivalent(other)) { + if (!this.typeEquivalent(other)) { throwException(s"Enum types are not equivalent: ${this.enumTypeName}, ${other.enumTypeName}") } @@ -104,24 +105,34 @@ abstract class EnumType(private val factory: EnumFactory, selfAnnotating: Boolea this.factory == that.asInstanceOf[EnumType].factory } - private[chisel3] override def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo, - compileOptions: CompileOptions): Unit = { + private[chisel3] 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 - - 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) + 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 + + 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) override def do_asUInt(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = pushOp(DefPrim(sourceInfo, UInt(width), AsUIntOp, ref)) @@ -151,21 +162,26 @@ abstract class EnumType(private val factory: EnumFactory, selfAnnotating: Boolea * @param u2 zero or more additional values to look for * @return a hardware [[Bool]] that indicates if this value matches any of the given values */ - final def isOneOf(u1: EnumType, u2: EnumType*)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool - = isOneOf(u1 +: u2.toSeq) + final def isOneOf( + u1: EnumType, + u2: EnumType* + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Bool = isOneOf(u1 +: u2.toSeq) def next(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): this.type = { if (litOption.isDefined) { val index = factory.all.indexOf(this) - if (index < factory.all.length-1) { + 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) } ) + 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] } } @@ -175,7 +191,10 @@ abstract class EnumType(private val factory: EnumFactory, selfAnnotating: Boolea lit.bindLitArg(this) } - override private[chisel3] def bind(target: Binding, parentDirection: SpecifiedDirection = SpecifiedDirection.Unspecified): Unit = { + 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 @@ -186,10 +205,11 @@ abstract class EnumType(private val factory: EnumFactory, selfAnnotating: Boolea // 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 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)) @@ -205,10 +225,11 @@ abstract class EnumType(private val factory: EnumFactory, selfAnnotating: Boolea } d.binding match { - case Some(ChildBinding(parent)) => outerMostVec(parent) match { - case outer @ Some(_) => outer - case None => currentVecOpt - } + case Some(ChildBinding(parent)) => + outerMostVec(parent) match { + case outer @ Some(_) => outer + case None => currentVecOpt + } case _ => currentVecOpt } } @@ -216,7 +237,7 @@ abstract class EnumType(private val factory: EnumFactory, selfAnnotating: Boolea private def annotateEnum(): Unit = { val anno = outerMostVec() match { case Some(v) => EnumVecChiselAnnotation(v, enumTypeName, enumFields(v)) - case None => EnumComponentChiselAnnotation(this, enumTypeName) + case None => EnumComponentChiselAnnotation(this, enumTypeName) } if (!Builder.annotations.contains(anno)) { @@ -233,14 +254,13 @@ abstract class EnumType(private val factory: EnumFactory, selfAnnotating: Boolea 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 var id: BigInt = 0 private[chisel3] var width: Width = 0.W private case class EnumRecord(inst: Type, name: String) @@ -255,7 +275,7 @@ abstract class EnumFactory { // Do all bitvectors of this Enum's width represent legal states? private[chisel3] def isTotal: Boolean = { (this.getWidth < 31) && // guard against Integer overflow - (enumRecords.size == (1 << this.getWidth)) + (enumRecords.size == (1 << this.getWidth)) } private[chisel3] def globalAnnotation: EnumDefChiselAnnotation = @@ -280,7 +300,7 @@ abstract class EnumFactory { enumRecords.append(EnumRecord(result, name)) - width = (1 max id.bitLength).W + width = (1.max(id.bitLength)).W id += 1 result @@ -302,11 +322,17 @@ abstract class EnumFactory { def apply(): Type = new Type - private def castImpl(n: UInt, warn: Boolean)(implicit sourceInfo: SourceInfo, connectionCompileOptions: CompileOptions): Type = { + private def castImpl( + n: UInt, + warn: Boolean + )( + implicit sourceInfo: SourceInfo, + connectionCompileOptions: CompileOptions + ): Type = { 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") + 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") @@ -314,7 +340,9 @@ abstract class EnumFactory { throwException(s"The UInt being cast to $enumTypeName is wider than $enumTypeName's width ($getWidth)") } else { if (warn && !this.isTotal) { - Builder.warning(s"Casting non-literal UInt to $enumTypeName. You can use $enumTypeName.safe to cast without this warning.") + Builder.warning( + s"Casting non-literal UInt to $enumTypeName. You can use $enumTypeName.safe to cast without this warning." + ) } val glue = Wire(new UnsafeEnum(width)) glue := n @@ -330,7 +358,8 @@ abstract class EnumFactory { * @param n the UInt to cast * @return the equivalent Enum to the value of the cast UInt */ - def apply(n: UInt)(implicit sourceInfo: SourceInfo, connectionCompileOptions: CompileOptions): Type = castImpl(n, warn = true) + def apply(n: UInt)(implicit sourceInfo: SourceInfo, connectionCompileOptions: CompileOptions): Type = + castImpl(n, warn = true) /** Safely cast an [[UInt]] to the type of this Enum * @@ -344,9 +373,8 @@ abstract class EnumFactory { } } - private[chisel3] object EnumMacros { - def ValImpl(c: Context) : c.Tree = { + def ValImpl(c: Context): c.Tree = { import c.universe._ // Much thanks to michael_s for this solution: @@ -375,7 +403,6 @@ private[chisel3] object EnumMacros { } } - // 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) { diff --git a/core/src/main/scala/chisel3/UIntFactory.scala b/core/src/main/scala/chisel3/UIntFactory.scala index e0f3dc92..64127991 100644 --- a/core/src/main/scala/chisel3/UIntFactory.scala +++ b/core/src/main/scala/chisel3/UIntFactory.scala @@ -9,8 +9,10 @@ import firrtl.ir.{Closed, IntWidth, Open} // 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) @@ -21,6 +23,7 @@ trait UIntFactory { // Bind result to being an Literal lit.bindLitArg(result) } + /** Create a UInt with the specified range, validate that range is effectively > 0 */ def apply(range: IntervalRange): UInt = { @@ -34,8 +37,8 @@ trait UIntFactory { } // because this is a UInt we don't have to take into account the lower bound - val newWidth = if(range.upperBound.isInstanceOf[IsKnown]) { - KnownWidth(Utils.getUIntWidth(range.maxAdjusted.get).max(1)) // max(1) handles range"[0,0]" + val newWidth = if (range.upperBound.isInstanceOf[IsKnown]) { + KnownWidth(Utils.getUIntWidth(range.maxAdjusted.get).max(1)) // max(1) handles range"[0,0]" } else { UnknownWidth() } diff --git a/core/src/main/scala/chisel3/VerificationStatement.scala b/core/src/main/scala/chisel3/VerificationStatement.scala index 23adc192..bfdfc26e 100644 --- a/core/src/main/scala/chisel3/VerificationStatement.scala +++ b/core/src/main/scala/chisel3/VerificationStatement.scala @@ -12,6 +12,7 @@ import chisel3.internal.sourceinfo.SourceInfo import scala.reflect.macros.blackbox object assert { + /** 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. * @@ -33,34 +34,62 @@ object assert { * 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): Assert = macro _applyMacroWithMessage - def apply(cond: Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Assert = macro _applyMacroWithNoMessage + def apply( + cond: Bool, + message: String, + data: Bits* + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Assert = macro _applyMacroWithMessage + def apply(cond: Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Assert = + macro _applyMacroWithNoMessage /** An elaboration-time assertion. Calls the built-in Scala assert function. */ def apply(cond: Boolean, message: => String): Unit = Predef.assert(cond, message) + /** An elaboration-time assertion. Calls the built-in Scala assert function. */ def apply(cond: Boolean): Unit = Predef.assert(cond, "") /** Named class for assertions. */ - final class Assert private[chisel3]() extends VerificationStatement + final class Assert private[chisel3] () extends VerificationStatement import VerificationStatement._ - def _applyMacroWithMessage(c: blackbox.Context)(cond: c.Tree, message: c.Tree, data: c.Tree*)(sourceInfo: c.Tree, compileOptions: c.Tree): c.Tree = { + def _applyMacroWithMessage( + c: blackbox.Context + )(cond: c.Tree, + message: c.Tree, + data: c.Tree* + )(sourceInfo: c.Tree, + compileOptions: c.Tree + ): c.Tree = { import c.universe._ val apply_impl_do = symbolOf[this.type].asClass.module.info.member(TermName("_applyWithSourceLine")) q"$apply_impl_do($cond, ${getLine(c)}, _root_.scala.Some($message), ..$data)($sourceInfo, $compileOptions)" } - def _applyMacroWithNoMessage(c: blackbox.Context)(cond: c.Tree)(sourceInfo: c.Tree, compileOptions: c.Tree): c.Tree = { + def _applyMacroWithNoMessage( + c: blackbox.Context + )(cond: c.Tree + )(sourceInfo: c.Tree, + compileOptions: c.Tree + ): c.Tree = { import c.universe._ val apply_impl_do = symbolOf[this.type].asClass.module.info.member(TermName("_applyWithSourceLine")) q"$apply_impl_do($cond, ${getLine(c)}, _root_.scala.None)($sourceInfo, $compileOptions)" } /** Used by our macros. Do not call directly! */ - def _applyWithSourceLine(cond: Bool, line: SourceLineInfo, message: Option[String], data: Bits*) - (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Assert = { + def _applyWithSourceLine( + cond: Bool, + line: SourceLineInfo, + message: Option[String], + data: Bits* + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Assert = { val id = new Assert() when(!Module.reset.asBool()) { Builder.pushCommand(Verification(id, Formal.Assert, sourceInfo, Module.clock.ref, cond.ref, "")) @@ -70,8 +99,8 @@ object assert { } } - object assume { + /** Assumes a condition to be valid in the circuit at all times. * Acts like an assertion in simulation and imposes a declarative * assumption on the state explored by formal tools. @@ -91,34 +120,62 @@ object assume { * @note See [[printf.apply(fmt:String* printf]] for format string documentation */ // 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): Assume = macro _applyMacroWithMessage - def apply(cond: Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Assume = macro _applyMacroWithNoMessage + def apply( + cond: Bool, + message: String, + data: Bits* + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Assume = macro _applyMacroWithMessage + def apply(cond: Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Assume = + macro _applyMacroWithNoMessage /** An elaboration-time assumption. Calls the built-in Scala assume function. */ def apply(cond: Boolean, message: => String): Unit = Predef.assume(cond, message) + /** An elaboration-time assumption. Calls the built-in Scala assume function. */ def apply(cond: Boolean): Unit = Predef.assume(cond, "") /** Named class for assumptions. */ - final class Assume private[chisel3]() extends VerificationStatement + final class Assume private[chisel3] () extends VerificationStatement import VerificationStatement._ - def _applyMacroWithMessage(c: blackbox.Context)(cond: c.Tree, message: c.Tree, data: c.Tree*)(sourceInfo: c.Tree, compileOptions: c.Tree): c.Tree = { + def _applyMacroWithMessage( + c: blackbox.Context + )(cond: c.Tree, + message: c.Tree, + data: c.Tree* + )(sourceInfo: c.Tree, + compileOptions: c.Tree + ): c.Tree = { import c.universe._ val apply_impl_do = symbolOf[this.type].asClass.module.info.member(TermName("_applyWithSourceLine")) q"$apply_impl_do($cond, ${getLine(c)}, _root_.scala.Some($message), ..$data)($sourceInfo, $compileOptions)" } - def _applyMacroWithNoMessage(c: blackbox.Context)(cond: c.Tree)(sourceInfo: c.Tree, compileOptions: c.Tree): c.Tree = { + def _applyMacroWithNoMessage( + c: blackbox.Context + )(cond: c.Tree + )(sourceInfo: c.Tree, + compileOptions: c.Tree + ): c.Tree = { import c.universe._ val apply_impl_do = symbolOf[this.type].asClass.module.info.member(TermName("_applyWithSourceLine")) q"$apply_impl_do($cond, ${getLine(c)}, _root_.scala.None)($sourceInfo, $compileOptions)" } /** Used by our macros. Do not call directly! */ - def _applyWithSourceLine(cond: Bool, line: SourceLineInfo, message: Option[String], data: Bits*) - (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Assume = { + def _applyWithSourceLine( + cond: Bool, + line: SourceLineInfo, + message: Option[String], + data: Bits* + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Assume = { val id = new Assume() when(!Module.reset.asBool()) { Builder.pushCommand(Verification(id, Formal.Assume, sourceInfo, Module.clock.ref, cond.ref, "")) @@ -128,8 +185,8 @@ object assume { } } - object cover { + /** Declares a condition to be covered. * At ever clock event, a counter is incremented iff the condition is active * and reset is inactive. @@ -146,29 +203,48 @@ object cover { * @param message a string describing the cover event */ // Macros currently can't take default arguments, so we need two functions to emulate defaults. - def apply(cond: Bool, message: String)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Cover = macro _applyMacroWithMessage - def apply(cond: Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Cover = macro _applyMacroWithNoMessage + def apply(cond: Bool, message: String)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Cover = + macro _applyMacroWithMessage + def apply(cond: Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Cover = + macro _applyMacroWithNoMessage /** Named class for cover statements. */ - final class Cover private[chisel3]() extends VerificationStatement + final class Cover private[chisel3] () extends VerificationStatement import VerificationStatement._ - def _applyMacroWithNoMessage(c: blackbox.Context)(cond: c.Tree)(sourceInfo: c.Tree, compileOptions: c.Tree): c.Tree = { + def _applyMacroWithNoMessage( + c: blackbox.Context + )(cond: c.Tree + )(sourceInfo: c.Tree, + compileOptions: c.Tree + ): c.Tree = { import c.universe._ val apply_impl_do = symbolOf[this.type].asClass.module.info.member(TermName("_applyWithSourceLine")) q"$apply_impl_do($cond, ${getLine(c)}, _root_.scala.None)($sourceInfo, $compileOptions)" } - def _applyMacroWithMessage(c: blackbox.Context)(cond: c.Tree, message: c.Tree)(sourceInfo: c.Tree, compileOptions: c.Tree): c.Tree = { + def _applyMacroWithMessage( + c: blackbox.Context + )(cond: c.Tree, + message: c.Tree + )(sourceInfo: c.Tree, + compileOptions: c.Tree + ): c.Tree = { import c.universe._ val apply_impl_do = symbolOf[this.type].asClass.module.info.member(TermName("_applyWithSourceLine")) q"$apply_impl_do($cond, ${getLine(c)}, _root_.scala.Some($message))($sourceInfo, $compileOptions)" } /** Used by our macros. Do not call directly! */ - def _applyWithSourceLine(cond: Bool, line: SourceLineInfo, message: Option[String]) - (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Cover = { + def _applyWithSourceLine( + cond: Bool, + line: SourceLineInfo, + message: Option[String] + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Cover = { val id = new Cover() when(!Module.reset.asBool()) { Builder.pushCommand(Verification(id, Formal.Cover, sourceInfo, Module.clock.ref, cond.ref, "")) @@ -178,30 +254,34 @@ object cover { } object stop { + /** Terminate execution, indicating success. * * @param message a string describing why the simulation was stopped */ def apply(message: String = "")(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Stop = { val stp = new Stop() - when (!Module.reset.asBool) { + when(!Module.reset.asBool) { pushCommand(Stop(stp, sourceInfo, Builder.forcedClock.ref, 0)) } stp } /** Terminate execution with a failure code. */ - @deprecated("Non-zero return codes are not well supported. Please use assert(false.B) if you want to indicate a failure.", "Chisel 3.5") + @deprecated( + "Non-zero return codes are not well supported. Please use assert(false.B) if you want to indicate a failure.", + "Chisel 3.5" + ) def apply(code: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Stop = { val stp = new Stop() - when (!Module.reset.asBool) { + when(!Module.reset.asBool) { pushCommand(Stop(stp, sourceInfo, Builder.forcedClock.ref, code)) } stp } /** Named class for [[stop]]s. */ - final class Stop private[chisel3]()extends VerificationStatement + final class Stop private[chisel3] () extends VerificationStatement } /** Base class for all verification statements: Assert, Assume, Cover, Stop and Printf. */ @@ -220,8 +300,16 @@ private object VerificationStatement { } // creates a printf to inform the user of a failed assertion or assumption - def failureMessage(kind: String, lineInfo: SourceLineInfo, cond: Bool, message: Option[String], data: Seq[Bits]) - (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) : Unit = { + def failureMessage( + kind: String, + lineInfo: SourceLineInfo, + cond: Bool, + message: Option[String], + data: Seq[Bits] + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Unit = { val (filename, line, content) = lineInfo val lineMsg = s"$filename:$line $content".replaceAll("%", "%%") val fmt = message match { @@ -230,7 +318,7 @@ private object VerificationStatement { case None => s"$kind failed\n at $lineMsg\n" } when(!cond) { - printf.printfWithoutReset(fmt, data:_*) + printf.printfWithoutReset(fmt, data: _*) } } } diff --git a/core/src/main/scala/chisel3/When.scala b/core/src/main/scala/chisel3/When.scala index ca383c0f..727d8d0c 100644 --- a/core/src/main/scala/chisel3/When.scala +++ b/core/src/main/scala/chisel3/When.scala @@ -9,6 +9,7 @@ import chisel3.internal.firrtl._ import chisel3.internal.sourceinfo.{SourceInfo, UnlocatableSourceInfo} object when { + /** Create a `when` condition block, where whether a block of logic is * executed or not depends on the conditional. * @@ -27,7 +28,13 @@ object when { * }}} */ - def apply(cond: => Bool)(block: => Any)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): WhenContext = { + def apply( + cond: => Bool + )(block: => Any + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): WhenContext = { new WhenContext(sourceInfo, Some(() => cond), block, 0, Nil) } @@ -44,7 +51,7 @@ object when { * } * } * }}} - * */ + */ def cond: Bool = { implicit val compileOptions = ExplicitCompileOptions.Strict implicit val sourceInfo = UnlocatableSourceInfo @@ -66,13 +73,12 @@ object when { * added by preprocessing the command queue. */ final class WhenContext private[chisel3] ( - sourceInfo: SourceInfo, - cond: Option[() => Bool], - block: => Any, + sourceInfo: SourceInfo, + cond: Option[() => Bool], + block: => Any, firrtlDepth: Int, // For capturing conditions from prior whens or elsewhens - altConds: List[() => Bool] -) { + altConds: List[() => Bool]) { @deprecated("Use when(...) { ... }, this should never have been public", "Chisel 3.4.2") def this(sourceInfo: SourceInfo, cond: Option[() => Bool], block: => Any, firrtlDepth: Int = 0) = @@ -87,8 +93,9 @@ final class WhenContext private[chisel3] ( val alt = altConds.foldRight(true.B) { case (c, acc) => acc & !c() } - cond.map(alt && _()) - .getOrElse(alt) + cond + .map(alt && _()) + .getOrElse(alt) } /** This block of logic gets executed if above conditions have been @@ -97,7 +104,13 @@ final class WhenContext private[chisel3] ( * declaration and assignment of the Bool node of the predicate in * the correct place. */ - def elsewhen (elseCond: => Bool)(block: => Any)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): WhenContext = { + def elsewhen( + elseCond: => Bool + )(block: => Any + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): WhenContext = { new WhenContext(sourceInfo, Some(() => elseCond), block, firrtlDepth + 1, cond ++: altConds) } @@ -113,26 +126,30 @@ final class WhenContext private[chisel3] ( def active: Boolean = scopeOpen - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) def active(dummy: Int*): Boolean = active /* * */ if (firrtlDepth > 0) { pushCommand(AltBegin(sourceInfo)) } - cond.foreach( c => pushCommand(WhenBegin(sourceInfo, c().ref)) ) + cond.foreach(c => pushCommand(WhenBegin(sourceInfo, c().ref))) Builder.pushWhen(this) try { scopeOpen = true block } catch { case _: 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?" + throwException( + "Cannot exit from a when() block with a \"return\"!" + + " Perhaps you meant to use Mux or a Wire as a return value?" ) } scopeOpen = false Builder.popWhen() - cond.foreach(_ => pushCommand(WhenEnd(sourceInfo,firrtlDepth))) - if (cond.isEmpty) { pushCommand(OtherwiseEnd(sourceInfo,firrtlDepth)) } + cond.foreach(_ => pushCommand(WhenEnd(sourceInfo, firrtlDepth))) + if (cond.isEmpty) { pushCommand(OtherwiseEnd(sourceInfo, firrtlDepth)) } } diff --git a/core/src/main/scala/chisel3/aop/Aspect.scala b/core/src/main/scala/chisel3/aop/Aspect.scala index be9b8975..dd014357 100644 --- a/core/src/main/scala/chisel3/aop/Aspect.scala +++ b/core/src/main/scala/chisel3/aop/Aspect.scala @@ -12,10 +12,12 @@ import firrtl.AnnotationSeq * @tparam T Type of top-level module */ abstract class Aspect[T <: RawModule] extends Annotation with Unserializable with NoTargetAnnotation { + /** variable to save [[AnnotationSeq]] from [[chisel3.stage.phases.AspectPhase]] * to be used at [[chisel3.aop.injecting.InjectorAspect]], exposes annotations to [[chisel3.internal.DynamicContext]] */ private[aop] var annotationsInAspect: AnnotationSeq = Seq() + /** Convert this Aspect to a seq of FIRRTL annotation * @param top * @return diff --git a/core/src/main/scala/chisel3/dontTouch.scala b/core/src/main/scala/chisel3/dontTouch.scala index e679f1a4..dc998ff5 100644 --- a/core/src/main/scala/chisel3/dontTouch.scala +++ b/core/src/main/scala/chisel3/dontTouch.scala @@ -2,7 +2,7 @@ package chisel3 -import chisel3.experimental.{ChiselAnnotation, annotate, requireIsHardware} +import chisel3.experimental.{annotate, requireIsHardware, ChiselAnnotation} import firrtl.transforms.DontTouchAnnotation /** Marks that a signal is an optimization barrier to Chisel and the FIRRTL compiler. This has the effect of @@ -26,6 +26,7 @@ import firrtl.transforms.DontTouchAnnotation * dontTouch. */ object dontTouch { + /** Mark a signal as an optimization barrier to Chisel and FIRRTL. * * @note Requires the argument to be bound to hardware diff --git a/core/src/main/scala/chisel3/experimental/Analog.scala b/core/src/main/scala/chisel3/experimental/Analog.scala index e94bae2d..a366f0c3 100644 --- a/core/src/main/scala/chisel3/experimental/Analog.scala +++ b/core/src/main/scala/chisel3/experimental/Analog.scala @@ -5,7 +5,18 @@ package chisel3.experimental import chisel3.internal.firrtl.Width import chisel3.internal.sourceinfo.SourceInfo import chisel3.internal._ -import chisel3.{ActualDirection, Bits, CompileOptions, Data, Element, PString, Printable, RawModule, SpecifiedDirection, UInt} +import chisel3.{ + ActualDirection, + Bits, + CompileOptions, + Data, + Element, + PString, + Printable, + RawModule, + SpecifiedDirection, + UInt +} import scala.collection.mutable @@ -47,7 +58,7 @@ final class Analog private (private[chisel3] val width: Width) extends Element { _parent.foreach(_.addId(this)) SpecifiedDirection.fromParent(parentDirection, specifiedDirection) match { case SpecifiedDirection.Unspecified | SpecifiedDirection.Flip => - case x => throwException(s"Analog may not have explicit direction, got '$x'") + case x => throwException(s"Analog may not have explicit direction, got '$x'") } val targetTopBinding = target match { case target: TopBinding => target @@ -67,8 +78,12 @@ final class Analog private (private[chisel3] val width: Width) extends Element { override def do_asUInt(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = throwException("Analog does not support asUInt") - private[chisel3] override def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo, - compileOptions: CompileOptions): Unit = { + private[chisel3] override def connectFromBits( + that: Bits + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Unit = { throwException("Analog does not support connectFromBits") } diff --git a/core/src/main/scala/chisel3/experimental/Trace.scala b/core/src/main/scala/chisel3/experimental/Trace.scala index 2d965c7b..4ab615a5 100644 --- a/core/src/main/scala/chisel3/experimental/Trace.scala +++ b/core/src/main/scala/chisel3/experimental/Trace.scala @@ -18,7 +18,7 @@ import firrtl.transforms.DontTouchAllTargets * // get final reference of `a` Seq(ReferenceTarget("Dut", "Dut", Seq.empty, "a", Seq.empty)) * val firrtlReferenceOfDutA = finalTarget(annos)(dut.a) * }}} - * */ + */ object Trace { /** Trace a Instance name. */ @@ -49,8 +49,8 @@ object Trace { * @param chiselTarget original annotated target in Chisel, which should not be changed or renamed in FIRRTL. */ private case class TraceNameAnnotation[T <: CompleteTarget](target: T, chiselTarget: T) - extends SingleTargetAnnotation[T] - with DontTouchAllTargets { + extends SingleTargetAnnotation[T] + with DontTouchAllTargets { def duplicate(n: T): Annotation = this.copy(target = n) } @@ -64,6 +64,6 @@ object Trace { * This API can be used to gather all final reference to the signal or module which is marked by `traceName` */ def finalTargetMap(annos: AnnotationSeq): Map[CompleteTarget, Seq[CompleteTarget]] = annos.collect { - case TraceNameAnnotation(t, chiselTarget) => chiselTarget -> t - }.groupBy(_._1).map{case (k, v) => k -> v.map(_._2)} + case TraceNameAnnotation(t, chiselTarget) => chiselTarget -> t + }.groupBy(_._1).map { case (k, v) => k -> v.map(_._2) } } diff --git a/core/src/main/scala/chisel3/experimental/dataview/DataProduct.scala b/core/src/main/scala/chisel3/experimental/dataview/DataProduct.scala index 438f97b8..c6ebe604 100644 --- a/core/src/main/scala/chisel3/experimental/dataview/DataProduct.scala +++ b/core/src/main/scala/chisel3/experimental/dataview/DataProduct.scala @@ -3,7 +3,7 @@ package chisel3.experimental.dataview import chisel3.experimental.BaseModule -import chisel3.{Data, Vec, getRecursiveFields} +import chisel3.{getRecursiveFields, Data, Vec} import scala.annotation.implicitNotFound @@ -18,9 +18,12 @@ import scala.annotation.implicitNotFound * @tparam A Type that has elements of type [[Data]] * @see [[https://www.chisel-lang.org/chisel3/docs/explanations/dataview#dataproduct Detailed Documentation]] */ -@implicitNotFound("Could not find implicit value for DataProduct[${A}].\n" + - "Please see https://www.chisel-lang.org/chisel3/docs/explanations/dataview#dataproduct") +@implicitNotFound( + "Could not find implicit value for DataProduct[${A}].\n" + + "Please see https://www.chisel-lang.org/chisel3/docs/explanations/dataview#dataproduct" +) trait DataProduct[-A] { + /** Provides [[Data]] elements within some containing object * * @param a Containing object @@ -59,6 +62,7 @@ sealed trait LowPriorityDataProduct { * @note DataProduct implementations provided in this object are available in the implicit scope */ object DataProduct extends LowPriorityDataProduct { + /** [[DataProduct]] implementation for [[BaseModule]] */ implicit val userModuleDataProduct: DataProduct[BaseModule] = new DataProduct[BaseModule] { def dataIterator(a: BaseModule, path: String): Iterator[(Data, String)] = { @@ -78,19 +82,18 @@ object DataProduct extends LowPriorityDataProduct { } /** [[DataProduct]] implementation for any `Seq[A]` where `A` has an implementation of `DataProduct`. */ - implicit def seqDataProduct[A : DataProduct]: DataProduct[Seq[A]] = new DataProduct[Seq[A]] { + implicit def seqDataProduct[A: DataProduct]: DataProduct[Seq[A]] = new DataProduct[Seq[A]] { def dataIterator(a: Seq[A], path: String): Iterator[(Data, String)] = { val dpa = implicitly[DataProduct[A]] - a.iterator - .zipWithIndex - .flatMap { case (elt, idx) => + a.iterator.zipWithIndex.flatMap { + case (elt, idx) => dpa.dataIterator(elt, s"$path[$idx]") - } + } } } /** [[DataProduct]] implementation for any [[Tuple2]] where each field has an implementation of `DataProduct`. */ - implicit def tuple2DataProduct[A : DataProduct, B : DataProduct]: DataProduct[(A, B)] = new DataProduct[(A, B)] { + implicit def tuple2DataProduct[A: DataProduct, B: DataProduct]: DataProduct[(A, B)] = new DataProduct[(A, B)] { def dataIterator(tup: (A, B), path: String): Iterator[(Data, String)] = { val dpa = implicitly[DataProduct[A]] val dpb = implicitly[DataProduct[B]] @@ -100,7 +103,7 @@ object DataProduct extends LowPriorityDataProduct { } /** [[DataProduct]] implementation for any [[Tuple3]] where each field has an implementation of `DataProduct`. */ - implicit def tuple3DataProduct[A : DataProduct, B : DataProduct, C : DataProduct]: DataProduct[(A, B, C)] = + implicit def tuple3DataProduct[A: DataProduct, B: DataProduct, C: DataProduct]: DataProduct[(A, B, C)] = new DataProduct[(A, B, C)] { def dataIterator(tup: (A, B, C), path: String): Iterator[(Data, String)] = { val dpa = implicitly[DataProduct[A]] @@ -112,7 +115,12 @@ object DataProduct extends LowPriorityDataProduct { } /** [[DataProduct]] implementation for any [[Tuple4]] where each field has an implementation of `DataProduct`. */ - implicit def tuple4DataProduct[A : DataProduct, B : DataProduct, C : DataProduct, D : DataProduct]: DataProduct[(A, B, C, D)] = + implicit def tuple4DataProduct[ + A: DataProduct, + B: DataProduct, + C: DataProduct, + D: DataProduct + ]: DataProduct[(A, B, C, D)] = new DataProduct[(A, B, C, D)] { def dataIterator(tup: (A, B, C, D), path: String): Iterator[(Data, String)] = { val dpa = implicitly[DataProduct[A]] @@ -129,11 +137,12 @@ object DataProduct extends LowPriorityDataProduct { /** [[DataProduct]] implementation for any [[Tuple5]] where each field has an implementation of `DataProduct`. */ implicit def tuple5DataProduct[ - A : DataProduct, - B : DataProduct, - C : DataProduct, - D : DataProduct, - E : DataProduct]: DataProduct[(A, B, C, D, E)] = + A: DataProduct, + B: DataProduct, + C: DataProduct, + D: DataProduct, + E: DataProduct + ]: DataProduct[(A, B, C, D, E)] = new DataProduct[(A, B, C, D, E)] { def dataIterator(tup: (A, B, C, D, E), path: String): Iterator[(Data, String)] = { val dpa = implicitly[DataProduct[A]] @@ -152,12 +161,13 @@ object DataProduct extends LowPriorityDataProduct { /** [[DataProduct]] implementation for any [[Tuple6]] where each field has an implementation of `DataProduct`. */ implicit def tuple6DataProduct[ - A : DataProduct, - B : DataProduct, - C : DataProduct, - D : DataProduct, - E : DataProduct, - F : DataProduct]: DataProduct[(A, B, C, D, E, F)] = + A: DataProduct, + B: DataProduct, + C: DataProduct, + D: DataProduct, + E: DataProduct, + F: DataProduct + ]: DataProduct[(A, B, C, D, E, F)] = new DataProduct[(A, B, C, D, E, F)] { def dataIterator(tup: (A, B, C, D, E, F), path: String): Iterator[(Data, String)] = { val dpa = implicitly[DataProduct[A]] @@ -178,13 +188,14 @@ object DataProduct extends LowPriorityDataProduct { /** [[DataProduct]] implementation for any [[Tuple7]] where each field has an implementation of `DataProduct`. */ implicit def tuple7DataProduct[ - A : DataProduct, - B : DataProduct, - C : DataProduct, - D : DataProduct, - E : DataProduct, - F : DataProduct, - G : DataProduct]: DataProduct[(A, B, C, D, E, F, G)] = + A: DataProduct, + B: DataProduct, + C: DataProduct, + D: DataProduct, + E: DataProduct, + F: DataProduct, + G: DataProduct + ]: DataProduct[(A, B, C, D, E, F, G)] = new DataProduct[(A, B, C, D, E, F, G)] { def dataIterator(tup: (A, B, C, D, E, F, G), path: String): Iterator[(Data, String)] = { val dpa = implicitly[DataProduct[A]] @@ -207,14 +218,15 @@ object DataProduct extends LowPriorityDataProduct { /** [[DataProduct]] implementation for any [[Tuple8]] where each field has an implementation of `DataProduct`. */ implicit def tuple8DataProduct[ - A : DataProduct, - B : DataProduct, - C : DataProduct, - D : DataProduct, - E : DataProduct, - F : DataProduct, - G : DataProduct, - H : DataProduct]: DataProduct[(A, B, C, D, E, F, G, H)] = + A: DataProduct, + B: DataProduct, + C: DataProduct, + D: DataProduct, + E: DataProduct, + F: DataProduct, + G: DataProduct, + H: DataProduct + ]: DataProduct[(A, B, C, D, E, F, G, H)] = new DataProduct[(A, B, C, D, E, F, G, H)] { def dataIterator(tup: (A, B, C, D, E, F, G, H), path: String): Iterator[(Data, String)] = { val dpa = implicitly[DataProduct[A]] @@ -239,15 +251,16 @@ object DataProduct extends LowPriorityDataProduct { /** [[DataProduct]] implementation for any [[Tuple9]] where each field has an implementation of `DataProduct`. */ implicit def tuple9DataProduct[ - A : DataProduct, - B : DataProduct, - C : DataProduct, - D : DataProduct, - E : DataProduct, - F : DataProduct, - G : DataProduct, - H : DataProduct, - I : DataProduct]: DataProduct[(A, B, C, D, E, F, G, H, I)] = + A: DataProduct, + B: DataProduct, + C: DataProduct, + D: DataProduct, + E: DataProduct, + F: DataProduct, + G: DataProduct, + H: DataProduct, + I: DataProduct + ]: DataProduct[(A, B, C, D, E, F, G, H, I)] = new DataProduct[(A, B, C, D, E, F, G, H, I)] { def dataIterator(tup: (A, B, C, D, E, F, G, H, I), path: String): Iterator[(Data, String)] = { val dpa = implicitly[DataProduct[A]] @@ -274,16 +287,17 @@ object DataProduct extends LowPriorityDataProduct { /** [[DataProduct]] implementation for any [[Tuple9]] where each field has an implementation of `DataProduct`. */ implicit def tuple10DataProduct[ - A : DataProduct, - B : DataProduct, - C : DataProduct, - D : DataProduct, - E : DataProduct, - F : DataProduct, - G : DataProduct, - H : DataProduct, - I : DataProduct, - J : DataProduct]: DataProduct[(A, B, C, D, E, F, G, H, I, J)] = + A: DataProduct, + B: DataProduct, + C: DataProduct, + D: DataProduct, + E: DataProduct, + F: DataProduct, + G: DataProduct, + H: DataProduct, + I: DataProduct, + J: DataProduct + ]: DataProduct[(A, B, C, D, E, F, G, H, I, J)] = new DataProduct[(A, B, C, D, E, F, G, H, I, J)] { def dataIterator(tup: (A, B, C, D, E, F, G, H, I, J), path: String): Iterator[(Data, String)] = { val dpa = implicitly[DataProduct[A]] diff --git a/core/src/main/scala/chisel3/experimental/dataview/DataView.scala b/core/src/main/scala/chisel3/experimental/dataview/DataView.scala index c17a5574..7f20964d 100644 --- a/core/src/main/scala/chisel3/experimental/dataview/DataView.scala +++ b/core/src/main/scala/chisel3/experimental/dataview/DataView.scala @@ -11,7 +11,6 @@ import chisel3.ExplicitCompileOptions.Strict import scala.reflect.runtime.universe.WeakTypeTag import annotation.implicitNotFound - /** Mapping between a target type `T` and a view type `V` * * Enables calling `.viewAs[T]` on instances of the target type. @@ -41,9 +40,11 @@ import annotation.implicitNotFound * @see [[DataView$ object DataView]] for factory methods * @see [[PartialDataView object PartialDataView]] for defining non-total `DataViews` */ -@implicitNotFound("Could not find implicit value for DataView[${T}, ${V}].\n" + - "Please see https://www.chisel-lang.org/chisel3/docs/explanations/dataview") -sealed class DataView[T : DataProduct, V <: Data] private[chisel3] ( +@implicitNotFound( + "Could not find implicit value for DataView[${T}, ${V}].\n" + + "Please see https://www.chisel-lang.org/chisel3/docs/explanations/dataview" +) +sealed class DataView[T: DataProduct, V <: Data] private[chisel3] ( /** Function constructing an object of the View type from an object of the Target type */ private[chisel3] val mkView: T => V, /** Function that returns corresponding fields of the target and view */ @@ -51,8 +52,8 @@ sealed class DataView[T : DataProduct, V <: Data] private[chisel3] ( // Aliasing this with a def below to make the ScalaDoc show up for the field _total: Boolean )( - implicit private[chisel3] val sourceInfo: SourceInfo -) { + implicit private[chisel3] val sourceInfo: SourceInfo) { + /** Indicates if the mapping contains every field of the target */ def total: Boolean = _total @@ -89,15 +90,30 @@ sealed class DataView[T : DataProduct, V <: Data] private[chisel3] ( object DataView { /** Default factory method, alias for [[pairs]] */ - def apply[T : DataProduct, V <: Data](mkView: T => V, pairs: ((T, V) => (Data, Data))*)(implicit sourceInfo: SourceInfo): DataView[T, V] = + def apply[T: DataProduct, V <: Data]( + mkView: T => V, + pairs: ((T, V) => (Data, Data))* + )( + implicit sourceInfo: SourceInfo + ): DataView[T, V] = DataView.pairs(mkView, pairs: _*) /** Construct [[DataView]]s with pairs of functions from the target and view to corresponding fields */ - def pairs[T : DataProduct, V <: Data](mkView: T => V, pairs: ((T, V) => (Data, Data))*)(implicit sourceInfo: SourceInfo): DataView[T, V] = + def pairs[T: DataProduct, V <: Data]( + mkView: T => V, + pairs: ((T, V) => (Data, Data))* + )( + implicit sourceInfo: SourceInfo + ): DataView[T, V] = mapping(mkView: T => V, swizzle(pairs)) /** More general factory method for complex mappings */ - def mapping[T : DataProduct, V <: Data](mkView: T => V, mapping: (T, V) => Iterable[(Data, Data)])(implicit sourceInfo: SourceInfo): DataView[T, V] = + def mapping[T: DataProduct, V <: Data]( + mkView: T => V, + mapping: (T, V) => Iterable[(Data, Data)] + )( + implicit sourceInfo: SourceInfo + ): DataView[T, V] = new DataView[T, V](mkView, mapping, _total = true) /** Provides `invert` for invertible [[DataView]]s @@ -107,7 +123,7 @@ object DataView { * * @note [[PartialDataView]]s are **not** invertible and will result in an elaboration time exception */ - implicit class InvertibleDataView[T <: Data : WeakTypeTag, V <: Data : WeakTypeTag](view: DataView[T, V]) { + implicit class InvertibleDataView[T <: Data: WeakTypeTag, V <: Data: WeakTypeTag](view: DataView[T, V]) { def invert(mkView: V => T): DataView[V, T] = { // It would've been nice to make this a compiler error, but it's unclear how to make that work. // We tried having separate TotalDataView and PartialDataView and only defining inversion for @@ -143,7 +159,10 @@ object DataView { DataView[A, A](chiselTypeOf.apply, { case (x, y) => (x, y) }) /** Provides `DataView[Seq[A], Vec[B]]` for all `A` such that there exists `DataView[A, B]` */ - implicit def seqDataView[A : DataProduct, B <: Data](implicit dv: DataView[A, B], sourceInfo: SourceInfo): DataView[Seq[A], Vec[B]] = { + implicit def seqDataView[A: DataProduct, B <: Data]( + implicit dv: DataView[A, B], + sourceInfo: SourceInfo + ): DataView[Seq[A], Vec[B]] = { // TODO this would need a better way to determine the prototype for the Vec DataView.mapping[Seq[A], Vec[B]]( xs => Vec(xs.size, chiselTypeClone(xs.head.viewAs[B]))(sourceInfo, Strict), // xs.head is not correct in general @@ -151,223 +170,395 @@ object DataView { ) } - /** Provides implementations of [[DataView]] for [[Tuple2]] to [[HWTuple2]] */ - implicit def tuple2DataView[T1 : DataProduct, T2 : DataProduct, V1 <: Data, V2 <: Data]( - implicit v1: DataView[T1, V1], v2: DataView[T2, V2], sourceInfo: SourceInfo + /** Provides implementations of [[DataView]] for [[Tuple2]] to [[HWTuple2]] */ + implicit def tuple2DataView[T1: DataProduct, T2: DataProduct, V1 <: Data, V2 <: Data]( + implicit v1: DataView[T1, V1], + v2: DataView[T2, V2], + sourceInfo: SourceInfo ): DataView[(T1, T2), HWTuple2[V1, V2]] = DataView.mapping( - { case (a, b) => new HWTuple2(a.viewAs[V1].cloneType, b.viewAs[V2].cloneType)}, - { case ((a, b), hwt) => - Seq(a.viewAs[V1] -> hwt._1, - b.viewAs[V2] -> hwt._2) + { case (a, b) => new HWTuple2(a.viewAs[V1].cloneType, b.viewAs[V2].cloneType) }, + { + case ((a, b), hwt) => + Seq(a.viewAs[V1] -> hwt._1, b.viewAs[V2] -> hwt._2) } ) - /** Provides implementations of [[DataView]] for [[Tuple3]] to [[HWTuple3]] */ - implicit def tuple3DataView[ - T1 : DataProduct, T2 : DataProduct, T3 : DataProduct, - V1 <: Data, V2 <: Data, V3 <: Data - ]( - implicit v1: DataView[T1, V1], v2: DataView[T2, V2], v3: DataView[T3, V3], sourceInfo: SourceInfo + /** Provides implementations of [[DataView]] for [[Tuple3]] to [[HWTuple3]] */ + implicit def tuple3DataView[T1: DataProduct, T2: DataProduct, T3: DataProduct, V1 <: Data, V2 <: Data, V3 <: Data]( + implicit v1: DataView[T1, V1], + v2: DataView[T2, V2], + v3: DataView[T3, V3], + sourceInfo: SourceInfo ): DataView[(T1, T2, T3), HWTuple3[V1, V2, V3]] = DataView.mapping( - { case (a, b, c) => new HWTuple3(a.viewAs[V1].cloneType, b.viewAs[V2].cloneType, c.viewAs[V3].cloneType)}, - { case ((a, b, c), hwt) => - Seq(a.viewAs[V1] -> hwt._1, - b.viewAs[V2] -> hwt._2, - c.viewAs[V3] -> hwt._3) + { case (a, b, c) => new HWTuple3(a.viewAs[V1].cloneType, b.viewAs[V2].cloneType, c.viewAs[V3].cloneType) }, + { + case ((a, b, c), hwt) => + Seq(a.viewAs[V1] -> hwt._1, b.viewAs[V2] -> hwt._2, c.viewAs[V3] -> hwt._3) } ) - /** Provides implementations of [[DataView]] for [[Tuple4]] to [[HWTuple4]] */ + /** Provides implementations of [[DataView]] for [[Tuple4]] to [[HWTuple4]] */ implicit def tuple4DataView[ - T1 : DataProduct, T2 : DataProduct, T3 : DataProduct, T4 : DataProduct, - V1 <: Data, V2 <: Data, V3 <: Data, V4 <: Data + T1: DataProduct, + T2: DataProduct, + T3: DataProduct, + T4: DataProduct, + V1 <: Data, + V2 <: Data, + V3 <: Data, + V4 <: Data ]( - implicit v1: DataView[T1, V1], v2: DataView[T2, V2], v3: DataView[T3, V3], v4: DataView[T4, V4], sourceInfo: SourceInfo + implicit v1: DataView[T1, V1], + v2: DataView[T2, V2], + v3: DataView[T3, V3], + v4: DataView[T4, V4], + sourceInfo: SourceInfo ): DataView[(T1, T2, T3, T4), HWTuple4[V1, V2, V3, V4]] = DataView.mapping( - { case (a, b, c, d) => - new HWTuple4(a.viewAs[V1].cloneType, b.viewAs[V2].cloneType, c.viewAs[V3].cloneType, d.viewAs[V4].cloneType - )}, - { case ((a, b, c, d), hwt) => - Seq(a.viewAs[V1] -> hwt._1, - b.viewAs[V2] -> hwt._2, - c.viewAs[V3] -> hwt._3, - d.viewAs[V4] -> hwt._4) + { + case (a, b, c, d) => + new HWTuple4(a.viewAs[V1].cloneType, b.viewAs[V2].cloneType, c.viewAs[V3].cloneType, d.viewAs[V4].cloneType) + }, + { + case ((a, b, c, d), hwt) => + Seq(a.viewAs[V1] -> hwt._1, b.viewAs[V2] -> hwt._2, c.viewAs[V3] -> hwt._3, d.viewAs[V4] -> hwt._4) } ) - /** Provides implementations of [[DataView]] for [[Tuple5]] to [[HWTuple5]] */ + /** Provides implementations of [[DataView]] for [[Tuple5]] to [[HWTuple5]] */ implicit def tuple5DataView[ - T1 : DataProduct, T2 : DataProduct, T3 : DataProduct, T4 : DataProduct, T5 : DataProduct, - V1 <: Data, V2 <: Data, V3 <: Data, V4 <: Data, V5 <: Data + T1: DataProduct, + T2: DataProduct, + T3: DataProduct, + T4: DataProduct, + T5: DataProduct, + V1 <: Data, + V2 <: Data, + V3 <: Data, + V4 <: Data, + V5 <: Data ]( - implicit v1: DataView[T1, V1], v2: DataView[T2, V2], v3: DataView[T3, V3], v4: DataView[T4, V4], v5: DataView[T5, V5], sourceInfo: SourceInfo + implicit v1: DataView[T1, V1], + v2: DataView[T2, V2], + v3: DataView[T3, V3], + v4: DataView[T4, V4], + v5: DataView[T5, V5], + sourceInfo: SourceInfo ): DataView[(T1, T2, T3, T4, T5), HWTuple5[V1, V2, V3, V4, V5]] = { DataView.mapping( - { case tup: Tuple5[T1, T2, T3, T4, T5] => - val (a, b, c, d, e) = tup - new HWTuple5(a.viewAs[V1].cloneType, b.viewAs[V2].cloneType, c.viewAs[V3].cloneType, d.viewAs[V4].cloneType, - e.viewAs[V5].cloneType - ) + { + case tup: Tuple5[T1, T2, T3, T4, T5] => + val (a, b, c, d, e) = tup + new HWTuple5( + a.viewAs[V1].cloneType, + b.viewAs[V2].cloneType, + c.viewAs[V3].cloneType, + d.viewAs[V4].cloneType, + e.viewAs[V5].cloneType + ) }, - { case ((a, b, c, d, e), hwt) => - Seq(a.viewAs[V1] -> hwt._1, - b.viewAs[V2] -> hwt._2, - c.viewAs[V3] -> hwt._3, - d.viewAs[V4] -> hwt._4, - e.viewAs[V5] -> hwt._5) + { + case ((a, b, c, d, e), hwt) => + Seq( + a.viewAs[V1] -> hwt._1, + b.viewAs[V2] -> hwt._2, + c.viewAs[V3] -> hwt._3, + d.viewAs[V4] -> hwt._4, + e.viewAs[V5] -> hwt._5 + ) } ) } - /** Provides implementations of [[DataView]] for [[Tuple6]] to [[HWTuple6]] */ + /** Provides implementations of [[DataView]] for [[Tuple6]] to [[HWTuple6]] */ implicit def tuple6DataView[ - T1 : DataProduct, T2 : DataProduct, T3 : DataProduct, T4 : DataProduct, T5 : DataProduct, - T6 : DataProduct, - V1 <: Data, V2 <: Data, V3 <: Data, V4 <: Data, V5 <: Data, + T1: DataProduct, + T2: DataProduct, + T3: DataProduct, + T4: DataProduct, + T5: DataProduct, + T6: DataProduct, + V1 <: Data, + V2 <: Data, + V3 <: Data, + V4 <: Data, + V5 <: Data, V6 <: Data ]( - implicit v1: DataView[T1, V1], v2: DataView[T2, V2], v3: DataView[T3, V3], v4: DataView[T4, V4], - v5: DataView[T5, V5], v6: DataView[T6, V6], - sourceInfo: SourceInfo + implicit v1: DataView[T1, V1], + v2: DataView[T2, V2], + v3: DataView[T3, V3], + v4: DataView[T4, V4], + v5: DataView[T5, V5], + v6: DataView[T6, V6], + sourceInfo: SourceInfo ): DataView[(T1, T2, T3, T4, T5, T6), HWTuple6[V1, V2, V3, V4, V5, V6]] = DataView.mapping( - { case (a, b, c, d, e, f) => - new HWTuple6(a.viewAs[V1].cloneType, b.viewAs[V2].cloneType, c.viewAs[V3].cloneType, d.viewAs[V4].cloneType, - e.viewAs[V5].cloneType, f.viewAs[V6].cloneType - ) + { + case (a, b, c, d, e, f) => + new HWTuple6( + a.viewAs[V1].cloneType, + b.viewAs[V2].cloneType, + c.viewAs[V3].cloneType, + d.viewAs[V4].cloneType, + e.viewAs[V5].cloneType, + f.viewAs[V6].cloneType + ) }, - { case ((a, b, c, d, e, f), hwt) => - Seq(a.viewAs[V1] -> hwt._1, - b.viewAs[V2] -> hwt._2, - c.viewAs[V3] -> hwt._3, - d.viewAs[V4] -> hwt._4, - e.viewAs[V5] -> hwt._5, - f.viewAs[V6] -> hwt._6) + { + case ((a, b, c, d, e, f), hwt) => + Seq( + a.viewAs[V1] -> hwt._1, + b.viewAs[V2] -> hwt._2, + c.viewAs[V3] -> hwt._3, + d.viewAs[V4] -> hwt._4, + e.viewAs[V5] -> hwt._5, + f.viewAs[V6] -> hwt._6 + ) } ) - /** Provides implementations of [[DataView]] for [[Tuple7]] to [[HWTuple7]] */ + /** Provides implementations of [[DataView]] for [[Tuple7]] to [[HWTuple7]] */ implicit def tuple7DataView[ - T1 : DataProduct, T2 : DataProduct, T3 : DataProduct, T4 : DataProduct, T5 : DataProduct, - T6 : DataProduct, T7 : DataProduct, - V1 <: Data, V2 <: Data, V3 <: Data, V4 <: Data, V5 <: Data, - V6 <: Data, V7 <: Data + T1: DataProduct, + T2: DataProduct, + T3: DataProduct, + T4: DataProduct, + T5: DataProduct, + T6: DataProduct, + T7: DataProduct, + V1 <: Data, + V2 <: Data, + V3 <: Data, + V4 <: Data, + V5 <: Data, + V6 <: Data, + V7 <: Data ]( - implicit v1: DataView[T1, V1], v2: DataView[T2, V2], v3: DataView[T3, V3], v4: DataView[T4, V4], - v5: DataView[T5, V5], v6: DataView[T6, V6], v7: DataView[T7, V7], - sourceInfo: SourceInfo + implicit v1: DataView[T1, V1], + v2: DataView[T2, V2], + v3: DataView[T3, V3], + v4: DataView[T4, V4], + v5: DataView[T5, V5], + v6: DataView[T6, V6], + v7: DataView[T7, V7], + sourceInfo: SourceInfo ): DataView[(T1, T2, T3, T4, T5, T6, T7), HWTuple7[V1, V2, V3, V4, V5, V6, V7]] = DataView.mapping( - { case (a, b, c, d, e, f, g) => - new HWTuple7(a.viewAs[V1].cloneType, b.viewAs[V2].cloneType, c.viewAs[V3].cloneType, d.viewAs[V4].cloneType, - e.viewAs[V5].cloneType, f.viewAs[V6].cloneType, g.viewAs[V7].cloneType - ) + { + case (a, b, c, d, e, f, g) => + new HWTuple7( + a.viewAs[V1].cloneType, + b.viewAs[V2].cloneType, + c.viewAs[V3].cloneType, + d.viewAs[V4].cloneType, + e.viewAs[V5].cloneType, + f.viewAs[V6].cloneType, + g.viewAs[V7].cloneType + ) }, - { case ((a, b, c, d, e, f, g), hwt) => - Seq(a.viewAs[V1] -> hwt._1, - b.viewAs[V2] -> hwt._2, - c.viewAs[V3] -> hwt._3, - d.viewAs[V4] -> hwt._4, - e.viewAs[V5] -> hwt._5, - f.viewAs[V6] -> hwt._6, - g.viewAs[V7] -> hwt._7) + { + case ((a, b, c, d, e, f, g), hwt) => + Seq( + a.viewAs[V1] -> hwt._1, + b.viewAs[V2] -> hwt._2, + c.viewAs[V3] -> hwt._3, + d.viewAs[V4] -> hwt._4, + e.viewAs[V5] -> hwt._5, + f.viewAs[V6] -> hwt._6, + g.viewAs[V7] -> hwt._7 + ) } ) - /** Provides implementations of [[DataView]] for [[Tuple8]] to [[HWTuple8]] */ + /** Provides implementations of [[DataView]] for [[Tuple8]] to [[HWTuple8]] */ implicit def tuple8DataView[ - T1 : DataProduct, T2 : DataProduct, T3 : DataProduct, T4 : DataProduct, T5 : DataProduct, - T6 : DataProduct, T7 : DataProduct, T8 : DataProduct, - V1 <: Data, V2 <: Data, V3 <: Data, V4 <: Data, V5 <: Data, - V6 <: Data, V7 <: Data, V8 <: Data + T1: DataProduct, + T2: DataProduct, + T3: DataProduct, + T4: DataProduct, + T5: DataProduct, + T6: DataProduct, + T7: DataProduct, + T8: DataProduct, + V1 <: Data, + V2 <: Data, + V3 <: Data, + V4 <: Data, + V5 <: Data, + V6 <: Data, + V7 <: Data, + V8 <: Data ]( - implicit v1: DataView[T1, V1], v2: DataView[T2, V2], v3: DataView[T3, V3], v4: DataView[T4, V4], - v5: DataView[T5, V5], v6: DataView[T6, V6], v7: DataView[T7, V7], v8: DataView[T8, V8], - sourceInfo: SourceInfo + implicit v1: DataView[T1, V1], + v2: DataView[T2, V2], + v3: DataView[T3, V3], + v4: DataView[T4, V4], + v5: DataView[T5, V5], + v6: DataView[T6, V6], + v7: DataView[T7, V7], + v8: DataView[T8, V8], + sourceInfo: SourceInfo ): DataView[(T1, T2, T3, T4, T5, T6, T7, T8), HWTuple8[V1, V2, V3, V4, V5, V6, V7, V8]] = DataView.mapping( - { case (a, b, c, d, e, f, g, h) => - new HWTuple8(a.viewAs[V1].cloneType, b.viewAs[V2].cloneType, c.viewAs[V3].cloneType, d.viewAs[V4].cloneType, - e.viewAs[V5].cloneType, f.viewAs[V6].cloneType, g.viewAs[V7].cloneType, h.viewAs[V8].cloneType - ) + { + case (a, b, c, d, e, f, g, h) => + new HWTuple8( + a.viewAs[V1].cloneType, + b.viewAs[V2].cloneType, + c.viewAs[V3].cloneType, + d.viewAs[V4].cloneType, + e.viewAs[V5].cloneType, + f.viewAs[V6].cloneType, + g.viewAs[V7].cloneType, + h.viewAs[V8].cloneType + ) }, - { case ((a, b, c, d, e, f, g, h), hwt) => - Seq(a.viewAs[V1] -> hwt._1, - b.viewAs[V2] -> hwt._2, - c.viewAs[V3] -> hwt._3, - d.viewAs[V4] -> hwt._4, - e.viewAs[V5] -> hwt._5, - f.viewAs[V6] -> hwt._6, - g.viewAs[V7] -> hwt._7, - h.viewAs[V8] -> hwt._8) + { + case ((a, b, c, d, e, f, g, h), hwt) => + Seq( + a.viewAs[V1] -> hwt._1, + b.viewAs[V2] -> hwt._2, + c.viewAs[V3] -> hwt._3, + d.viewAs[V4] -> hwt._4, + e.viewAs[V5] -> hwt._5, + f.viewAs[V6] -> hwt._6, + g.viewAs[V7] -> hwt._7, + h.viewAs[V8] -> hwt._8 + ) } ) - /** Provides implementations of [[DataView]] for [[Tuple9]] to [[HWTuple9]] */ + /** Provides implementations of [[DataView]] for [[Tuple9]] to [[HWTuple9]] */ implicit def tuple9DataView[ - T1 : DataProduct, T2 : DataProduct, T3 : DataProduct, T4 : DataProduct, T5 : DataProduct, - T6 : DataProduct, T7 : DataProduct, T8 : DataProduct, T9 : DataProduct, - V1 <: Data, V2 <: Data, V3 <: Data, V4 <: Data, V5 <: Data, - V6 <: Data, V7 <: Data, V8 <: Data, V9 <: Data + T1: DataProduct, + T2: DataProduct, + T3: DataProduct, + T4: DataProduct, + T5: DataProduct, + T6: DataProduct, + T7: DataProduct, + T8: DataProduct, + T9: DataProduct, + V1 <: Data, + V2 <: Data, + V3 <: Data, + V4 <: Data, + V5 <: Data, + V6 <: Data, + V7 <: Data, + V8 <: Data, + V9 <: Data ]( - implicit v1: DataView[T1, V1], v2: DataView[T2, V2], v3: DataView[T3, V3], v4: DataView[T4, V4], - v5: DataView[T5, V5], v6: DataView[T6, V6], v7: DataView[T7, V7], v8: DataView[T8, V8], - v9: DataView[T9, V9], - sourceInfo: SourceInfo + implicit v1: DataView[T1, V1], + v2: DataView[T2, V2], + v3: DataView[T3, V3], + v4: DataView[T4, V4], + v5: DataView[T5, V5], + v6: DataView[T6, V6], + v7: DataView[T7, V7], + v8: DataView[T8, V8], + v9: DataView[T9, V9], + sourceInfo: SourceInfo ): DataView[(T1, T2, T3, T4, T5, T6, T7, T8, T9), HWTuple9[V1, V2, V3, V4, V5, V6, V7, V8, V9]] = DataView.mapping( - { case (a, b, c, d, e, f, g, h, i) => - new HWTuple9(a.viewAs[V1].cloneType, b.viewAs[V2].cloneType, c.viewAs[V3].cloneType, d.viewAs[V4].cloneType, - e.viewAs[V5].cloneType, f.viewAs[V6].cloneType, g.viewAs[V7].cloneType, h.viewAs[V8].cloneType, - i.viewAs[V9].cloneType - ) + { + case (a, b, c, d, e, f, g, h, i) => + new HWTuple9( + a.viewAs[V1].cloneType, + b.viewAs[V2].cloneType, + c.viewAs[V3].cloneType, + d.viewAs[V4].cloneType, + e.viewAs[V5].cloneType, + f.viewAs[V6].cloneType, + g.viewAs[V7].cloneType, + h.viewAs[V8].cloneType, + i.viewAs[V9].cloneType + ) }, - { case ((a, b, c, d, e, f, g, h, i), hwt) => - Seq(a.viewAs[V1] -> hwt._1, - b.viewAs[V2] -> hwt._2, - c.viewAs[V3] -> hwt._3, - d.viewAs[V4] -> hwt._4, - e.viewAs[V5] -> hwt._5, - f.viewAs[V6] -> hwt._6, - g.viewAs[V7] -> hwt._7, - h.viewAs[V8] -> hwt._8, - i.viewAs[V9] -> hwt._9) + { + case ((a, b, c, d, e, f, g, h, i), hwt) => + Seq( + a.viewAs[V1] -> hwt._1, + b.viewAs[V2] -> hwt._2, + c.viewAs[V3] -> hwt._3, + d.viewAs[V4] -> hwt._4, + e.viewAs[V5] -> hwt._5, + f.viewAs[V6] -> hwt._6, + g.viewAs[V7] -> hwt._7, + h.viewAs[V8] -> hwt._8, + i.viewAs[V9] -> hwt._9 + ) } ) - /** Provides implementations of [[DataView]] for [[Tuple10]] to [[HWTuple10]] */ + /** Provides implementations of [[DataView]] for [[Tuple10]] to [[HWTuple10]] */ implicit def tuple10DataView[ - T1 : DataProduct, T2 : DataProduct, T3 : DataProduct, T4 : DataProduct, T5 : DataProduct, - T6 : DataProduct, T7 : DataProduct, T8 : DataProduct, T9 : DataProduct, T10 : DataProduct, - V1 <: Data, V2 <: Data, V3 <: Data, V4 <: Data, V5 <: Data, - V6 <: Data, V7 <: Data, V8 <: Data, V9 <: Data, V10 <: Data + T1: DataProduct, + T2: DataProduct, + T3: DataProduct, + T4: DataProduct, + T5: DataProduct, + T6: DataProduct, + T7: DataProduct, + T8: DataProduct, + T9: DataProduct, + T10: DataProduct, + V1 <: Data, + V2 <: Data, + V3 <: Data, + V4 <: Data, + V5 <: Data, + V6 <: Data, + V7 <: Data, + V8 <: Data, + V9 <: Data, + V10 <: Data ]( - implicit v1: DataView[T1, V1], v2: DataView[T2, V2], v3: DataView[T3, V3], v4: DataView[T4, V4], - v5: DataView[T5, V5], v6: DataView[T6, V6], v7: DataView[T7, V7], v8: DataView[T8, V8], - v9: DataView[T9, V9], v10: DataView[T10, V10], - sourceInfo: SourceInfo + implicit v1: DataView[T1, V1], + v2: DataView[T2, V2], + v3: DataView[T3, V3], + v4: DataView[T4, V4], + v5: DataView[T5, V5], + v6: DataView[T6, V6], + v7: DataView[T7, V7], + v8: DataView[T8, V8], + v9: DataView[T9, V9], + v10: DataView[T10, V10], + sourceInfo: SourceInfo ): DataView[(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10), HWTuple10[V1, V2, V3, V4, V5, V6, V7, V8, V9, V10]] = DataView.mapping( - { case (a, b, c, d, e, f, g, h, i, j) => - new HWTuple10(a.viewAs[V1].cloneType, b.viewAs[V2].cloneType, c.viewAs[V3].cloneType, d.viewAs[V4].cloneType, - e.viewAs[V5].cloneType, f.viewAs[V6].cloneType, g.viewAs[V7].cloneType, h.viewAs[V8].cloneType, - i.viewAs[V9].cloneType, j.viewAs[V10].cloneType - ) + { + case (a, b, c, d, e, f, g, h, i, j) => + new HWTuple10( + a.viewAs[V1].cloneType, + b.viewAs[V2].cloneType, + c.viewAs[V3].cloneType, + d.viewAs[V4].cloneType, + e.viewAs[V5].cloneType, + f.viewAs[V6].cloneType, + g.viewAs[V7].cloneType, + h.viewAs[V8].cloneType, + i.viewAs[V9].cloneType, + j.viewAs[V10].cloneType + ) }, - { case ((a, b, c, d, e, f, g, h, i, j), hwt) => - Seq(a.viewAs[V1] -> hwt._1, - b.viewAs[V2] -> hwt._2, - c.viewAs[V3] -> hwt._3, - d.viewAs[V4] -> hwt._4, - e.viewAs[V5] -> hwt._5, - f.viewAs[V6] -> hwt._6, - g.viewAs[V7] -> hwt._7, - h.viewAs[V8] -> hwt._8, - i.viewAs[V9] -> hwt._9, - j.viewAs[V10] -> hwt._10) + { + case ((a, b, c, d, e, f, g, h, i, j), hwt) => + Seq( + a.viewAs[V1] -> hwt._1, + b.viewAs[V2] -> hwt._2, + c.viewAs[V3] -> hwt._3, + d.viewAs[V4] -> hwt._4, + e.viewAs[V5] -> hwt._5, + f.viewAs[V6] -> hwt._6, + g.viewAs[V7] -> hwt._7, + h.viewAs[V8] -> hwt._8, + i.viewAs[V9] -> hwt._9, + j.viewAs[V10] -> hwt._10 + ) } ) } @@ -376,14 +567,29 @@ object DataView { object PartialDataView { /** Default factory method, alias for [[pairs]] */ - def apply[T: DataProduct, V <: Data](mkView: T => V, pairs: ((T, V) => (Data, Data))*)(implicit sourceInfo: SourceInfo): DataView[T, V] = + def apply[T: DataProduct, V <: Data]( + mkView: T => V, + pairs: ((T, V) => (Data, Data))* + )( + implicit sourceInfo: SourceInfo + ): DataView[T, V] = PartialDataView.pairs(mkView, pairs: _*) /** Construct [[DataView]]s with pairs of functions from the target and view to corresponding fields */ - def pairs[T: DataProduct, V <: Data](mkView: T => V, pairs: ((T, V) => (Data, Data))*)(implicit sourceInfo: SourceInfo): DataView[T, V] = + def pairs[T: DataProduct, V <: Data]( + mkView: T => V, + pairs: ((T, V) => (Data, Data))* + )( + implicit sourceInfo: SourceInfo + ): DataView[T, V] = mapping(mkView, DataView.swizzle(pairs)) /** More general factory method for complex mappings */ - def mapping[T: DataProduct, V <: Data](mkView: T => V, mapping: (T, V) => Iterable[(Data, Data)])(implicit sourceInfo: SourceInfo): DataView[T, V] = + def mapping[T: DataProduct, V <: Data]( + mkView: T => V, + mapping: (T, V) => Iterable[(Data, Data)] + )( + implicit sourceInfo: SourceInfo + ): DataView[T, V] = new DataView[T, V](mkView, mapping, _total = false) } diff --git a/core/src/main/scala/chisel3/experimental/dataview/package.scala b/core/src/main/scala/chisel3/experimental/dataview/package.scala index 1acf43e1..3278d82c 100644 --- a/core/src/main/scala/chisel3/experimental/dataview/package.scala +++ b/core/src/main/scala/chisel3/experimental/dataview/package.scala @@ -39,27 +39,39 @@ package object dataview { } // This private type alias lets us provide a custom error message for misuing the .viewAs for upcasting Bundles - @implicitNotFound("${A} is not a subtype of ${B}! Did you mean .viewAs[${B}]? " + - "Please see https://www.chisel-lang.org/chisel3/docs/cookbooks/dataview") + @implicitNotFound( + "${A} is not a subtype of ${B}! Did you mean .viewAs[${B}]? " + + "Please see https://www.chisel-lang.org/chisel3/docs/cookbooks/dataview" + ) private type SubTypeOf[A, B] = A <:< B /** Provides `viewAsSupertype` for subclasses of [[Bundle]] */ implicit class BundleUpcastable[T <: Bundle](target: T) { + /** View a [[Bundle]] or [[Record]] as a parent type (upcast) */ def viewAsSupertype[V <: Bundle](proto: V)(implicit ev: SubTypeOf[T, V], sourceInfo: SourceInfo): V = { - implicit val dataView = PartialDataView.mapping[T, V](_ => proto, { - case (a, b) => - val aElts = a.elements - val bElts = b.elements - val bKeys = bElts.keySet - val keys = aElts.keysIterator.filter(bKeys.contains) - keys.map(k => aElts(k) -> bElts(k)).toSeq - }) + implicit val dataView = PartialDataView.mapping[T, V]( + _ => proto, + { + case (a, b) => + val aElts = a.elements + val bElts = b.elements + val bKeys = bElts.keySet + val keys = aElts.keysIterator.filter(bKeys.contains) + keys.map(k => aElts(k) -> bElts(k)).toSeq + } + ) target.viewAs[V] } } - private def nonTotalViewException(dataView: DataView[_, _], target: Any, view: Data, targetFields: Seq[String], viewFields: Seq[String]) = { + private def nonTotalViewException( + dataView: DataView[_, _], + target: Any, + view: Data, + targetFields: Seq[String], + viewFields: Seq[String] + ) = { def missingMsg(name: String, fields: Seq[String]): Option[String] = { val str = fields.mkString(", ") fields.size match { @@ -77,18 +89,17 @@ package object dataview { } // TODO should this be moved to class Aggregate / can it be unified with Aggregate.bind? - private def doBind[T : DataProduct, V <: Data](target: T, view: V, dataView: DataView[T, V]): Unit = { + private def doBind[T: DataProduct, V <: Data](target: T, view: V, dataView: DataView[T, V]): Unit = { val mapping = dataView.mapping(target, view) val total = dataView.total // Lookups to check the mapping results val viewFieldLookup: Map[Data, String] = getRecursiveFields(view, "_").toMap - val targetContains: Data => Boolean = implicitly[DataProduct[T]].dataSet(target) + val targetContains: Data => Boolean = implicitly[DataProduct[T]].dataSet(target) // Resulting bindings for each Element of the View val childBindings = new mutable.HashMap[Data, mutable.ListBuffer[Element]] ++ - viewFieldLookup.view - .collect { case (elt: Element, _) => elt } + viewFieldLookup.view.collect { case (elt: Element, _) => elt } .map(_ -> new mutable.ListBuffer[Element]) def viewFieldName(d: Data): String = @@ -115,7 +126,9 @@ package object dataview { val fieldName = viewFieldName(vex) val vwidth = widthAsString(vex) val twidth = widthAsString(tex) - throw InvalidViewException(s"View field $fieldName has width ${vwidth} that is incompatible with target value $tex's width ${twidth}") + throw InvalidViewException( + s"View field $fieldName has width ${vwidth} that is incompatible with target value $tex's width ${twidth}" + ) } childBindings(vex) += tex } @@ -137,23 +150,24 @@ package object dataview { } // Errors in totality of the View, use var List to keep fast path cheap (no allocation) - var viewNonTotalErrors: List[Data] = Nil + var viewNonTotalErrors: List[Data] = Nil var targetNonTotalErrors: List[String] = Nil val targetSeen: Option[mutable.Set[Data]] = if (total) Some(mutable.Set.empty[Data]) else None - val resultBindings = childBindings.map { case (data, targets) => - val targetsx = targets match { - case collection.Seq(target: Element) => target - case collection.Seq() => - viewNonTotalErrors = data :: viewNonTotalErrors - data.asInstanceOf[Element] // Return the Data itself, will error after this map, cast is safe - case x => - throw InvalidViewException(s"Got $x, expected Seq(_: Direct)") - } - // TODO record and report aliasing errors - targetSeen.foreach(_ += targetsx) - data -> targetsx + val resultBindings = childBindings.map { + case (data, targets) => + val targetsx = targets match { + case collection.Seq(target: Element) => target + case collection.Seq() => + viewNonTotalErrors = data :: viewNonTotalErrors + data.asInstanceOf[Element] // Return the Data itself, will error after this map, cast is safe + case x => + throw InvalidViewException(s"Got $x, expected Seq(_: Direct)") + } + // TODO record and report aliasing errors + targetSeen.foreach(_ += targetsx) + data -> targetsx }.toMap // Check for totality of Target @@ -169,7 +183,7 @@ package object dataview { } view match { - case elt: Element => view.bind(ViewBinding(resultBindings(elt))) + case elt: Element => view.bind(ViewBinding(resultBindings(elt))) case agg: Aggregate => // We record total Data mappings to provide a better .toTarget val topt = target match { @@ -221,31 +235,31 @@ package object dataview { @tailrec private[chisel3] def reify(elt: Element, topBinding: TopBinding): Element = topBinding match { case ViewBinding(target) => reify(target, elt.topBinding) - case _ => elt + case _ => elt } - /** Determine the target of a View if it is a single Target - * - * @note An Aggregate may be a view of unrelated [[Data]] (eg. like a Seq or tuple) and thus this - * there is no single Data representing the Target and this function will return None - * @return The single Data target of this view or None if a single Data doesn't exist - */ - private[chisel3] def reifySingleData(data: Data): Option[Data] = { - val candidate: Option[Data] = - data.binding.collect { // First check if this is a total mapping of an Aggregate - case AggregateViewBinding(_, Some(t)) => t - }.orElse { // Otherwise look via top binding - data.topBindingOpt match { - case None => None - case Some(ViewBinding(target)) => Some(target) - case Some(AggregateViewBinding(lookup, _)) => lookup.get(data) - case Some(_) => None - } + /** Determine the target of a View if it is a single Target + * + * @note An Aggregate may be a view of unrelated [[Data]] (eg. like a Seq or tuple) and thus this + * there is no single Data representing the Target and this function will return None + * @return The single Data target of this view or None if a single Data doesn't exist + */ + private[chisel3] def reifySingleData(data: Data): Option[Data] = { + val candidate: Option[Data] = + data.binding.collect { // First check if this is a total mapping of an Aggregate + case AggregateViewBinding(_, Some(t)) => t + }.orElse { // Otherwise look via top binding + data.topBindingOpt match { + case None => None + case Some(ViewBinding(target)) => Some(target) + case Some(AggregateViewBinding(lookup, _)) => lookup.get(data) + case Some(_) => None } - candidate.flatMap { d => - // Candidate may itself be a view, keep tracing in those cases - if (isView(d)) reifySingleData(d) else Some(d) } + candidate.flatMap { d => + // Candidate may itself be a view, keep tracing in those cases + if (isView(d)) reifySingleData(d) else Some(d) } + } } diff --git a/core/src/main/scala/chisel3/experimental/hierarchy/Definition.scala b/core/src/main/scala/chisel3/experimental/hierarchy/Definition.scala index c7b51072..b498daf0 100644 --- a/core/src/main/scala/chisel3/experimental/hierarchy/Definition.scala +++ b/core/src/main/scala/chisel3/experimental/hierarchy/Definition.scala @@ -13,14 +13,17 @@ import chisel3.internal.BaseModule.IsClone import firrtl.annotations.{IsModule, ModuleTarget} /** User-facing Definition type. - * Represents a definition of an object of type [[A]] which are marked as @instantiable + * Represents a definition of an object of type [[A]] which are marked as @instantiable * Can be created using Definition.apply method. - * + * * These definitions are then used to create multiple [[Instance]]s. * * @param underlying The internal representation of the definition, which may be either be directly the object, or a clone of an object */ -final case class Definition[+A] private[chisel3] (private[chisel3] underlying: Underlying[A]) extends IsLookupable with SealedHierarchy[A] { +final case class Definition[+A] private[chisel3] (private[chisel3] underlying: Underlying[A]) + extends IsLookupable + with SealedHierarchy[A] { + /** Used by Chisel's internal macros. DO NOT USE in your normal Chisel code!!! * Instead, mark the field you are accessing with [[@public]] * @@ -35,14 +38,22 @@ final case class Definition[+A] private[chisel3] (private[chisel3] underlying: U * @param lookup typeclass which contains the correct lookup function, based on the types of A and B * @param macroGenerated a value created in the macro, to make it harder for users to use this API */ - def _lookup[B, C](that: A => B)(implicit lookup: Lookupable[B], macroGenerated: chisel3.internal.MacroGenerated): lookup.C = { + def _lookup[B, C]( + that: A => B + )( + implicit lookup: Lookupable[B], + macroGenerated: chisel3.internal.MacroGenerated + ): lookup.C = { lookup.definitionLookup(that, this) } /** @return the context of any Data's return from inside the instance */ private[chisel3] def getInnerDataContext: Option[BaseModule] = proto match { case value: BaseModule => - val newChild = Module.do_pseudo_apply(new internal.BaseModule.DefinitionClone(value))(chisel3.internal.sourceinfo.UnlocatableSourceInfo, chisel3.ExplicitCompileOptions.Strict) + val newChild = Module.do_pseudo_apply(new internal.BaseModule.DefinitionClone(value))( + chisel3.internal.sourceinfo.UnlocatableSourceInfo, + chisel3.ExplicitCompileOptions.Strict + ) newChild._circuit = value._circuit.orElse(Some(value)) newChild._parent = None Some(newChild) @@ -50,14 +61,14 @@ final case class Definition[+A] private[chisel3] (private[chisel3] underlying: U } override def toDefinition: Definition[A] = this - override def toInstance: Instance[A] = new Instance(underlying) - + override def toInstance: Instance[A] = new Instance(underlying) } /** Factory methods for constructing [[Definition]]s */ object Definition extends SourceInfoDoc { implicit class DefinitionBaseModuleExtensions[T <: BaseModule](d: Definition[T]) { + /** If this is an instance of a Module, returns the toTarget of this instance * @return target of this instance */ @@ -68,6 +79,7 @@ object Definition extends SourceInfoDoc { */ def toAbsoluteTarget: IsModule = d.proto.toAbsoluteTarget } + /** A construction method to build a Definition of a Module * * @param proto the Module being defined @@ -82,7 +94,12 @@ object Definition extends SourceInfoDoc { * * @return the input module as a Definition */ - def do_apply[T <: BaseModule with IsInstantiable](proto: => T) (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Definition[T] = { + def do_apply[T <: BaseModule with IsInstantiable]( + proto: => T + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Definition[T] = { val dynamicContext = new DynamicContext(Nil) Builder.globalNamespace.copyTo(dynamicContext.globalNamespace) dynamicContext.inDefinition = true diff --git a/core/src/main/scala/chisel3/experimental/hierarchy/Hierarchy.scala b/core/src/main/scala/chisel3/experimental/hierarchy/Hierarchy.scala index 503e437b..2016bb54 100644 --- a/core/src/main/scala/chisel3/experimental/hierarchy/Hierarchy.scala +++ b/core/src/main/scala/chisel3/experimental/hierarchy/Hierarchy.scala @@ -34,27 +34,27 @@ sealed trait Hierarchy[+A] { * E.g. isA[List[Int]] will return true, even if underlying proto is of type List[String] * @return Whether underlying proto is of provided type (with caveats outlined above) */ - def isA[B : TypeTag]: Boolean = { + def isA[B: TypeTag]: Boolean = { val tptag = implicitly[TypeTag[B]] - val name = tptag.tpe.toString + // drop any type information for the comparison, because the proto will not have that information. + val name = tptag.tpe.toString.takeWhile(_ != '[') inBaseClasses(name) } - // This code handles a special-case where, within an mdoc context, the type returned from // scala reflection (typetag) looks different than when returned from java reflection. // This function detects this case and reshapes the string to match. private def modifyReplString(clz: String): String = { - if(clz != null) { + if (clz != null) { clz.split('.').toList match { case "repl" :: "MdocSession" :: app :: rest => s"$app.this." + rest.mkString(".") - case other => clz + case other => clz } } else clz } private lazy val superClasses = calculateSuperClasses(proto.getClass()) private def calculateSuperClasses(clz: Class[_]): Set[String] = { - if(clz != null) { + if (clz != null) { Set(modifyReplString(clz.getCanonicalName())) ++ clz.getInterfaces().flatMap(i => calculateSuperClasses(i)) ++ calculateSuperClasses(clz.getSuperclass()) @@ -64,7 +64,6 @@ sealed trait Hierarchy[+A] { } private def inBaseClasses(clz: String): Boolean = superClasses.contains(clz) - /** Used by Chisel's internal macros. DO NOT USE in your normal Chisel code!!! * Instead, mark the field you are accessing with [[@public]] * @@ -79,7 +78,12 @@ sealed trait Hierarchy[+A] { * @param lookup typeclass which contains the correct lookup function, based on the types of A and B * @param macroGenerated a value created in the macro, to make it harder for users to use this API */ - def _lookup[B, C](that: A => B)(implicit lookup: Lookupable[B], macroGenerated: chisel3.internal.MacroGenerated): lookup.C + def _lookup[B, C]( + that: A => B + )( + implicit lookup: Lookupable[B], + macroGenerated: chisel3.internal.MacroGenerated + ): lookup.C /** @return Return the underlying Definition[A] of this Hierarchy[A] */ def toDefinition: Definition[A] @@ -93,6 +97,7 @@ private[chisel3] trait SealedHierarchy[+A] extends Hierarchy[A] object Hierarchy { implicit class HierarchyBaseModuleExtensions[T <: BaseModule](i: Hierarchy[T]) { + /** Returns the toTarget of this hierarchy * @return target of this hierarchy */ diff --git a/core/src/main/scala/chisel3/experimental/hierarchy/Instance.scala b/core/src/main/scala/chisel3/experimental/hierarchy/Instance.scala index 97b62c23..cc926771 100644 --- a/core/src/main/scala/chisel3/experimental/hierarchy/Instance.scala +++ b/core/src/main/scala/chisel3/experimental/hierarchy/Instance.scala @@ -11,12 +11,12 @@ import chisel3.experimental.BaseModule import firrtl.annotations.IsModule /** User-facing Instance type. - * Represents a unique instance of type [[A]] which are marked as @instantiable + * Represents a unique instance of type [[A]] which are marked as @instantiable * Can be created using Instance.apply method. * * @param underlying The internal representation of the instance, which may be either be directly the object, or a clone of an object */ -final case class Instance[+A] private [chisel3] (private[chisel3] underlying: Underlying[A]) extends SealedHierarchy[A] { +final case class Instance[+A] private[chisel3] (private[chisel3] underlying: Underlying[A]) extends SealedHierarchy[A] { underlying match { case Proto(p: IsClone[_]) => chisel3.internal.throwException("Cannot have a Proto with a clone!") case other => //Ok @@ -24,16 +24,16 @@ final case class Instance[+A] private [chisel3] (private[chisel3] underlying: Un /** @return the context of any Data's return from inside the instance */ private[chisel3] def getInnerDataContext: Option[BaseModule] = underlying match { - case Proto(value: BaseModule) => Some(value) - case Proto(value: IsInstantiable) => None - case Clone(i: BaseModule) => Some(i) + case Proto(value: BaseModule) => Some(value) + case Proto(value: IsInstantiable) => None + case Clone(i: BaseModule) => Some(i) case Clone(i: InstantiableClone[_]) => i.getInnerContext } /** @return the context this instance. Note that for non-module clones, getInnerDataContext will be the same as getClonedParent */ private[chisel3] def getClonedParent: Option[BaseModule] = underlying match { case Proto(value: BaseModule) => value._parent - case Clone(i: BaseModule) => i._parent + case Clone(i: BaseModule) => i._parent case Clone(i: InstantiableClone[_]) => i.getInnerContext } @@ -51,19 +51,25 @@ final case class Instance[+A] private [chisel3] (private[chisel3] underlying: Un * @param lookup typeclass which contains the correct lookup function, based on the types of A and B * @param macroGenerated a value created in the macro, to make it harder for users to use this API */ - def _lookup[B, C](that: A => B)(implicit lookup: Lookupable[B], macroGenerated: chisel3.internal.MacroGenerated): lookup.C = { + def _lookup[B, C]( + that: A => B + )( + implicit lookup: Lookupable[B], + macroGenerated: chisel3.internal.MacroGenerated + ): lookup.C = { lookup.instanceLookup(that, this) } /** Returns the definition of this Instance */ override def toDefinition: Definition[A] = new Definition(Proto(proto)) - override def toInstance: Instance[A] = this + override def toInstance: Instance[A] = this } /** Factory methods for constructing [[Instance]]s */ object Instance extends SourceInfoDoc { implicit class InstanceBaseModuleExtensions[T <: BaseModule](i: Instance[T]) { + /** If this is an instance of a Module, returns the toTarget of this instance * @return target of this instance */ @@ -81,19 +87,26 @@ object Instance extends SourceInfoDoc { } } + /** A constructs an [[Instance]] from a [[Definition]] * * @param definition the Module being created * @return an instance of the module definition */ - def apply[T <: BaseModule with IsInstantiable](definition: Definition[T]): Instance[T] = macro InstanceTransform.apply[T] + def apply[T <: BaseModule with IsInstantiable](definition: Definition[T]): Instance[T] = + macro InstanceTransform.apply[T] /** A constructs an [[Instance]] from a [[Definition]] * * @param definition the Module being created * @return an instance of the module definition */ - def do_apply[T <: BaseModule with IsInstantiable](definition: Definition[T])(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Instance[T] = { + def do_apply[T <: BaseModule with IsInstantiable]( + definition: Definition[T] + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Instance[T] = { val ports = experimental.CloneModuleAsRecord(definition.proto) val clone = ports._parent.get.asInstanceOf[ModuleClone[T]] clone._madeFromDefinition = true diff --git a/core/src/main/scala/chisel3/experimental/hierarchy/IsInstantiable.scala b/core/src/main/scala/chisel3/experimental/hierarchy/IsInstantiable.scala index 4f3c2d42..27e06d92 100644 --- a/core/src/main/scala/chisel3/experimental/hierarchy/IsInstantiable.scala +++ b/core/src/main/scala/chisel3/experimental/hierarchy/IsInstantiable.scala @@ -6,7 +6,6 @@ package chisel3.experimental.hierarchy * Instead, use the [[@instantiable]] annotation on your trait or class. * * This trait indicates whether a class can be returned from an Instance. - * */ trait IsInstantiable diff --git a/core/src/main/scala/chisel3/experimental/hierarchy/IsLookupable.scala b/core/src/main/scala/chisel3/experimental/hierarchy/IsLookupable.scala index 37d29a43..a82cbd7d 100644 --- a/core/src/main/scala/chisel3/experimental/hierarchy/IsLookupable.scala +++ b/core/src/main/scala/chisel3/experimental/hierarchy/IsLookupable.scala @@ -4,9 +4,9 @@ package chisel3.experimental.hierarchy /** A User-extendable trait to mark metadata-containers, e.g. parameter case classes, as valid to return unchanged * from an instance. - * + * * This should only be true of the metadata returned is identical for ALL instances! - * + * * @example For instances of the same proto, metadata or other construction parameters * may be useful to access outside of the instance construction. For parameters that are * the same for all instances, we should mark it as IsLookupable diff --git a/core/src/main/scala/chisel3/experimental/hierarchy/LibraryHooks.scala b/core/src/main/scala/chisel3/experimental/hierarchy/LibraryHooks.scala index c16cc633..d4818f63 100644 --- a/core/src/main/scala/chisel3/experimental/hierarchy/LibraryHooks.scala +++ b/core/src/main/scala/chisel3/experimental/hierarchy/LibraryHooks.scala @@ -16,9 +16,12 @@ object LibraryHooks { * definition's Underlying * @note Implicitly requires being inside a Hierarchy Library Extension */ - def buildInstance[A](definition: Definition[A], - createUnderlying: Underlying[A] => Underlying[A] - )(implicit inside: InsideHierarchyLibraryExtension): Instance[A] = { + def buildInstance[A]( + definition: Definition[A], + createUnderlying: Underlying[A] => Underlying[A] + )( + implicit inside: InsideHierarchyLibraryExtension + ): Instance[A] = { new Instance(createUnderlying(definition.underlying)) } diff --git a/core/src/main/scala/chisel3/experimental/hierarchy/Lookupable.scala b/core/src/main/scala/chisel3/experimental/hierarchy/Lookupable.scala index ff4d676c..8552267a 100644 --- a/core/src/main/scala/chisel3/experimental/hierarchy/Lookupable.scala +++ b/core/src/main/scala/chisel3/experimental/hierarchy/Lookupable.scala @@ -11,18 +11,20 @@ import scala.collection.mutable.HashMap import chisel3._ import chisel3.experimental.dataview.{isView, reify, reifySingleData} import chisel3.internal.firrtl.{Arg, ILit, Index, Slot, ULit} -import chisel3.internal.{AggregateViewBinding, Builder, ChildBinding, ViewBinding, ViewParent, throwException} +import chisel3.internal.{throwException, AggregateViewBinding, Builder, ChildBinding, ViewBinding, ViewParent} /** Represents lookup typeclass to determine how a value accessed from an original IsInstantiable * should be tweaked to return the Instance's version * Sealed. */ -@implicitNotFound("@public is only legal within a class marked @instantiable and only on vals of type" + - " Data, BaseModule, IsInstantiable, IsLookupable, or Instance[_], or in an Iterable or Option") +@implicitNotFound( + "@public is only legal within a class or trait marked @instantiable, and only on vals of type" + + " Data, BaseModule, IsInstantiable, IsLookupable, or Instance[_], or in an Iterable, Option, or Either" +) trait Lookupable[-B] { type C // Return type of the lookup /** Function called to modify the returned value of type B from A, into C - * + * * @param that function that selects B from A * @param instance Instance of A, used to determine C's context * @return @@ -35,8 +37,8 @@ trait Lookupable[-B] { * @param definition Definition of A, used to determine C's context * @return */ - def definitionLookup[A](that: A => B, definition: Definition[A]): C - protected def getProto[A](h: Hierarchy[A]): A = h.proto + def definitionLookup[A](that: A => B, definition: Definition[A]): C + protected def getProto[A](h: Hierarchy[A]): A = h.proto protected def getUnderlying[A](h: Hierarchy[A]): Underlying[A] = h.underlying } @@ -48,8 +50,13 @@ object Lookupable { * @param context new context * @return */ - private[chisel3] def cloneDataToContext[T <: Data](data: T, context: BaseModule) - (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T = { + private[chisel3] def cloneDataToContext[T <: Data]( + data: T, + context: BaseModule + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): T = { internal.requireIsHardware(data, "cross module reference type") data._parent match { case None => data @@ -68,11 +75,18 @@ object Lookupable { } // The business logic of lookupData // Also called by cloneViewToContext which potentially needs to lookup stuff from ioMap or the cache - private[chisel3] def doLookupData[A, B <: Data](data: B, cache: HashMap[Data, Data], ioMap: Option[Map[Data, Data]], context: Option[BaseModule]) - (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): B = { + private[chisel3] def doLookupData[A, B <: Data]( + data: B, + cache: HashMap[Data, Data], + ioMap: Option[Map[Data, Data]], + context: Option[BaseModule] + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): B = { def impl[C <: Data](d: C): C = d match { case x: Data if ioMap.nonEmpty && ioMap.get.contains(x) => ioMap.get(x).asInstanceOf[C] - case x: Data if cache.contains(x) => cache(x).asInstanceOf[C] + case x: Data if cache.contains(x) => cache(x).asInstanceOf[C] case _ => assert(context.nonEmpty) // TODO is this even possible? Better error message here val ret = cloneDataToContext(d, context.get) @@ -105,12 +119,13 @@ object Lookupable { * Invariants that elt is a Child of something of the type of data is dynamically checked as we traverse */ private def mapRootAndExtractSubField[A <: Data](arg: A, f: Data => Data): A = { - def err(msg: String) = throwException(s"Internal Error! $msg") + def err(msg: String) = throwException(s"Internal Error! $msg") def unrollCoordinates(res: List[Arg], d: Data): (List[Arg], Data) = d.binding.get match { - case ChildBinding(parent) => d.getRef match { - case arg @ (_: Slot | _: Index) => unrollCoordinates(arg :: res, parent) - case other => err(s"Unroll coordinates failed for '$arg'! Unexpected arg '$other'") - } + case ChildBinding(parent) => + d.getRef match { + case arg @ (_: Slot | _: Index) => unrollCoordinates(arg :: res, parent) + case other => err(s"Unroll coordinates failed for '$arg'! Unexpected arg '$other'") + } case _ => (res, d) } def applyCoordinates(fullCoor: List[Arg], start: Data): Data = { @@ -133,15 +148,22 @@ object Lookupable { try { result.asInstanceOf[A] } catch { - case _: ClassCastException => err(s"Applying '$coor' to '$newRoot' somehow resulted in '$result'") + case _: ClassCastException => err(s"Applying '$coor' to '$newRoot' somehow resulted in '$result'") } } // TODO this logic is complicated, can any of it be unified with viewAs? // If `.viewAs` would capture its arguments, we could potentially use it // TODO Describe what this is doing at a high level - private[chisel3] def cloneViewToContext[A, B <: Data](data: B, cache: HashMap[Data, Data], ioMap: Option[Map[Data, Data]], context: Option[BaseModule]) - (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): B = { + private[chisel3] def cloneViewToContext[A, B <: Data]( + data: B, + cache: HashMap[Data, Data], + ioMap: Option[Map[Data, Data]], + context: Option[BaseModule] + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): B = { // alias to shorten lookups def lookupData[C <: Data](d: C) = doLookupData(d, cache, ioMap, context) @@ -150,29 +172,31 @@ object Lookupable { // We have to lookup the target(s) of the view since they may need to be underlying into the current context val newBinding = data.topBinding match { case ViewBinding(target) => ViewBinding(lookupData(reify(target))) - case avb @ AggregateViewBinding(map, targetOpt) => data match { - case _: Element => ViewBinding(lookupData(reify(map(data)))) - case _: Aggregate => - // Provide a 1:1 mapping if possible - val singleTargetOpt = targetOpt.filter(_ => avb == data.binding.get).flatMap(reifySingleData) - singleTargetOpt match { - case Some(singleTarget) => // It is 1:1! - // This is a little tricky because the values in newMap need to point to Elements of newTarget - val newTarget = lookupData(singleTarget) - val newMap = coiterate(result, data).map { case (res, from) => - (res: Data) -> mapRootAndExtractSubField(map(from), _ => newTarget) - }.toMap - AggregateViewBinding(newMap, Some(newTarget)) + case avb @ AggregateViewBinding(map, targetOpt) => + data match { + case _: Element => ViewBinding(lookupData(reify(map(data)))) + case _: Aggregate => + // Provide a 1:1 mapping if possible + val singleTargetOpt = targetOpt.filter(_ => avb == data.binding.get).flatMap(reifySingleData) + singleTargetOpt match { + case Some(singleTarget) => // It is 1:1! + // This is a little tricky because the values in newMap need to point to Elements of newTarget + val newTarget = lookupData(singleTarget) + val newMap = coiterate(result, data).map { + case (res, from) => + (res: Data) -> mapRootAndExtractSubField(map(from), _ => newTarget) + }.toMap + AggregateViewBinding(newMap, Some(newTarget)) - case None => // No 1:1 mapping so we have to do a flat binding - // Just remap each Element of this aggregate - val newMap = coiterate(result, data).map { - // Upcast res to Data since Maps are invariant in the Key type parameter - case (res, from) => (res: Data) -> lookupData(reify(map(from))) - }.toMap - AggregateViewBinding(newMap, None) - } - } + case None => // No 1:1 mapping so we have to do a flat binding + // Just remap each Element of this aggregate + val newMap = coiterate(result, data).map { + // Upcast res to Data since Maps are invariant in the Key type parameter + case (res, from) => (res: Data) -> lookupData(reify(map(from))) + }.toMap + AggregateViewBinding(newMap, None) + } + } } // TODO Unify the following with `.viewAs` @@ -188,7 +212,7 @@ object Lookupable { case (agg: Aggregate, _) if agg != result => Builder.unnamedViews += agg case _ => // Do nothing - } + } } result.bind(newBinding) @@ -196,6 +220,7 @@ object Lookupable { result.forceName(None, "view", Builder.viewNamespace) result } + /** Given a module (either original or a clone), clone it to a new context * * This function effectively recurses up the parents of module to find whether: @@ -208,8 +233,13 @@ object Lookupable { * @param context new context * @return original or clone in the new context */ - private[chisel3] def cloneModuleToContext[T <: BaseModule](module: Underlying[T], context: BaseModule) - (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Underlying[T] = { + private[chisel3] def cloneModuleToContext[T <: BaseModule]( + module: Underlying[T], + context: BaseModule + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Underlying[T] = { // Recursive call def rec[A <: BaseModule](m: A): Underlying[A] = { def clone(x: A, p: Option[BaseModule], name: () => String): Underlying[A] = { @@ -221,7 +251,7 @@ object Lookupable { case (c, ctx) if ctx == c => Proto(c) case (c, ctx: IsClone[_]) if ctx.hasSameProto(c) => Clone(ctx.asInstanceOf[IsClone[A]]) case (c, ctx) if c._parent.isEmpty => Proto(c) - case (_, _) => + case (_, _) => cloneModuleToContext(Proto(m._parent.get), context) match { case Proto(p) => Proto(m) case Clone(p: BaseModule) => @@ -254,93 +284,128 @@ object Lookupable { type B = X type C = X def definitionLookup[A](that: A => B, definition: Definition[A]): C = that(definition.proto) - def instanceLookup[A](that: A => B, instance: Instance[A]): C = that(instance.proto) + def instanceLookup[A](that: A => B, instance: Instance[A]): C = that(instance.proto) } - implicit def lookupInstance[B <: BaseModule](implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) = new Lookupable[Instance[B]] { - type C = Instance[B] - def definitionLookup[A](that: A => Instance[B], definition: Definition[A]): C = { - val ret = that(definition.proto) - new Instance(cloneModuleToContext(ret.underlying, definition.getInnerDataContext.get)) - } - def instanceLookup[A](that: A => Instance[B], instance: Instance[A]): C = { - val ret = that(instance.proto) - instance.underlying match { - // If instance is just a normal module, no changing of context is necessary - case Proto(_) => new Instance(ret.underlying) - case Clone(_) => new Instance(cloneModuleToContext(ret.underlying, instance.getInnerDataContext.get)) + implicit def lookupInstance[B <: BaseModule](implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) = + new Lookupable[Instance[B]] { + type C = Instance[B] + def definitionLookup[A](that: A => Instance[B], definition: Definition[A]): C = { + val ret = that(definition.proto) + new Instance(cloneModuleToContext(ret.underlying, definition.getInnerDataContext.get)) } - } - } - - implicit def lookupModule[B <: BaseModule](implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) = new Lookupable[B] { - type C = Instance[B] - def definitionLookup[A](that: A => B, definition: Definition[A]): C = { - val ret = that(definition.proto) - new Instance(cloneModuleToContext(Proto(ret), definition.getInnerDataContext.get)) - } - def instanceLookup[A](that: A => B, instance: Instance[A]): C = { - val ret = that(instance.proto) - instance.underlying match { - // If instance is just a normal module, no changing of context is necessary - case Proto(_) => new Instance(Proto(ret)) - case Clone(_) => new Instance(cloneModuleToContext(Proto(ret), instance.getInnerDataContext.get)) + def instanceLookup[A](that: A => Instance[B], instance: Instance[A]): C = { + val ret = that(instance.proto) + instance.underlying match { + // If instance is just a normal module, no changing of context is necessary + case Proto(_) => new Instance(ret.underlying) + case Clone(_) => new Instance(cloneModuleToContext(ret.underlying, instance.getInnerDataContext.get)) + } } } - } - implicit def lookupData[B <: Data](implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) = new Lookupable[B] { - type C = B - def definitionLookup[A](that: A => B, definition: Definition[A]): C = { - val ret = that(definition.proto) - if (isView(ret)) { - ??? // TODO!!!!!! cloneViewToContext(ret, instance, ioMap, instance.getInnerDataContext) - } else { - doLookupData(ret, definition.cache, None, definition.getInnerDataContext) + implicit def lookupModule[B <: BaseModule](implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) = + new Lookupable[B] { + type C = Instance[B] + def definitionLookup[A](that: A => B, definition: Definition[A]): C = { + val ret = that(definition.proto) + new Instance(cloneModuleToContext(Proto(ret), definition.getInnerDataContext.get)) } - } - def instanceLookup[A](that: A => B, instance: Instance[A]): C = { - val ret = that(instance.proto) - val ioMap: Option[Map[Data, Data]] = instance.underlying match { - case Clone(x: ModuleClone[_]) => Some(x.ioMap) - case Proto(x: BaseModule) => Some(x.getChiselPorts.map { case (_, data) => data -> data }.toMap) - case _ => None + def instanceLookup[A](that: A => B, instance: Instance[A]): C = { + val ret = that(instance.proto) + instance.underlying match { + // If instance is just a normal module, no changing of context is necessary + case Proto(_) => new Instance(Proto(ret)) + case Clone(_) => new Instance(cloneModuleToContext(Proto(ret), instance.getInnerDataContext.get)) + } } - if (isView(ret)) { - cloneViewToContext(ret, instance.cache, ioMap, instance.getInnerDataContext) - } else { - doLookupData(ret, instance.cache, ioMap, instance.getInnerDataContext) + } + + implicit def lookupData[B <: Data](implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) = + new Lookupable[B] { + type C = B + def definitionLookup[A](that: A => B, definition: Definition[A]): C = { + val ret = that(definition.proto) + if (isView(ret)) { + ??? // TODO!!!!!! cloneViewToContext(ret, instance, ioMap, instance.getInnerDataContext) + } else { + doLookupData(ret, definition.cache, None, definition.getInnerDataContext) + } } + def instanceLookup[A](that: A => B, instance: Instance[A]): C = { + val ret = that(instance.proto) + val ioMap: Option[Map[Data, Data]] = instance.underlying match { + case Clone(x: ModuleClone[_]) => Some(x.ioMap) + case Proto(x: BaseModule) => Some(x.getChiselPorts.map { case (_, data) => data -> data }.toMap) + case _ => None + } + if (isView(ret)) { + cloneViewToContext(ret, instance.cache, ioMap, instance.getInnerDataContext) + } else { + doLookupData(ret, instance.cache, ioMap, instance.getInnerDataContext) + } + } } - } import scala.language.higherKinds // Required to avoid warning for lookupIterable type parameter - implicit def lookupIterable[B, F[_] <: Iterable[_]](implicit sourceInfo: SourceInfo, compileOptions: CompileOptions, lookupable: Lookupable[B]) = new Lookupable[F[B]] { + implicit def lookupIterable[B, F[_] <: Iterable[_]]( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions, + lookupable: Lookupable[B] + ) = new Lookupable[F[B]] { type C = F[lookupable.C] def definitionLookup[A](that: A => F[B], definition: Definition[A]): C = { val ret = that(definition.proto).asInstanceOf[Iterable[B]] - ret.map{ x: B => lookupable.definitionLookup[A](_ => x, definition) }.asInstanceOf[C] + ret.map { x: B => lookupable.definitionLookup[A](_ => x, definition) }.asInstanceOf[C] } def instanceLookup[A](that: A => F[B], instance: Instance[A]): C = { import instance._ val ret = that(proto).asInstanceOf[Iterable[B]] - ret.map{ x: B => lookupable.instanceLookup[A](_ => x, instance) }.asInstanceOf[C] + ret.map { x: B => lookupable.instanceLookup[A](_ => x, instance) }.asInstanceOf[C] } } - implicit def lookupOption[B](implicit sourceInfo: SourceInfo, compileOptions: CompileOptions, lookupable: Lookupable[B]) = new Lookupable[Option[B]] { + implicit def lookupOption[B]( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions, + lookupable: Lookupable[B] + ) = new Lookupable[Option[B]] { type C = Option[lookupable.C] def definitionLookup[A](that: A => Option[B], definition: Definition[A]): C = { val ret = that(definition.proto) - ret.map{ x: B => lookupable.definitionLookup[A](_ => x, definition) } + ret.map { x: B => lookupable.definitionLookup[A](_ => x, definition) } } def instanceLookup[A](that: A => Option[B], instance: Instance[A]): C = { import instance._ val ret = that(proto) - ret.map{ x: B => lookupable.instanceLookup[A](_ => x, instance) } + ret.map { x: B => lookupable.instanceLookup[A](_ => x, instance) } } } - implicit def lookupIsInstantiable[B <: IsInstantiable](implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) = new Lookupable[B] { + implicit def lookupEither[L, R]( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions, + lookupableL: Lookupable[L], + lookupableR: Lookupable[R] + ) = new Lookupable[Either[L, R]] { + type C = Either[lookupableL.C, lookupableR.C] + def definitionLookup[A](that: A => Either[L, R], definition: Definition[A]): C = { + val ret = that(definition.proto) + ret.map { x: R => lookupableR.definitionLookup[A](_ => x, definition) }.left.map { x: L => + lookupableL.definitionLookup[A](_ => x, definition) + } + } + def instanceLookup[A](that: A => Either[L, R], instance: Instance[A]): C = { + import instance._ + val ret = that(proto) + ret.map { x: R => lookupableR.instanceLookup[A](_ => x, instance) }.left.map { x: L => + lookupableL.instanceLookup[A](_ => x, instance) + } + } + } + implicit def lookupIsInstantiable[B <: IsInstantiable]( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ) = new Lookupable[B] { type C = Instance[B] def definitionLookup[A](that: A => B, definition: Definition[A]): C = { val ret = that(definition.proto) @@ -360,8 +425,9 @@ object Lookupable { } } - implicit def lookupIsLookupable[B <: IsLookupable](implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) = new SimpleLookupable[B]() - + implicit def lookupIsLookupable[B <: IsLookupable](implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) = + new SimpleLookupable[B]() + implicit val lookupInt = new SimpleLookupable[Int]() implicit val lookupByte = new SimpleLookupable[Byte]() implicit val lookupShort = new SimpleLookupable[Short]() diff --git a/core/src/main/scala/chisel3/experimental/package.scala b/core/src/main/scala/chisel3/experimental/package.scala index 5397a1c3..ce258a25 100644 --- a/core/src/main/scala/chisel3/experimental/package.scala +++ b/core/src/main/scala/chisel3/experimental/package.scala @@ -16,9 +16,9 @@ package object experimental { import chisel3.internal.BaseModule // Implicit conversions for BlackBox Parameters - implicit def fromIntToIntParam(x: Int): IntParam = IntParam(BigInt(x)) - implicit def fromLongToIntParam(x: Long): IntParam = IntParam(BigInt(x)) - implicit def fromBigIntToIntParam(x: BigInt): IntParam = IntParam(x) + implicit def fromIntToIntParam(x: Int): IntParam = IntParam(BigInt(x)) + implicit def fromLongToIntParam(x: Long): IntParam = IntParam(BigInt(x)) + implicit def fromBigIntToIntParam(x: BigInt): IntParam = IntParam(x) implicit def fromDoubleToDoubleParam(x: Double): DoubleParam = DoubleParam(x) implicit def fromStringToStringParam(x: String): StringParam = StringParam(x) @@ -32,6 +32,7 @@ package object experimental { type ClonePorts = BaseModule.ClonePorts object CloneModuleAsRecord { + /** Clones an existing module and returns a record of all its top-level ports. * Each element of the record is named with a string matching the * corresponding port's name and shares the port's type. @@ -41,13 +42,18 @@ package object experimental { * q2_io.enq <> q1.io.deq * }}} */ - def apply(proto: BaseModule)(implicit sourceInfo: chisel3.internal.sourceinfo.SourceInfo, compileOptions: CompileOptions): ClonePorts = { + def apply( + proto: BaseModule + )( + implicit sourceInfo: chisel3.internal.sourceinfo.SourceInfo, + compileOptions: CompileOptions + ): ClonePorts = { BaseModule.cloneIORecord(proto) } } val requireIsHardware = chisel3.internal.requireIsHardware - val requireIsChiselType = chisel3.internal.requireIsChiselType + val requireIsChiselType = chisel3.internal.requireIsChiselType type Direction = ActualDirection val Direction = ActualDirection @@ -68,6 +74,7 @@ package object experimental { class dump extends chisel3.internal.naming.dump class treedump extends chisel3.internal.naming.treedump + /** Experimental macro for naming Chisel hardware values * * By default, Chisel uses reflection for naming which only works for public fields of `Bundle` @@ -94,6 +101,7 @@ package object experimental { * }}} */ class chiselName extends chisel3.internal.naming.chiselName + /** Do not name instances of this type in [[chiselName]] * * By default, `chiselName` will include `val` names of instances of annotated classes as a @@ -138,6 +146,7 @@ package object experimental { */ object VecLiterals { implicit class AddVecLiteralConstructor[T <: Data](x: Vec[T]) { + /** Given a generator of a list tuples of the form [Int, Data] * constructs a Vec literal, parallel concept to `BundleLiteral` * @@ -150,15 +159,16 @@ package object experimental { } implicit class AddObjectLiteralConstructor(x: Vec.type) { + /** This provides an literal construction method for cases using * object `Vec` as in `Vec.Lit(1.U, 2.U)` */ def Lit[T <: Data](elems: T*)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Vec[T] = { require(elems.nonEmpty, s"Lit.Vec(...) must have at least one element") - val indexElements = elems.zipWithIndex.map { case (element, index) => (index, element)} + val indexElements = elems.zipWithIndex.map { case (element, index) => (index, element) } val widestElement = elems.maxBy(_.getWidth) val vec: Vec[T] = Vec.apply(indexElements.length, chiselTypeOf(widestElement)) - vec.Lit(indexElements:_*) + vec.Lit(indexElements: _*) } } } @@ -178,7 +188,7 @@ package object experimental { */ final class HWTuple2[+A <: Data, +B <: Data] private[chisel3] (val _1: A, val _2: B) extends Bundle()(Strict) { // Because this implementation exists in chisel3.core, it cannot compile with the plugin, so we implement the behavior manually - override protected def _usingPlugin: Boolean = true + override protected def _usingPlugin: Boolean = true override protected def _cloneTypeImpl: Bundle = new HWTuple2(chiselTypeClone(_1), chiselTypeClone(_2)) } @@ -188,12 +198,16 @@ package object experimental { * `chisel3.experimental.conversions` */ final class HWTuple3[+A <: Data, +B <: Data, +C <: Data] private[chisel3] ( - val _1: A, val _2: B, val _3: C - ) extends Bundle()(Strict) { + val _1: A, + val _2: B, + val _3: C) + extends Bundle()(Strict) { // Because this implementation exists in chisel3.core, it cannot compile with the plugin, so we implement the behavior manually override protected def _usingPlugin: Boolean = true override protected def _cloneTypeImpl: Bundle = new HWTuple3( - chiselTypeClone(_1), chiselTypeClone(_2), chiselTypeClone(_3) + chiselTypeClone(_1), + chiselTypeClone(_2), + chiselTypeClone(_3) ) } @@ -203,12 +217,18 @@ package object experimental { * `chisel3.experimental.conversions` */ final class HWTuple4[+A <: Data, +B <: Data, +C <: Data, +D <: Data] private[chisel3] ( - val _1: A, val _2: B, val _3: C, val _4: D - ) extends Bundle()(Strict) { + val _1: A, + val _2: B, + val _3: C, + val _4: D) + extends Bundle()(Strict) { // Because this implementation exists in chisel3.core, it cannot compile with the plugin, so we implement the behavior manually override protected def _usingPlugin: Boolean = true override protected def _cloneTypeImpl: Bundle = new HWTuple4( - chiselTypeClone(_1), chiselTypeClone(_2), chiselTypeClone(_3), chiselTypeClone(_4) + chiselTypeClone(_1), + chiselTypeClone(_2), + chiselTypeClone(_3), + chiselTypeClone(_4) ) } @@ -218,12 +238,20 @@ package object experimental { * `chisel3.experimental.conversions` */ final class HWTuple5[+A <: Data, +B <: Data, +C <: Data, +D <: Data, +E <: Data] private[chisel3] ( - val _1: A, val _2: B, val _3: C, val _4: D, val _5: E - ) extends Bundle()(Strict) { + val _1: A, + val _2: B, + val _3: C, + val _4: D, + val _5: E) + extends Bundle()(Strict) { // Because this implementation exists in chisel3.core, it cannot compile with the plugin, so we implement the behavior manually override protected def _usingPlugin: Boolean = true override protected def _cloneTypeImpl: Bundle = new HWTuple5( - chiselTypeClone(_1), chiselTypeClone(_2), chiselTypeClone(_3), chiselTypeClone(_4), chiselTypeClone(_5) + chiselTypeClone(_1), + chiselTypeClone(_2), + chiselTypeClone(_3), + chiselTypeClone(_4), + chiselTypeClone(_5) ) } @@ -233,12 +261,21 @@ package object experimental { * `chisel3.experimental.conversions` */ final class HWTuple6[+A <: Data, +B <: Data, +C <: Data, +D <: Data, +E <: Data, +F <: Data] private[chisel3] ( - val _1: A, val _2: B, val _3: C, val _4: D, val _5: E, val _6: F - ) extends Bundle()(Strict) { + val _1: A, + val _2: B, + val _3: C, + val _4: D, + val _5: E, + val _6: F) + extends Bundle()(Strict) { // Because this implementation exists in chisel3.core, it cannot compile with the plugin, so we implement the behavior manually override protected def _usingPlugin: Boolean = true override protected def _cloneTypeImpl: Bundle = new HWTuple6( - chiselTypeClone(_1), chiselTypeClone(_2), chiselTypeClone(_3), chiselTypeClone(_4), chiselTypeClone(_5), + chiselTypeClone(_1), + chiselTypeClone(_2), + chiselTypeClone(_3), + chiselTypeClone(_4), + chiselTypeClone(_5), chiselTypeClone(_6) ) } @@ -248,14 +285,33 @@ package object experimental { * Users may not instantiate this class directly. Instead they should use the implicit conversion from `Tuple7` in * `chisel3.experimental.conversions` */ - final class HWTuple7[+A <: Data, +B <: Data, +C <: Data, +D <: Data, +E <: Data, +F <: Data, +G <: Data] private[chisel3] ( - val _1: A, val _2: B, val _3: C, val _4: D, val _5: E, val _6: F, val _7: G - ) extends Bundle()(Strict) { + final class HWTuple7[ + +A <: Data, + +B <: Data, + +C <: Data, + +D <: Data, + +E <: Data, + +F <: Data, + +G <: Data + ] private[chisel3] ( + val _1: A, + val _2: B, + val _3: C, + val _4: D, + val _5: E, + val _6: F, + val _7: G) + extends Bundle()(Strict) { // Because this implementation exists in chisel3.core, it cannot compile with the plugin, so we implement the behavior manually override protected def _usingPlugin: Boolean = true override protected def _cloneTypeImpl: Bundle = new HWTuple7( - chiselTypeClone(_1), chiselTypeClone(_2), chiselTypeClone(_3), chiselTypeClone(_4), chiselTypeClone(_5), - chiselTypeClone(_6), chiselTypeClone(_7) + chiselTypeClone(_1), + chiselTypeClone(_2), + chiselTypeClone(_3), + chiselTypeClone(_4), + chiselTypeClone(_5), + chiselTypeClone(_6), + chiselTypeClone(_7) ) } @@ -265,15 +321,35 @@ package object experimental { * `chisel3.experimental.conversions` */ final class HWTuple8[ - +A <: Data, +B <: Data, +C <: Data, +D <: Data, +E <: Data, +F <: Data, +G <: Data, +H <: Data + +A <: Data, + +B <: Data, + +C <: Data, + +D <: Data, + +E <: Data, + +F <: Data, + +G <: Data, + +H <: Data ] private[chisel3] ( - val _1: A, val _2: B, val _3: C, val _4: D, val _5: E, val _6: F, val _7: G, val _8: H - ) extends Bundle()(Strict) { + val _1: A, + val _2: B, + val _3: C, + val _4: D, + val _5: E, + val _6: F, + val _7: G, + val _8: H) + extends Bundle()(Strict) { // Because this implementation exists in chisel3.core, it cannot compile with the plugin, so we implement the behavior manually override protected def _usingPlugin: Boolean = true override protected def _cloneTypeImpl: Bundle = new HWTuple8( - chiselTypeClone(_1), chiselTypeClone(_2), chiselTypeClone(_3), chiselTypeClone(_4), chiselTypeClone(_5), - chiselTypeClone(_6), chiselTypeClone(_7), chiselTypeClone(_8) + chiselTypeClone(_1), + chiselTypeClone(_2), + chiselTypeClone(_3), + chiselTypeClone(_4), + chiselTypeClone(_5), + chiselTypeClone(_6), + chiselTypeClone(_7), + chiselTypeClone(_8) ) } @@ -283,34 +359,82 @@ package object experimental { * `chisel3.experimental.conversions` */ final class HWTuple9[ - +A <: Data, +B <: Data, +C <: Data, +D <: Data, +E <: Data, +F <: Data, +G <: Data, +H <: Data, +I <: Data + +A <: Data, + +B <: Data, + +C <: Data, + +D <: Data, + +E <: Data, + +F <: Data, + +G <: Data, + +H <: Data, + +I <: Data ] private[chisel3] ( - val _1: A, val _2: B, val _3: C, val _4: D, val _5: E, val _6: F, val _7: G, val _8: H, val _9: I - ) extends Bundle()(Strict) { + val _1: A, + val _2: B, + val _3: C, + val _4: D, + val _5: E, + val _6: F, + val _7: G, + val _8: H, + val _9: I) + extends Bundle()(Strict) { // Because this implementation exists in chisel3.core, it cannot compile with the plugin, so we implement the behavior manually override protected def _usingPlugin: Boolean = true override protected def _cloneTypeImpl: Bundle = new HWTuple9( - chiselTypeClone(_1), chiselTypeClone(_2), chiselTypeClone(_3), chiselTypeClone(_4), chiselTypeClone(_5), - chiselTypeClone(_6), chiselTypeClone(_7), chiselTypeClone(_8), chiselTypeClone(_9) + chiselTypeClone(_1), + chiselTypeClone(_2), + chiselTypeClone(_3), + chiselTypeClone(_4), + chiselTypeClone(_5), + chiselTypeClone(_6), + chiselTypeClone(_7), + chiselTypeClone(_8), + chiselTypeClone(_9) ) } - /** [[Data]] equivalent of Scala's [[Tuple9]] * * Users may not instantiate this class directly. Instead they should use the implicit conversion from `Tuple9` in * `chisel3.experimental.conversions` */ final class HWTuple10[ - +A <: Data, +B <: Data, +C <: Data, +D <: Data, +E <: Data, +F <: Data, +G <: Data, +H <: Data, +I <: Data, +J <: Data + +A <: Data, + +B <: Data, + +C <: Data, + +D <: Data, + +E <: Data, + +F <: Data, + +G <: Data, + +H <: Data, + +I <: Data, + +J <: Data ] private[chisel3] ( - val _1: A, val _2: B, val _3: C, val _4: D, val _5: E, val _6: F, val _7: G, val _8: H, val _9: I, val _10: J - ) extends Bundle()(Strict) { + val _1: A, + val _2: B, + val _3: C, + val _4: D, + val _5: E, + val _6: F, + val _7: G, + val _8: H, + val _9: I, + val _10: J) + extends Bundle()(Strict) { // Because this implementation exists in chisel3.core, it cannot compile with the plugin, so we implement the behavior manually override protected def _usingPlugin: Boolean = true override protected def _cloneTypeImpl: Bundle = new HWTuple10( - chiselTypeClone(_1), chiselTypeClone(_2), chiselTypeClone(_3), chiselTypeClone(_4), chiselTypeClone(_5), - chiselTypeClone(_6), chiselTypeClone(_7), chiselTypeClone(_8), chiselTypeClone(_9), chiselTypeClone(_10) + chiselTypeClone(_1), + chiselTypeClone(_2), + chiselTypeClone(_3), + chiselTypeClone(_4), + chiselTypeClone(_5), + chiselTypeClone(_6), + chiselTypeClone(_7), + chiselTypeClone(_8), + chiselTypeClone(_9), + chiselTypeClone(_10) ) } } diff --git a/core/src/main/scala/chisel3/internal/BiConnect.scala b/core/src/main/scala/chisel3/internal/BiConnect.scala index aa58cb95..5b4ad1b9 100644 --- a/core/src/main/scala/chisel3/internal/BiConnect.scala +++ b/core/src/main/scala/chisel3/internal/BiConnect.scala @@ -4,7 +4,7 @@ package chisel3.internal import chisel3._ import chisel3.experimental.dataview.reify -import chisel3.experimental.{Analog, BaseModule, attach} +import chisel3.experimental.{attach, Analog, BaseModule} import chisel3.internal.Builder.pushCommand import chisel3.internal.firrtl.{Connect, DefInvalid} @@ -14,18 +14,17 @@ import chisel3.internal.sourceinfo._ import scala.annotation.tailrec /** -* 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. -* -*/ + * 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. + */ private[chisel3] object BiConnect { // These are all the possible exceptions that can be thrown. @@ -53,26 +52,32 @@ private[chisel3] object BiConnect { BiConnectException(": DontCare cannot be a connection sink (LHS)") /** 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 = { + * + * 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 = { (left, right) match { // Handle element case (root case) case (left_a: Analog, right_a: Analog) => try { markAnalogConnected(sourceInfo, left_a, context_mod) markAnalogConnected(sourceInfo, right_a, context_mod) - } catch { // convert attach exceptions to BiConnectExceptions + } catch { // convert attach exceptions to BiConnectExceptions case attach.AttachException(message) => throw BiConnectException(message) } attach.impl(Seq(left_a, right_a), context_mod)(sourceInfo) case (left_a: Analog, DontCare) => try { markAnalogConnected(sourceInfo, left_a, context_mod) - } catch { // convert attach exceptions to BiConnectExceptions + } catch { // convert attach exceptions to BiConnectExceptions case attach.AttachException(message) => throw BiConnectException(message) } pushCommand(DefInvalid(sourceInfo, left_a.lref)) @@ -82,7 +87,7 @@ private[chisel3] object BiConnect { // TODO(twigg): Verify the element-level classes are connectable } // Handle Vec case - case (left_v: Vec[Data@unchecked], right_v: Vec[Data@unchecked]) => { + case (left_v: Vec[Data @unchecked], right_v: Vec[Data @unchecked]) => { if (left_v.length != right_v.length) { throw MismatchedVecException } @@ -96,7 +101,7 @@ private[chisel3] object BiConnect { } } // Handle Vec connected to DontCare - case (left_v: Vec[Data@unchecked], DontCare) => { + case (left_v: Vec[Data @unchecked], DontCare) => { for (idx <- 0 until left_v.length) { try { implicit val compileOptions = connectCompileOptions @@ -107,7 +112,7 @@ private[chisel3] object BiConnect { } } // Handle DontCare connected to Vec - case (DontCare, right_v: Vec[Data@unchecked]) => { + case (DontCare, right_v: Vec[Data @unchecked]) => { for (idx <- 0 until right_v.length) { try { implicit val compileOptions = connectCompileOptions @@ -135,7 +140,7 @@ private[chisel3] object BiConnect { case _ => true } } - def canBeSink(data: Data): Boolean = traceFlow(true, data) + def canBeSink(data: Data): Boolean = traceFlow(true, data) def canBeSource(data: Data): Boolean = traceFlow(false, data) // chisel3 <> is commutative but FIRRTL <- is not val flipConnection = !canBeSink(left_r) || !canBeSource(right_r) @@ -181,21 +186,23 @@ private[chisel3] object BiConnect { } // Do connection of two Records - def recordConnect(sourceInfo: SourceInfo, - connectCompileOptions: CompileOptions, - left_r: Record, - right_r: Record, - context_mod: RawModule): Unit = { + 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)) { + 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) { + 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) @@ -211,7 +218,6 @@ private[chisel3] object BiConnect { } } - // 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 = { @@ -238,13 +244,19 @@ private[chisel3] object BiConnect { // This function checks if element-level connection operation allowed. // Then it either issues it or throws the appropriate exception. - def elemConnect(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions, _left: Element, _right: Element, context_mod: RawModule): Unit = { - import BindingDirection.{Internal, Input, Output} // Using extensively so import these + def elemConnect( + implicit sourceInfo: SourceInfo, + connectCompileOptions: CompileOptions, + _left: Element, + _right: Element, + context_mod: RawModule + ): Unit = { + import BindingDirection.{Input, Internal, Output} // Using extensively so import these val left = reify(_left) val right = reify(_right) // 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 left_mod: BaseModule = left.topBinding.location.getOrElse(context_mod) val right_mod: BaseModule = right.topBinding.location.getOrElse(context_mod) val left_parent = Builder.retrieveParent(left_mod, context_mod).getOrElse(None) @@ -254,54 +266,54 @@ private[chisel3] object BiConnect { 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_parent == context_mod)) { + if ((left_mod == context_mod) && (right_parent == context_mod)) { // 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 (Input, Input) => issueConnectL2R(left, right) + case (Internal, Input) => issueConnectL2R(left, right) - case (Output, Output) => issueConnectR2L(left, right) - case (Internal, Output) => issueConnectR2L(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 (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_parent == context_mod)) { + else if ((right_mod == context_mod) && (left_parent == context_mod)) { // 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 (Input, Input) => issueConnectR2L(left, right) + case (Input, Internal) => issueConnectR2L(left, right) - case (Output, Output) => issueConnectL2R(left, right) - case (Output, Internal) => issueConnectL2R(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 (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) ) { + 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 (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 (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) => { + case (Input, Input) => throw BothDriversException + case (Output, Output) => throw BothDriversException + case (Internal, Internal) => { if (connectCompileOptions.dontAssumeDirectionality) { throw UnknownDriverException } else { @@ -314,22 +326,22 @@ private[chisel3] object BiConnect { // 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_parent == context_mod) && (right_parent == context_mod)) { + else if ((left_parent == context_mod) && (right_parent == context_mod)) { // 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, Output) => issueConnectR2L(left, right) + case (Output, Input) => issueConnectL2R(left, right) - case (Input, Input) => throw NeitherDriverException - case (Output, Output) => throw BothDriversException - case (_, Internal) => + case (Input, Input) => throw NeitherDriverException + case (Output, Output) => throw BothDriversException + case (_, Internal) => if (connectCompileOptions.dontAssumeDirectionality) { throw UnknownRelationException } else { issueConnectR2L(left, right) } - case (Internal, _) => + case (Internal, _) => if (connectCompileOptions.dontAssumeDirectionality) { throw UnknownRelationException } else { @@ -347,7 +359,7 @@ private[chisel3] object BiConnect { def markAnalogConnected(implicit sourceInfo: SourceInfo, analog: Analog, contextModule: RawModule): Unit = { analog.biConnectLocs.get(contextModule) match { case Some(sl) => throw AttachAlreadyBulkConnectedException(sl) - case None => // Do nothing + case None => // Do nothing } // Mark bulk connected analog.biConnectLocs(contextModule) = sourceInfo diff --git a/core/src/main/scala/chisel3/internal/Binding.scala b/core/src/main/scala/chisel3/internal/Binding.scala index a0dcc20c..6431dd23 100644 --- a/core/src/main/scala/chisel3/internal/Binding.scala +++ b/core/src/main/scala/chisel3/internal/Binding.scala @@ -12,14 +12,16 @@ import scala.collection.immutable.VectorMap */ object requireIsHardware { def apply(node: Data, msg: String = ""): Unit = { - node._parent match { // Compatibility layer hack + 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 ExpectedHardwareException(s"$prefix'$node' must be hardware, " + - "not a bare Chisel type. Perhaps you forgot to wrap it in Wire(_) or IO(_)?") + throw ExpectedHardwareException( + s"$prefix'$node' must be hardware, " + + "not a bare Chisel type. Perhaps you forgot to wrap it in Wire(_) or IO(_)?" + ) } } } @@ -36,12 +38,15 @@ object requireIsChiselType { // Element only direction used for the Binding system only. private[chisel3] sealed abstract class BindingDirection private[chisel3] 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 @@ -50,11 +55,12 @@ private[chisel3] object BindingDirection { */ 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 PortBinding(_) => + direction match { + case ActualDirection.Output => Output + case ActualDirection.Input => Input + case dir => throw new RuntimeException(s"Unexpected port element direction '$dir'") + } case _ => Internal } } @@ -81,7 +87,7 @@ sealed trait ConstrainedBinding extends TopBinding { // This allows aspect modules to pretend to be enclosed modules for connectivity checking, // inside vs outside instance checking, etc. Builder.aspectModule(enclosure) match { - case None => Some(enclosure) + case None => Some(enclosure) case Some(aspect) => Some(aspect) } } @@ -100,18 +106,29 @@ sealed trait ConditionalDeclarable extends TopBinding { case class PortBinding(enclosure: BaseModule) extends ConstrainedBinding -case class OpBinding(enclosure: RawModule, visibility: Option[WhenContext]) extends ConstrainedBinding with ReadOnlyBinding with ConditionalDeclarable -case class MemoryPortBinding(enclosure: RawModule, visibility: Option[WhenContext]) extends ConstrainedBinding with ConditionalDeclarable -case class RegBinding(enclosure: RawModule, visibility: Option[WhenContext]) extends ConstrainedBinding with ConditionalDeclarable -case class WireBinding(enclosure: RawModule, visibility: Option[WhenContext]) extends ConstrainedBinding with ConditionalDeclarable +case class OpBinding(enclosure: RawModule, visibility: Option[WhenContext]) + extends ConstrainedBinding + with ReadOnlyBinding + with ConditionalDeclarable +case class MemoryPortBinding(enclosure: RawModule, visibility: Option[WhenContext]) + extends ConstrainedBinding + with ConditionalDeclarable +case class RegBinding(enclosure: RawModule, visibility: Option[WhenContext]) + extends ConstrainedBinding + with ConditionalDeclarable +case class WireBinding(enclosure: RawModule, visibility: Option[WhenContext]) + extends ConstrainedBinding + with ConditionalDeclarable 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 } + /** Special binding for Mem types */ case class MemTypeBinding[T <: Data](parent: MemBase[T]) extends Binding { def location: Option[BaseModule] = parent._parent @@ -122,12 +139,13 @@ case class DontCareBinding() extends UnconstrainedBinding // Views currently only support 1:1 Element-level mappings private[chisel3] case class ViewBinding(target: Element) extends UnconstrainedBinding + /** Binding for Aggregate Views * @param childMap Mapping from children of this view to each child's target * @param target Optional Data this Aggregate views if the view is total and the target is a Data */ -private[chisel3] case class AggregateViewBinding(childMap: Map[Data, Element], target: Option[Data]) extends UnconstrainedBinding - +private[chisel3] case class AggregateViewBinding(childMap: Map[Data, Element], target: Option[Data]) + extends UnconstrainedBinding /** Binding for Data's returned from accessing an Instance/Definition members, if not readable/writable port */ private[chisel3] case object CrossModuleBinding extends TopBinding { diff --git a/core/src/main/scala/chisel3/internal/Builder.scala b/core/src/main/scala/chisel3/internal/Builder.scala index 71894887..fb6ebcc7 100644 --- a/core/src/main/scala/chisel3/internal/Builder.scala +++ b/core/src/main/scala/chisel3/internal/Builder.scala @@ -6,7 +6,7 @@ import scala.util.DynamicVariable import scala.collection.mutable.ArrayBuffer import chisel3._ import chisel3.experimental._ -import chisel3.experimental.hierarchy.{Instance, Clone} +import chisel3.experimental.hierarchy.{Clone, Instance} import chisel3.internal.firrtl._ import chisel3.internal.naming._ import _root_.firrtl.annotations.{CircuitName, ComponentName, IsMember, ModuleName, Named, ReferenceTarget} @@ -34,8 +34,8 @@ private[chisel3] class Namespace(keywords: Set[String]) { private def sanitize(s: String, leadingDigitOk: Boolean = false): String = { // TODO what character set does FIRRTL truly support? using ANSI C for now def legalStart(c: Char) = (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' - def legal(c: Char) = legalStart(c) || (c >= '0' && c <= '9') - val res = s filter legal + def legal(c: Char) = legalStart(c) || (c >= '0' && c <= '9') + val res = s.filter(legal) val headOk = (!res.isEmpty) && (leadingDigitOk || legalStart(res.head)) if (headOk) res else s"_$res" } @@ -55,6 +55,7 @@ private[chisel3] class Namespace(keywords: Set[String]) { } private[chisel3] object Namespace { + /** Constructs an empty Namespace */ def empty: Namespace = new Namespace(Set.empty[String]) } @@ -73,14 +74,17 @@ private[chisel3] class IdGen { * These are only valid once the design has been elaborated, and should not be used during its construction. */ trait InstanceId { - def instanceName: String - def pathName: String + def instanceName: String + def pathName: String def parentPathName: String - def parentModName: String + def parentModName: String + /** Returns a FIRRTL Named that refers to this object in the elaborated hardware graph */ def toNamed: Named + /** Returns a FIRRTL IsMember that refers to this object in the elaborated hardware graph */ def toTarget: IsMember + /** Returns a FIRRTL IsMember that refers to the absolute path to this object in the elaborated hardware graph */ def toAbsoluteTarget: IsMember } @@ -111,10 +115,10 @@ private[chisel3] trait HasId extends InstanceId { private var prefix_seed: Prefix = Nil // Post-seed hooks called to carry the suggested seeds to other candidates as needed - private val suggest_postseed_hooks = scala.collection.mutable.ListBuffer.empty[String=>Unit] + private val suggest_postseed_hooks = scala.collection.mutable.ListBuffer.empty[String => Unit] // Post-seed hooks called to carry the auto seeds to other candidates as needed - private val auto_postseed_hooks = scala.collection.mutable.ListBuffer.empty[String=>Unit] + private val auto_postseed_hooks = scala.collection.mutable.ListBuffer.empty[String => Unit] /** Takes the last seed suggested. Multiple calls to this function will take the last given seed, unless * this HasId is a module port (see overridden method in Data.scala). @@ -124,7 +128,7 @@ private[chisel3] trait HasId extends InstanceId { * * Is a lower priority than [[suggestName]], in that regardless of whether [[autoSeed]] * was called, [[suggestName]] will always take precedence if it was called. - * + * * @param seed Seed for the name of this component * @return this object */ @@ -132,7 +136,7 @@ private[chisel3] trait HasId extends InstanceId { // Bypass the overridden behavior of autoSeed in [[Data]], apply autoSeed even to ports private[chisel3] def forceAutoSeed(seed: String): this.type = { auto_seed = Some(seed) - for(hook <- auto_postseed_hooks) { hook(seed) } + for (hook <- auto_postseed_hooks) { hook(seed) } prefix_seed = Builder.getPrefix this } @@ -143,14 +147,14 @@ private[chisel3] trait HasId extends InstanceId { * * Is a higher priority than [[autoSeed]], in that regardless of whether [[autoSeed]] * was called, [[suggestName]] will always take precedence. - * + * * @param seed The seed for the name of this component * @return this object */ - def suggestName(seed: =>String): this.type = { - if(suggested_seed.isEmpty) suggested_seed = Some(seed) + def suggestName(seed: => String): this.type = { + if (suggested_seed.isEmpty) suggested_seed = Some(seed) prefix_seed = Builder.getPrefix - for(hook <- suggest_postseed_hooks) { hook(seed) } + for (hook <- suggest_postseed_hooks) { hook(seed) } this } @@ -171,6 +175,7 @@ private[chisel3] trait HasId extends InstanceId { * @return the name, if it can be computed */ private[chisel3] def _computeName(defaultPrefix: Option[String], defaultSeed: Option[String]): Option[String] = { + /** Computes a name of this signal, given the seed and prefix * @param seed * @param prefix @@ -189,14 +194,14 @@ private[chisel3] trait HasId extends InstanceId { defaultSeed.map { default => defaultPrefix match { case Some(p) => buildName(default, p :: construction_prefix.reverse) - case None => buildName(default, construction_prefix.reverse) + case None => buildName(default, construction_prefix.reverse) } } } } /** This resolves the precedence of [[autoSeed]] and [[suggestName]] - * + * * @return the current calculation of a name, if it exists */ private[chisel3] def seedOpt: Option[String] = suggested_seed.orElse(auto_seed) @@ -206,14 +211,14 @@ private[chisel3] trait HasId extends InstanceId { private[chisel3] def hasAutoSeed: Boolean = auto_seed.isDefined - private[chisel3] def addSuggestPostnameHook(hook: String=>Unit): Unit = suggest_postseed_hooks += hook - private[chisel3] def addAutoPostnameHook(hook: String=>Unit): Unit = auto_postseed_hooks += hook + private[chisel3] def addSuggestPostnameHook(hook: String => Unit): Unit = suggest_postseed_hooks += hook + private[chisel3] def addAutoPostnameHook(hook: String => Unit): Unit = auto_postseed_hooks += hook // Uses a namespace to convert suggestion into a true name // Will not do any naming if the reference already assigned. // (e.g. tried to suggest a name to part of a Record) - private[chisel3] def forceName(prefix: Option[String], default: =>String, namespace: Namespace): Unit = - if(_ref.isEmpty) { + private[chisel3] def forceName(prefix: Option[String], default: => String, namespace: Namespace): Unit = + if (_ref.isEmpty) { val candidate_name = _computeName(prefix, Some(default)).get val available_name = namespace.name(candidate_name) setRef(Ref(available_name)) @@ -226,15 +231,15 @@ private[chisel3] trait HasId extends InstanceId { _ref = Some(imm) } } - private[chisel3] def setRef(parent: HasId, name: String): Unit = setRef(Slot(Node(parent), name)) - private[chisel3] def setRef(parent: HasId, index: Int): Unit = setRef(Index(Node(parent), ILit(index))) - private[chisel3] def setRef(parent: HasId, index: UInt): Unit = setRef(Index(Node(parent), index.ref)) - private[chisel3] def getRef: Arg = _ref.get + private[chisel3] def setRef(parent: HasId, name: String): Unit = setRef(Slot(Node(parent), name)) + private[chisel3] def setRef(parent: HasId, index: Int): Unit = setRef(Index(Node(parent), ILit(index))) + private[chisel3] def setRef(parent: HasId, index: UInt): Unit = setRef(Index(Node(parent), index.ref)) + private[chisel3] def getRef: Arg = _ref.get private[chisel3] def getOptionRef: Option[Arg] = _ref private def refName(c: Component): String = _ref match { - case Some(arg) => arg fullName c - case None => _computeName(None, None).get + case Some(arg) => arg.fullName(c) + case None => _computeName(None, None).get } // Helper for reifying views if they map to a single Target @@ -253,33 +258,35 @@ private[chisel3] trait HasId extends InstanceId { (p._component, this) match { case (Some(c), _) => refName(c) case (None, d: Data) if d.topBindingOpt == Some(CrossModuleBinding) => _ref.get.localName - case (None, _) => throwException(s"signalName/pathName should be called after circuit elaboration: $this, ${_parent}") + case (None, _) => + throwException(s"signalName/pathName should be called after circuit elaboration: $this, ${_parent}") } case None => throwException("this cannot happen") } def pathName: String = _parent match { - case None => instanceName + case None => instanceName case Some(ViewParent) => s"${reifyParent.pathName}.$instanceName" - case Some(p) => s"${p.pathName}.$instanceName" + case Some(p) => s"${p.pathName}.$instanceName" } def parentPathName: String = _parent match { case Some(ViewParent) => reifyParent.pathName - case Some(p) => p.pathName - case None => throwException(s"$instanceName doesn't have a parent") + case Some(p) => p.pathName + case None => throwException(s"$instanceName doesn't have a parent") } def parentModName: String = _parent match { case Some(ViewParent) => reifyParent.name - case Some(p) => p.name - case None => throwException(s"$instanceName doesn't have a parent") + case Some(p) => p.name + case None => throwException(s"$instanceName doesn't have a parent") } // TODO Should this be public? protected def circuitName: String = _parent match { - case None => _circuit match { - case None => instanceName - case Some(o) => o.circuitName - } + case None => + _circuit match { + case None => instanceName + case Some(o) => o.circuitName + } case Some(ViewParent) => reifyParent.circuitName - case Some(p) => p.circuitName + case Some(p) => p.circuitName } private[chisel3] def getPublicFields(rootClass: Class[_]): Seq[java.lang.reflect.Method] = { @@ -302,8 +309,10 @@ private[chisel3] trait HasId extends InstanceId { this.getClass.getMethods.filter(isPublicVal).sortWith(_.getName < _.getName) } } + /** Holds the implementation of toNamed for Data and MemBase */ private[chisel3] trait NamedComponent extends HasId { + /** Returns a FIRRTL ComponentName that references this object * @note Should not be called until circuit elaboration is complete */ @@ -319,7 +328,7 @@ private[chisel3] trait NamedComponent extends HasId { import _root_.firrtl.annotations.{Target, TargetToken} val root = _parent.map { case ViewParent => reifyParent - case other => other + case other => other }.get.getTarget // All NamedComponents will have a parent, only the top module can have None here Target.toTargetTokens(name).toList match { case TargetToken.Ref(r) :: components => root.ref(r).copy(component = components) @@ -333,8 +342,8 @@ private[chisel3] trait NamedComponent extends HasId { def makeTarget(p: BaseModule) = p.toAbsoluteTarget.ref(localTarget.ref).copy(component = localTarget.component) _parent match { case Some(ViewParent) => makeTarget(reifyParent) - case Some(parent) => makeTarget(parent) - case None => localTarget + case Some(parent) => makeTarget(parent) + case None => localTarget } } } @@ -369,9 +378,9 @@ private[chisel3] class DynamicContext(val annotationSeq: AnnotationSeq) { // Set by object Module.apply before calling class Module constructor // Used to distinguish between no Module() wrapping, multiple wrappings, and rewrapping var readyForModuleConstr: Boolean = false - var whenStack: List[WhenContext] = Nil - var currentClock: Option[Clock] = None - var currentReset: Option[Reset] = None + var whenStack: List[WhenContext] = Nil + var currentClock: Option[Clock] = None + var currentReset: Option[Reset] = None val errors = new ErrorLog val namingStack = new NamingStack // Used to indicate if this is the top-level module of full elaboration, or from a Definition @@ -396,7 +405,7 @@ private[chisel3] object Builder extends LazyLogging { def restoreContext(dc: DynamicContext) = dynamicContextVar.value = Some(dc) // Ensure we have a thread-specific ChiselContext - private val chiselContext = new ThreadLocal[ChiselContext]{ + private val chiselContext = new ThreadLocal[ChiselContext] { override def initialValue: ChiselContext = { new ChiselContext } @@ -419,12 +428,12 @@ private[chisel3] object Builder extends LazyLogging { def idGen: IdGen = chiselContext.get.idGen def globalNamespace: Namespace = dynamicContext.globalNamespace - def components: ArrayBuffer[Component] = dynamicContext.components - def annotations: ArrayBuffer[ChiselAnnotation] = dynamicContext.annotations - def annotationSeq: AnnotationSeq = dynamicContext.annotationSeq - def namingStack: NamingStack = dynamicContext.namingStack + def components: ArrayBuffer[Component] = dynamicContext.components + def annotations: ArrayBuffer[ChiselAnnotation] = dynamicContext.annotations + def annotationSeq: AnnotationSeq = dynamicContext.annotationSeq + def namingStack: NamingStack = dynamicContext.namingStack - def unnamedViews: ArrayBuffer[Data] = dynamicContext.unnamedViews + def unnamedViews: ArrayBuffer[Data] = dynamicContext.unnamedViews def viewNamespace: Namespace = chiselContext.get.viewNamespace // Puts a prefix string onto the prefix stack @@ -441,8 +450,8 @@ private[chisel3] object Builder extends LazyLogging { def pushPrefix(d: HasId): Boolean = { def buildAggName(id: HasId): Option[String] = { def getSubName(field: Data): Option[String] = field.getOptionRef.flatMap { - case Slot(_, field) => Some(field) // Record - case Index(_, ILit(n)) => Some(n.toString) // Vec static indexing + case Slot(_, field) => Some(field) // Record + case Index(_, ILit(n)) => Some(n.toString) // Vec static indexing case Index(_, ULit(n, _)) => Some(n.toString) // Vec lit indexing case Index(_, _: Node) => None // Vec dynamic indexing case ModuleIO(_, n) => Some(n) // BlackBox port @@ -452,13 +461,14 @@ private[chisel3] object Builder extends LazyLogging { // If the binding is None, this is an illegal connection and later logic will error def recData(data: Data): Option[String] = data.binding.flatMap { case (_: WireBinding | _: RegBinding | _: MemoryPortBinding | _: OpBinding) => data.seedOpt - case ChildBinding(parent) => recData(parent).map { p => - // And name of the field if we have one, we don't for dynamic indexing of Vecs - getSubName(data).map(p + "_" + _).getOrElse(p) - } - case SampleElementBinding(parent) => recData(parent) + case ChildBinding(parent) => + recData(parent).map { p => + // And name of the field if we have one, we don't for dynamic indexing of Vecs + getSubName(data).map(p + "_" + _).getOrElse(p) + } + case SampleElementBinding(parent) => recData(parent) case PortBinding(mod) if Builder.currentModule.contains(mod) => data.seedOpt - case PortBinding(mod) => map2(mod.seedOpt, data.seedOpt)(_ + "_" + _) + case PortBinding(mod) => map2(mod.seedOpt, data.seedOpt)(_ + "_" + _) case (_: LitBinding | _: DontCareBinding) => None case _ => Some("view_") // TODO implement } @@ -495,30 +505,31 @@ private[chisel3] object Builder extends LazyLogging { def currentModule: Option[BaseModule] = dynamicContextVar.value match { case Some(dyanmicContext) => dynamicContext.currentModule - case _ => None + case _ => None } def currentModule_=(target: Option[BaseModule]): Unit = { dynamicContext.currentModule = target } def aspectModule(module: BaseModule): Option[BaseModule] = dynamicContextVar.value match { case Some(dynamicContext) => dynamicContext.aspectModule.get(module) - case _ => None + case _ => None } + /** Retrieves the parent of a module based on the elaboration context - * - * @param module the module to get the parent of - * @param context the context the parent should be evaluated in - * @return the parent of the module provided - */ + * + * @param module the module to get the parent of + * @param context the context the parent should be evaluated in + * @return the parent of the module provided + */ def retrieveParent(module: BaseModule, context: BaseModule): Option[BaseModule] = { module._parent match { case Some(parentModule) => { //if a parent exists investigate, otherwise return None context match { case aspect: ModuleAspect => { //if aspect context, do the translation - Builder.aspectModule(parentModule) match { - case Some(parentAspect) => Some(parentAspect) //we've found a translation - case _ => Some(parentModule) //no translation found - } + Builder.aspectModule(parentModule) match { + case Some(parentAspect) => Some(parentAspect) //we've found a translation + case _ => Some(parentModule) //no translation found + } } //otherwise just return our parent case _ => Some(parentModule) } @@ -531,10 +542,11 @@ private[chisel3] object Builder extends LazyLogging { } def forcedModule: BaseModule = currentModule match { case Some(module) => module - case None => throwException( - "Error: Not in a Module. Likely cause: Missed Module() wrap or bare chisel API call." - // A bare api call is, e.g. calling Wire() from the scala console). - ) + case None => + throwException( + "Error: Not in a Module. Likely cause: Missed Module() wrap or bare chisel API call." + // A bare api call is, e.g. calling Wire() from the scala console). + ) } def referenceUserModule: RawModule = { currentModule match { @@ -543,18 +555,20 @@ private[chisel3] object Builder extends LazyLogging { case Some(aspect: RawModule) => aspect case other => module } - case _ => throwException( - "Error: Not in a RawModule. Likely cause: Missed Module() wrap, bare chisel API call, or attempting to construct hardware inside a BlackBox." - // A bare api call is, e.g. calling Wire() from the scala console). - ) + case _ => + throwException( + "Error: Not in a RawModule. Likely cause: Missed Module() wrap, bare chisel API call, or attempting to construct hardware inside a BlackBox." + // A bare api call is, e.g. calling Wire() from the scala console). + ) } } def forcedUserModule: RawModule = currentModule match { case Some(module: RawModule) => module - case _ => throwException( - "Error: Not in a UserModule. Likely cause: Missed Module() wrap, bare chisel API call, or attempting to construct hardware inside a BlackBox." - // A bare api call is, e.g. calling Wire() from the scala console). - ) + case _ => + throwException( + "Error: Not in a UserModule. Likely cause: Missed Module() wrap, bare chisel API call, or attempting to construct hardware inside a BlackBox." + // A bare api call is, e.g. calling Wire() from the scala console). + ) } def hasDynamicContext: Boolean = dynamicContextVar.value.isDefined @@ -594,8 +608,8 @@ private[chisel3] object Builder extends LazyLogging { def inDefinition: Boolean = { dynamicContextVar.value - .map(_.inDefinition) - .getOrElse(false) + .map(_.inDefinition) + .getOrElse(false) } def forcedClock: Clock = currentClock.getOrElse( @@ -623,10 +637,11 @@ private[chisel3] object Builder extends LazyLogging { * (Note: Map is Iterable[Tuple2[_,_]] and thus excluded) */ def nameRecursively(prefix: String, nameMe: Any, namer: (HasId, String) => Unit): Unit = nameMe match { - case (id: Instance[_]) => id.underlying match { - case Clone(m: internal.BaseModule.ModuleClone[_]) => namer(m.getPorts, prefix) - case _ => - } + case (id: Instance[_]) => + id.underlying match { + case Clone(m: internal.BaseModule.ModuleClone[_]) => namer(m.getPorts, prefix) + case _ => + } case (id: HasId) => namer(id, prefix) case Some(elt) => nameRecursively(prefix, elt, namer) case (iter: Iterable[_]) if iter.hasDefiniteSize => @@ -644,7 +659,7 @@ private[chisel3] object Builder extends LazyLogging { throwException(m) } } - def warning(m: => String): Unit = if (dynamicContextVar.value.isDefined) errors.warning(m) + def warning(m: => String): Unit = if (dynamicContextVar.value.isDefined) errors.warning(m) def deprecated(m: => String, location: Option[String] = None): Unit = if (dynamicContextVar.value.isDefined) errors.deprecated(m, location) @@ -667,7 +682,7 @@ private[chisel3] object Builder extends LazyLogging { if (getScalaMajorVersion == 11) { val url = _root_.firrtl.stage.transforms.CheckScalaVersion.migrationDocumentLink val msg = s"Chisel 3.4 is the last version that will support Scala 2.11. " + - s"Please upgrade to Scala 2.12. See $url" + s"Please upgrade to Scala 2.12. See $url" deprecated(msg, Some("")) } } @@ -680,8 +695,7 @@ private[chisel3] object Builder extends LazyLogging { for (view <- unnamedViews) { val localTarget = view.toTarget val absTarget = view.toAbsoluteTarget - val elts = getRecursiveFields.lazily(view, "") - .collect { case (elt: Element, _) => elt } + val elts = getRecursiveFields.lazily(view, "").collect { case (elt: Element, _) => elt } for (elt <- elts) { val targetOfView = reify(elt) renames.record(localTarget, targetOfView.toTarget) @@ -691,10 +705,14 @@ private[chisel3] object Builder extends LazyLogging { renames } - private[chisel3] def build[T <: BaseModule](f: => T, dynamicContext: DynamicContext, forceModName: Boolean = true): (Circuit, T) = { + private[chisel3] def build[T <: BaseModule]( + f: => T, + dynamicContext: DynamicContext, + forceModName: Boolean = true + ): (Circuit, T) = { dynamicContextVar.withValue(Some(dynamicContext)) { ViewParent // Must initialize the singleton in a Builder context or weird things can happen - // in tiny designs/testcases that never access anything in chisel3.internal + // in tiny designs/testcases that never access anything in chisel3.internal checkScalaVersion() logger.info("Elaborating design...") val mod = f @@ -719,24 +737,28 @@ object DynamicNamingStack { def pushContext(): NamingContextInterface = { Builder.namingStackOption match { case Some(namingStack) => namingStack.pushContext() - case None => DummyNamer + case None => DummyNamer } } def popReturnContext[T <: Any](prefixRef: T, until: NamingContextInterface): T = { until match { case DummyNamer => - require(Builder.namingStackOption.isEmpty, - "Builder context must remain stable throughout a chiselName-annotated function invocation") + require( + Builder.namingStackOption.isEmpty, + "Builder context must remain stable throughout a chiselName-annotated function invocation" + ) case context: NamingContext => - require(Builder.namingStackOption.isDefined, - "Builder context must remain stable throughout a chiselName-annotated function invocation") + require( + Builder.namingStackOption.isDefined, + "Builder context must remain stable throughout a chiselName-annotated function invocation" + ) Builder.namingStackOption.get.popContext(prefixRef, context) } prefixRef } - def length() : Int = Builder.namingStackOption.get.length + def length(): Int = Builder.namingStackOption.get.length } /** Casts BigInt to Int, issuing an error when the input isn't representable. */ diff --git a/core/src/main/scala/chisel3/internal/Error.scala b/core/src/main/scala/chisel3/internal/Error.scala index d6e0c0e6..c42f39ed 100644 --- a/core/src/main/scala/chisel3/internal/Error.scala +++ b/core/src/main/scala/chisel3/internal/Error.scala @@ -38,7 +38,7 @@ object ExceptionHelpers { */ def trimStackTraceToUserCode( packageTrimlist: Set[String] = packageTrimlist, - anchor: Option[String] = Some(builderName) + anchor: Option[String] = Some(builderName) ): Unit = { def inTrimlist(ste: StackTraceElement) = { val packageName = ste.getClassName().takeWhile(_ != '.') @@ -47,25 +47,28 @@ object ExceptionHelpers { // Step 1: Remove elements from the top in the package trimlist ((a: Array[StackTraceElement]) => a.dropWhile(inTrimlist)) - // Step 2: Optionally remove elements from the bottom until the anchor + // Step 2: Optionally remove elements from the bottom until the anchor .andThen(_.reverse) - .andThen( a => + .andThen(a => anchor match { case Some(b) => a.dropWhile(ste => !ste.getClassName.startsWith(b)) case None => a } ) - // Step 3: Remove elements from the bottom in the package trimlist + // Step 3: Remove elements from the bottom in the package trimlist .andThen(_.dropWhile(inTrimlist)) - // Step 4: Reverse back to the original order + // Step 4: Reverse back to the original order .andThen(_.reverse.toArray) - // Step 5: Add ellipsis stack trace elements and "--full-stacktrace" info + // Step 5: Add ellipsis stack trace elements and "--full-stacktrace" info .andThen(a => ellipsis() +: a :+ ellipsis() :+ - ellipsis(Some("Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace"))) - // Step 5: Mutate the stack trace in this exception + ellipsis( + Some("Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace") + ) + ) + // Step 5: Mutate the stack trace in this exception .andThen(throwable.setStackTrace(_)) .apply(throwable.getStackTrace) } @@ -95,18 +98,21 @@ class ChiselException(message: String, cause: Throwable = null) extends Exceptio case a => getCauses(a, throwable +: acc) } - /** Returns true if an exception contains */ + /** Returns true if an exception contains */ private def containsBuilder(throwable: Throwable): Boolean = - throwable.getStackTrace().collectFirst { - case ste if ste.getClassName().startsWith(ExceptionHelpers.builderName) => throwable - }.isDefined + throwable + .getStackTrace() + .collectFirst { + case ste if ste.getClassName().startsWith(ExceptionHelpers.builderName) => throwable + } + .isDefined /** Examine this [[ChiselException]] and it's causes for the first [[Throwable]] that contains a stack trace including * a stack trace element whose declaring class is the [[builderName]]. If no such element exists, return this * [[ChiselException]]. */ private lazy val likelyCause: Throwable = - getCauses(this).collectFirst{ case a if containsBuilder(a) => a }.getOrElse(this) + getCauses(this).collectFirst { case a if containsBuilder(a) => a }.getOrElse(this) /** For an exception, return a stack trace trimmed to user code only * @@ -139,7 +145,9 @@ class ChiselException(message: String, cause: Throwable = null) extends Exceptio sw.write(likelyCause.toString + "\n") sw.write("\t...\n") trimmed.foreach(ste => sw.write(s"\tat $ste\n")) - sw.write("\t... (Stack trace trimmed to user code only, rerun with --full-stacktrace if you wish to see the full stack trace)\n") + sw.write( + "\t... (Stack trace trimmed to user code only, rerun with --full-stacktrace if you wish to see the full stack trace)\n" + ) sw.toString } } @@ -157,6 +165,7 @@ private[chisel3] object ErrorLog { } private[chisel3] class ErrorLog { + /** Log an error message */ def error(m: => String): Unit = errors += new Error(m, getUserLineNumber) @@ -168,16 +177,17 @@ private[chisel3] class ErrorLog { /** Emit an informational message */ @deprecated("This method will be removed in 3.5", "3.4") def info(m: String): Unit = - println(new Info("[%2.3f] %s".format(elapsedTime/1e3, m), None)) + println(new Info("[%2.3f] %s".format(elapsedTime / 1e3, m), None)) /** Log a deprecation warning message */ def deprecated(m: => String, location: Option[String]): Unit = { val sourceLoc = location match { case Some(loc) => loc - case None => getUserLineNumber match { - case Some(elt: StackTraceElement) => s"${elt.getFileName}:${elt.getLineNumber}" - case None => "(unknown)" - } + case None => + getUserLineNumber match { + case Some(elt: StackTraceElement) => s"${elt.getFileName}:${elt.getLineNumber}" + case None => "(unknown)" + } } val thisEntry = (m, sourceLoc) @@ -186,15 +196,20 @@ private[chisel3] class ErrorLog { /** Throw an exception if any errors have yet occurred. */ def checkpoint(logger: Logger): Unit = { - deprecations.foreach { case ((message, sourceLoc), count) => - logger.warn(s"${ErrorLog.depTag} $sourceLoc ($count calls): $message") + deprecations.foreach { + case ((message, sourceLoc), count) => + logger.warn(s"${ErrorLog.depTag} $sourceLoc ($count calls): $message") } errors.foreach(e => logger.error(e.toString)) if (!deprecations.isEmpty) { - logger.warn(s"${ErrorLog.warnTag} ${Console.YELLOW}There were ${deprecations.size} deprecated function(s) used." + - s" These may stop compiling in a future release - you are encouraged to fix these issues.${Console.RESET}") - logger.warn(s"${ErrorLog.warnTag} Line numbers for deprecations reported by Chisel may be inaccurate; enable scalac compiler deprecation warnings via either of the following methods:") + logger.warn( + s"${ErrorLog.warnTag} ${Console.YELLOW}There were ${deprecations.size} deprecated function(s) used." + + s" These may stop compiling in a future release - you are encouraged to fix these issues.${Console.RESET}" + ) + logger.warn( + s"${ErrorLog.warnTag} Line numbers for deprecations reported by Chisel may be inaccurate; enable scalac compiler deprecation warnings via either of the following methods:" + ) logger.warn(s"${ErrorLog.warnTag} In the sbt interactive console, enter:") logger.warn(s"""${ErrorLog.warnTag} set scalacOptions in ThisBuild ++= Seq("-unchecked", "-deprecation")""") logger.warn(s"${ErrorLog.warnTag} or, in your build.sbt, add the line:") @@ -205,16 +220,22 @@ private[chisel3] class ErrorLog { val allWarnings = errors.filter(!_.isFatal) if (!allWarnings.isEmpty && !allErrors.isEmpty) { - logger.warn(s"${ErrorLog.errTag} There were ${Console.RED}${allErrors.size} error(s)${Console.RESET} and ${Console.YELLOW}${allWarnings.size} warning(s)${Console.RESET} during hardware elaboration.") + logger.warn( + s"${ErrorLog.errTag} There were ${Console.RED}${allErrors.size} error(s)${Console.RESET} and ${Console.YELLOW}${allWarnings.size} warning(s)${Console.RESET} during hardware elaboration." + ) } else if (!allWarnings.isEmpty) { - logger.warn(s"${ErrorLog.warnTag} There were ${Console.YELLOW}${allWarnings.size} warning(s)${Console.RESET} during hardware elaboration.") + logger.warn( + s"${ErrorLog.warnTag} There were ${Console.YELLOW}${allWarnings.size} warning(s)${Console.RESET} during hardware elaboration." + ) } else if (!allErrors.isEmpty) { - logger.warn(s"${ErrorLog.errTag} There were ${Console.RED}${allErrors.size} error(s)${Console.RESET} during hardware elaboration.") + logger.warn( + s"${ErrorLog.errTag} There were ${Console.RED}${allErrors.size} error(s)${Console.RESET} during hardware elaboration." + ) } if (!allErrors.isEmpty) { throw new ChiselException("Fatal errors during hardware elaboration. Look above for error list.") - with scala.util.control.NoStackTrace + with scala.util.control.NoStackTrace } else { // No fatal errors, clear accumulated warnings since they've been reported errors.clear() @@ -228,20 +249,25 @@ private[chisel3] class ErrorLog { // List of classpath prefixes that are Chisel internals and should be ignored when looking for user code // utils are not part of internals and errors there can be reported val chiselPrefixes = Set( - "java.", - "scala.", - "chisel3.", - "chisel3.internal.", - "chisel3.experimental.", - "chisel3.package$" // for some compatibility / deprecated types - ) + "java.", + "scala.", + "chisel3.", + "chisel3.internal.", + "chisel3.experimental.", + "chisel3.package$" // for some compatibility / deprecated types + ) !chiselPrefixes.filter(className.startsWith(_)).isEmpty } - Thread.currentThread().getStackTrace.toList.dropWhile( - // Get rid of everything in Chisel core - ste => isChiselClassname(ste.getClassName) - ).headOption + Thread + .currentThread() + .getStackTrace + .toList + .dropWhile( + // Get rid of everything in Chisel core + ste => isChiselClassname(ste.getClassName) + ) + .headOption } private val errors = ArrayBuffer[LogEntry]() @@ -257,7 +283,7 @@ private abstract class LogEntry(msg: => String, line: Option[StackTraceElement]) override def toString: String = line match { case Some(l) => s"${format} ${l.getFileName}:${l.getLineNumber}: ${msg} in class ${l.getClassName}" - case None => s"${format} ${msg}" + case None => s"${format} ${msg}" } protected def tag(name: String, color: String): String = @@ -266,7 +292,7 @@ private abstract class LogEntry(msg: => String, line: Option[StackTraceElement]) private class Error(msg: => String, line: Option[StackTraceElement]) extends LogEntry(msg, line) { override def isFatal: Boolean = true - def format: String = tag("error", Console.RED) + def format: String = tag("error", Console.RED) } private class Warning(msg: => String, line: Option[StackTraceElement]) extends LogEntry(msg, line) { diff --git a/core/src/main/scala/chisel3/internal/MonoConnect.scala b/core/src/main/scala/chisel3/internal/MonoConnect.scala index 6173fc91..b4d9aeff 100644 --- a/core/src/main/scala/chisel3/internal/MonoConnect.scala +++ b/core/src/main/scala/chisel3/internal/MonoConnect.scala @@ -12,28 +12,28 @@ 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 -*/ + * 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 + */ private[chisel3] object MonoConnect { def formatName(data: Data) = s"""${data.earlyName} in ${data.parentNameOpt.getOrElse("(unknown)")}""" @@ -41,9 +41,13 @@ private[chisel3] object MonoConnect { // These are all the possible exceptions that can be thrown. // These are from element-level connection def UnreadableSourceException(sink: Data, source: Data) = - MonoConnectException(s"""${formatName(source)} cannot be read from module ${sink.parentNameOpt.getOrElse("(unknown)")}.""") + MonoConnectException( + s"""${formatName(source)} cannot be read from module ${sink.parentNameOpt.getOrElse("(unknown)")}.""" + ) def UnwritableSinkException(sink: Data, source: Data) = - MonoConnectException(s"""${formatName(sink)} cannot be written from module ${source.parentNameOpt.getOrElse("(unknown)")}.""") + MonoConnectException( + s"""${formatName(sink)} cannot be written from module ${source.parentNameOpt.getOrElse("(unknown)")}.""" + ) def SourceEscapedWhenScopeException(source: Data) = MonoConnectException(s"Source ${formatName(source)} has escaped the scope of the when in which it was constructed.") def SinkEscapedWhenScopeException(sink: Data) = @@ -56,7 +60,9 @@ private[chisel3] object MonoConnect { def MissingFieldException(field: String) = MonoConnectException(s"Source Record missing field ($field).") def MismatchedException(sink: Data, source: Data) = - MonoConnectException(s"Sink (${sink.cloneType.toString}) and Source (${source.cloneType.toString}) have different types.") + MonoConnectException( + s"Sink (${sink.cloneType.toString}) and Source (${source.cloneType.toString}) have different types." + ) def DontCareCantBeSink = MonoConnectException("DontCare cannot be a connection sink") def AnalogCantBeMonoSink(sink: Data) = @@ -64,28 +70,32 @@ private[chisel3] object MonoConnect { def AnalogCantBeMonoSource(source: Data) = MonoConnectException(s"Source ${formatName(source)} of type Analog cannot participate in a mono connection (:=)") def AnalogMonoConnectionException(source: Data, sink: Data) = - MonoConnectException(s"Source ${formatName(source)} and sink ${formatName(sink)} of type Analog cannot participate in a mono connection (:=)") + MonoConnectException( + s"Source ${formatName(source)} and sink ${formatName(sink)} of type Analog cannot participate in a mono connection (:=)" + ) def checkWhenVisibility(x: Data): Boolean = { x.topBinding match { - case mp: MemoryPortBinding => true // TODO (albert-magyar): remove this "bridge" for odd enable logic of current CHIRRTL memories + case mp: MemoryPortBinding => + true // TODO (albert-magyar): remove this "bridge" for odd enable logic of current CHIRRTL memories case cd: ConditionalDeclarable => cd.visibility.map(_.active()).getOrElse(true) case _ => true } } /** 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. - */ + * + * 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, - sink: Data, - source: Data, - context_mod: RawModule): Unit = + 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 @@ -118,8 +128,8 @@ private[chisel3] object MonoConnect { // 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) { + 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) @@ -129,7 +139,7 @@ private[chisel3] object MonoConnect { } // 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) { + for (idx <- 0 until sink_v.length) { try { implicit val compileOptions = connectCompileOptions connect(sourceInfo, connectCompileOptions, sink_v(idx), source, context_mod) @@ -141,7 +151,7 @@ private[chisel3] object MonoConnect { // Handle Record case case (sink_r: Record, source_r: Record) => // For each field, descend with right - for((field, sink_sub) <- sink_r.elements) { + 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) @@ -158,7 +168,7 @@ private[chisel3] object MonoConnect { // 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) { + for ((field, sink_sub) <- sink_r.elements) { try { connect(sourceInfo, connectCompileOptions, sink_sub, source, context_mod) } catch { @@ -171,7 +181,7 @@ private[chisel3] object MonoConnect { // DontCare as a sink is illegal. case (DontCare, _) => throw DontCareCantBeSink // Analog is illegal in mono connections. - case (_: Analog, _:Analog) => throw AnalogMonoConnectionException(source, sink) + case (_: Analog, _: Analog) => throw AnalogMonoConnectionException(source, sink) // Analog is illegal in mono connections. case (_: Analog, _) => throw AnalogCantBeMonoSink(sink) // Analog is illegal in mono connections. @@ -192,13 +202,19 @@ private[chisel3] object MonoConnect { // This function checks if element-level connection operation allowed. // Then it either issues it or throws the appropriate exception. - def elemConnect(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions, _sink: Element, _source: Element, context_mod: RawModule): Unit = { - import BindingDirection.{Internal, Input, Output} // Using extensively so import these + def elemConnect( + implicit sourceInfo: SourceInfo, + connectCompileOptions: CompileOptions, + _sink: Element, + _source: Element, + context_mod: RawModule + ): Unit = { + import BindingDirection.{Input, Internal, Output} // Using extensively so import these val sink = reify(_sink) val source = reify(_source) // 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(sink, source)) + val sink_mod: BaseModule = sink.topBinding.location.getOrElse(throw UnwritableSinkException(sink, source)) val source_mod: BaseModule = source.topBinding.location.getOrElse(context_mod) val sink_parent = Builder.retrieveParent(sink_mod, context_mod).getOrElse(None) @@ -216,69 +232,69 @@ private[chisel3] object MonoConnect { } // CASE: Context is same module that both left node and right node are in - if( (context_mod == sink_mod) && (context_mod == source_mod) ) { + 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(sink, source) + case (Output, _) => issueConnect(sink, source) + case (Internal, _) => issueConnect(sink, source) + case (Input, _) => throw UnwritableSinkException(sink, source) } } // CASE: Context is same module as sink node and right node is in a child module - else if((sink_mod == context_mod) && (source_parent == context_mod)) { + else if ((sink_mod == context_mod) && (source_parent == context_mod)) { // 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) => { + 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(sink, source) } } - case (Input, Output) if (!(connectCompileOptions.dontTryConnectionsSwapped)) => issueConnect(source, sink) - case (Input, _) => throw UnwritableSinkException(sink, source) + case (Input, Output) if (!(connectCompileOptions.dontTryConnectionsSwapped)) => issueConnect(source, sink) + case (Input, _) => throw UnwritableSinkException(sink, source) } } // CASE: Context is same module as source node and sink node is in child module - else if((source_mod == context_mod) && (sink_parent == context_mod)) { + else if ((source_mod == context_mod) && (sink_parent == context_mod)) { // 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(sink, source) - case (Internal, _) => throw UnwritableSinkException(sink, source) + case (Input, _) => issueConnect(sink, source) + case (Output, _) => throw UnwritableSinkException(sink, source) + case (Internal, _) => throw UnwritableSinkException(sink, source) } } // 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_parent == context_mod) && (source_parent == context_mod)) { + else if ((sink_parent == context_mod) && (source_parent == context_mod)) { // 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(sink, source) - case (_, Internal) => { + case (Input, Input) => issueConnect(sink, source) + case (Input, Output) => issueConnect(sink, source) + case (Output, _) => throw UnwritableSinkException(sink, source) + case (_, Internal) => { if (!(connectCompileOptions.dontAssumeDirectionality)) { issueConnect(sink, source) } else { throw UnreadableSourceException(sink, source) } } - case (Internal, _) => throw UnwritableSinkException(sink, source) + case (Internal, _) => throw UnwritableSinkException(sink, source) } } diff --git a/core/src/main/scala/chisel3/internal/Namer.scala b/core/src/main/scala/chisel3/internal/Namer.scala index c6e36cb6..c36aafef 100644 --- a/core/src/main/scala/chisel3/internal/Namer.scala +++ b/core/src/main/scala/chisel3/internal/Namer.scala @@ -42,6 +42,7 @@ import scala.collection.JavaConverters._ * ability to take descendant naming contexts. */ sealed trait NamingContextInterface { + /** Suggest a name (that will be propagated to FIRRTL) for an object, then returns the object * itself (so this can be inserted transparently anywhere). * Is a no-op (so safe) when applied on objects that aren't named, including non-Chisel data @@ -61,8 +62,7 @@ sealed trait NamingContextInterface { object DummyNamer extends NamingContextInterface { def name[T](obj: T, name: String): T = obj - def namePrefix(prefix: String): Unit = { - } + def namePrefix(prefix: String): Unit = {} } /** Actual namer functionality. @@ -71,7 +71,7 @@ class NamingContext extends NamingContextInterface { val descendants = new IdentityHashMap[AnyRef, ListBuffer[NamingContext]]() val anonymousDescendants = ListBuffer[NamingContext]() val items = ListBuffer[(AnyRef, String)]() - var closed = false // a sanity check to ensure no more name() calls are done after namePrefix + var closed = false // a sanity check to ensure no more name() calls are done after namePrefix /** Adds a NamingContext object as a descendant - where its contained objects will have names * prefixed with the name given to the reference object, if the reference object is named in the @@ -82,11 +82,13 @@ class NamingContext extends NamingContextInterface { case ref: AnyRef => // getOrElseUpdate val l = descendants.get(ref) - val buf = if (l != null) l else { - val value = ListBuffer[NamingContext]() - descendants.put(ref, value) - value - } + val buf = + if (l != null) l + else { + val value = ListBuffer[NamingContext]() + descendants.put(ref, value) + value + } buf += descendant case _ => anonymousDescendants += descendant } @@ -95,8 +97,8 @@ class NamingContext extends NamingContextInterface { def name[T](obj: T, name: String): T = { assert(!closed, "Can't name elements after namePrefix called") obj match { - case _: NoChiselNamePrefix => // Don't name things with NoChiselNamePrefix - case ref: AnyRef => items += ((ref, name)) + case _: NoChiselNamePrefix => // Don't name things with NoChiselNamePrefix + case ref: AnyRef => items += ((ref, name)) case _ => } obj @@ -156,5 +158,5 @@ class NamingStack { } } - def length() : Int = namingStack.length + def length(): Int = namingStack.length } diff --git a/core/src/main/scala/chisel3/internal/SourceInfo.scala b/core/src/main/scala/chisel3/internal/SourceInfo.scala index 0d6d8eb7..dc7f7fab 100644 --- a/core/src/main/scala/chisel3/internal/SourceInfo.scala +++ b/core/src/main/scala/chisel3/internal/SourceInfo.scala @@ -20,6 +20,7 @@ import scala.reflect.macros.blackbox.Context /** Abstract base class for generalized source information. */ sealed trait SourceInfo { + /** A prettier toString * * Make a useful message if SourceInfo is available, nothing otherwise diff --git a/core/src/main/scala/chisel3/internal/firrtl/Converter.scala b/core/src/main/scala/chisel3/internal/firrtl/Converter.scala index ac784882..2d21a7cb 100644 --- a/core/src/main/scala/chisel3/internal/firrtl/Converter.scala +++ b/core/src/main/scala/chisel3/internal/firrtl/Converter.scala @@ -5,7 +5,7 @@ import chisel3._ import chisel3.experimental._ import chisel3.internal.sourceinfo.{NoSourceInfo, SourceInfo, SourceLine, UnlocatableSourceInfo} import firrtl.{ir => fir} -import chisel3.internal.{HasId, castToInt, throwException} +import chisel3.internal.{castToInt, throwException, HasId} import scala.annotation.{nowarn, tailrec} import scala.collection.immutable.Queue @@ -21,9 +21,9 @@ private[chisel3] object Converter { case PString(str) => (str.replaceAll("%", "%%"), List.empty) case format: FirrtlFormat => ("%" + format.specifier, List(format.bits.ref)) - case Name(data) => (data.ref.name, List.empty) + case Name(data) => (data.ref.name, List.empty) case FullName(data) => (data.ref.fullName(ctx), List.empty) - case Percent => ("%%", List.empty) + case Percent => ("%%", List.empty) } private def reportInternalError(msg: String): Nothing = { @@ -53,9 +53,9 @@ private[chisel3] object Converter { def convert(dir: MemPortDirection): firrtl.MPortDir = dir match { case MemPortDirection.INFER => firrtl.MInfer - case MemPortDirection.READ => firrtl.MRead + case MemPortDirection.READ => firrtl.MRead case MemPortDirection.WRITE => firrtl.MWrite - case MemPortDirection.RDWR => firrtl.MReadWrite + case MemPortDirection.RDWR => firrtl.MReadWrite } // TODO @@ -82,7 +82,8 @@ private[chisel3] object Converter { fir.UIntLiteral(n, fir.IntWidth(u.minWidth)) case ULit(n, w) => fir.UIntLiteral(n, convert(w)) - case slit @ SLit(n, w) => fir.SIntLiteral(n, convert(w)) + case slit @ SLit(n, w) => + fir.SIntLiteral(n, convert(w)) val unsigned = if (n < 0) (BigInt(1) << slit.width.get) + n else n val uint = convert(ULit(unsigned, slit.width), ctx, info) fir.DoPrim(firrtl.PrimOps.AsSInt, Seq(uint), Seq.empty, fir.UnknownType) @@ -120,19 +121,43 @@ private[chisel3] object Converter { case e @ DefWire(info, id) => Some(fir.DefWire(convert(info), e.name, extractType(id, info))) case e @ DefReg(info, id, clock) => - Some(fir.DefRegister(convert(info), e.name, extractType(id, info), convert(clock, ctx, info), - firrtl.Utils.zero, convert(getRef(id, info), ctx, info))) + Some( + fir.DefRegister( + convert(info), + e.name, + extractType(id, info), + convert(clock, ctx, info), + firrtl.Utils.zero, + convert(getRef(id, info), ctx, info) + ) + ) case e @ DefRegInit(info, id, clock, reset, init) => - Some(fir.DefRegister(convert(info), e.name, extractType(id, info), convert(clock, ctx, info), - convert(reset, ctx, info), convert(init, ctx, info))) + Some( + fir.DefRegister( + convert(info), + e.name, + extractType(id, info), + convert(clock, ctx, info), + convert(reset, ctx, info), + convert(init, ctx, info) + ) + ) case e @ DefMemory(info, id, t, size) => Some(firrtl.CDefMemory(convert(info), e.name, extractType(t, info), size, false)) case e @ DefSeqMemory(info, id, t, size, ruw) => Some(firrtl.CDefMemory(convert(info), e.name, extractType(t, info), size, true, ruw)) case e: DefMemPort[_] => val info = e.sourceInfo - Some(firrtl.CDefMPort(convert(e.sourceInfo), e.name, fir.UnknownType, - e.source.fullName(ctx), Seq(convert(e.index, ctx, info), convert(e.clock, ctx, info)), convert(e.dir))) + Some( + firrtl.CDefMPort( + convert(e.sourceInfo), + e.name, + fir.UnknownType, + e.source.fullName(ctx), + Seq(convert(e.index, ctx, info), convert(e.clock, ctx, info)), + convert(e.dir) + ) + ) case Connect(info, loc, exp) => Some(fir.Connect(convert(info), convert(loc, ctx, info), convert(exp, ctx, info))) case BulkConnect(info, loc, exp) => @@ -147,16 +172,33 @@ private[chisel3] object Converter { Some(fir.Stop(convert(info), ret, convert(clock, ctx, info), firrtl.Utils.one, e.name)) case e @ Printf(_, info, clock, pable) => val (fmt, args) = unpack(pable, ctx) - Some(fir.Print(convert(info), fir.StringLit(fmt), - args.map(a => convert(a, ctx, info)), convert(clock, ctx, info), firrtl.Utils.one, e.name)) + Some( + fir.Print( + convert(info), + fir.StringLit(fmt), + args.map(a => convert(a, ctx, info)), + convert(clock, ctx, info), + firrtl.Utils.one, + e.name + ) + ) case e @ Verification(_, op, info, clk, pred, msg) => val firOp = op match { case Formal.Assert => fir.Formal.Assert case Formal.Assume => fir.Formal.Assume - case Formal.Cover => fir.Formal.Cover + case Formal.Cover => fir.Formal.Cover } - Some(fir.Verification(firOp, convert(info), convert(clk, ctx, info), - convert(pred, ctx, info), firrtl.Utils.one, fir.StringLit(msg), e.name)) + Some( + fir.Verification( + firOp, + convert(info), + convert(clk, ctx, info), + convert(pred, ctx, info), + firrtl.Utils.one, + fir.StringLit(msg), + e.name + ) + ) case _ => None } @@ -183,59 +225,60 @@ private[chisel3] object Converter { */ def convert(cmds: Seq[Command], ctx: Component): fir.Statement = { @tailrec - def rec(acc: Queue[fir.Statement], - scope: List[WhenFrame]) - (cmds: Seq[Command]): Seq[fir.Statement] = { + def rec(acc: Queue[fir.Statement], scope: List[WhenFrame])(cmds: Seq[Command]): Seq[fir.Statement] = { if (cmds.isEmpty) { assert(scope.isEmpty) acc - } else convertSimpleCommand(cmds.head, ctx) match { - // Most Commands map 1:1 - case Some(stmt) => - rec(acc :+ stmt, scope)(cmds.tail) - // When scoping logic does not map 1:1 and requires pushing/popping WhenFrames - // Please see WhenFrame for more details - case None => cmds.head match { - case WhenBegin(info, pred) => - val when = fir.Conditionally(convert(info), convert(pred, ctx, info), fir.EmptyStmt, fir.EmptyStmt) - val frame = WhenFrame(when, acc, false) - rec(Queue.empty, frame +: scope)(cmds.tail) - case WhenEnd(info, depth, _) => - val frame = scope.head - val when = if (frame.alt) frame.when.copy(alt = fir.Block(acc)) - else frame.when.copy(conseq = fir.Block(acc)) - // Check if this when has an else - cmds.tail.headOption match { - case Some(AltBegin(_)) => - assert(!frame.alt, "Internal Error! Unexpected when structure!") // Only 1 else per when - rec(Queue.empty, frame.copy(when = when, alt = true) +: scope.tail)(cmds.drop(2)) - case _ => // Not followed by otherwise - // If depth > 0 then we need to close multiple When scopes so we add a new WhenEnd - // If we're nested we need to add more WhenEnds to ensure each When scope gets - // properly closed - val cmdsx = if (depth > 0) WhenEnd(info, depth - 1, false) +: cmds.tail else cmds.tail - rec(frame.outer :+ when, scope.tail)(cmdsx) + } else + convertSimpleCommand(cmds.head, ctx) match { + // Most Commands map 1:1 + case Some(stmt) => + rec(acc :+ stmt, scope)(cmds.tail) + // When scoping logic does not map 1:1 and requires pushing/popping WhenFrames + // Please see WhenFrame for more details + case None => + cmds.head match { + case WhenBegin(info, pred) => + val when = fir.Conditionally(convert(info), convert(pred, ctx, info), fir.EmptyStmt, fir.EmptyStmt) + val frame = WhenFrame(when, acc, false) + rec(Queue.empty, frame +: scope)(cmds.tail) + case WhenEnd(info, depth, _) => + val frame = scope.head + val when = + if (frame.alt) frame.when.copy(alt = fir.Block(acc)) + else frame.when.copy(conseq = fir.Block(acc)) + // Check if this when has an else + cmds.tail.headOption match { + case Some(AltBegin(_)) => + assert(!frame.alt, "Internal Error! Unexpected when structure!") // Only 1 else per when + rec(Queue.empty, frame.copy(when = when, alt = true) +: scope.tail)(cmds.drop(2)) + case _ => // Not followed by otherwise + // If depth > 0 then we need to close multiple When scopes so we add a new WhenEnd + // If we're nested we need to add more WhenEnds to ensure each When scope gets + // properly closed + val cmdsx = if (depth > 0) WhenEnd(info, depth - 1, false) +: cmds.tail else cmds.tail + rec(frame.outer :+ when, scope.tail)(cmdsx) + } + case OtherwiseEnd(info, depth) => + val frame = scope.head + val when = frame.when.copy(alt = fir.Block(acc)) + // TODO For some reason depth == 1 indicates the last closing otherwise whereas + // depth == 0 indicates last closing when + val cmdsx = if (depth > 1) OtherwiseEnd(info, depth - 1) +: cmds.tail else cmds.tail + rec(scope.head.outer :+ when, scope.tail)(cmdsx) } - case OtherwiseEnd(info, depth) => - val frame = scope.head - val when = frame.when.copy(alt = fir.Block(acc)) - // TODO For some reason depth == 1 indicates the last closing otherwise whereas - // depth == 0 indicates last closing when - val cmdsx = if (depth > 1) OtherwiseEnd(info, depth - 1) +: cmds.tail else cmds.tail - rec(scope.head.outer :+ when, scope.tail)(cmdsx) } - } } fir.Block(rec(Queue.empty, List.empty)(cmds)) } def convert(width: Width): fir.Width = width match { - case UnknownWidth() => fir.UnknownWidth + case UnknownWidth() => fir.UnknownWidth case KnownWidth(value) => fir.IntWidth(value) } def convert(bp: BinaryPoint): fir.Width = bp match { - case UnknownBinaryPoint => fir.UnknownWidth + case UnknownBinaryPoint => fir.UnknownWidth case KnownBinaryPoint(value) => fir.IntWidth(value) } @@ -248,15 +291,15 @@ private[chisel3] object Converter { def extractType(data: Data, info: SourceInfo): fir.Type = extractType(data, false, info) def extractType(data: Data, clearDir: Boolean, info: SourceInfo): fir.Type = data match { - case _: Clock => fir.ClockType + case _: Clock => fir.ClockType case _: AsyncReset => fir.AsyncResetType - case _: ResetType => fir.ResetType - case d: EnumType => fir.UIntType(convert(d.width)) - case d: UInt => fir.UIntType(convert(d.width)) - case d: SInt => fir.SIntType(convert(d.width)) + case _: ResetType => fir.ResetType + case d: EnumType => fir.UIntType(convert(d.width)) + case d: UInt => fir.UIntType(convert(d.width)) + case d: SInt => fir.SIntType(convert(d.width)) case d: FixedPoint => fir.FixedType(convert(d.width), convert(d.binaryPoint)) - case d: Interval => fir.IntervalType(d.range.lowerBound, d.range.upperBound, d.range.firrtlBinaryPoint) - case d: Analog => fir.AnalogType(convert(d.width)) + case d: Interval => fir.IntervalType(d.range.lowerBound, d.range.upperBound, d.range.firrtlBinaryPoint) + case d: Analog => fir.AnalogType(convert(d.width)) case d: Vec[_] => fir.VectorType(extractType(d.sample_element, clearDir, info), d.length) case d: Record => val childClearDir = clearDir || @@ -269,23 +312,23 @@ private[chisel3] object Converter { fir.Field(getRef(elt, info).name, fir.Flip, extractType(elt, false, info)) } fir.BundleType(d.elements.toIndexedSeq.reverse.map { case (_, e) => eltField(e) }) - } + } def convert(name: String, param: Param): fir.Param = param match { - case IntParam(value) => fir.IntParam(name, value) + case IntParam(value) => fir.IntParam(name, value) case DoubleParam(value) => fir.DoubleParam(name, value) case StringParam(value) => fir.StringParam(name, fir.StringLit(value)) - case RawParam(value) => fir.RawStringParam(name, value) + case RawParam(value) => fir.RawStringParam(name, value) } def convert(port: Port, topDir: SpecifiedDirection = SpecifiedDirection.Unspecified): fir.Port = { val resolvedDir = SpecifiedDirection.fromParent(topDir, port.dir) val dir = resolvedDir match { case SpecifiedDirection.Unspecified | SpecifiedDirection.Output => fir.Output - case SpecifiedDirection.Flip | SpecifiedDirection.Input => fir.Input + case SpecifiedDirection.Flip | SpecifiedDirection.Input => fir.Input } val clearDir = resolvedDir match { - case SpecifiedDirection.Input | SpecifiedDirection.Output => true + case SpecifiedDirection.Input | SpecifiedDirection.Output => true case SpecifiedDirection.Unspecified | SpecifiedDirection.Flip => false } val info = UnlocatableSourceInfo // Unfortunately there is no source locator for ports ATM @@ -297,8 +340,13 @@ private[chisel3] object Converter { case ctx @ DefModule(_, name, ports, cmds) => fir.Module(fir.NoInfo, name, ports.map(p => convert(p)), convert(cmds.toList, ctx)) case ctx @ DefBlackBox(id, name, ports, topDir, params) => - fir.ExtModule(fir.NoInfo, name, ports.map(p => convert(p, topDir)), id.desiredName, - params.map { case (name, p) => convert(name, p) }.toSeq) + fir.ExtModule( + fir.NoInfo, + name, + ports.map(p => convert(p, topDir)), + id.desiredName, + params.map { case (name, p) => convert(name, p) }.toSeq + ) } def convert(circuit: Circuit): fir.Circuit = @@ -310,4 +358,3 @@ private[chisel3] object Converter { fir.Circuit(fir.NoInfo, lazyModules.map(convert), circuit.name) } } - diff --git a/core/src/main/scala/chisel3/internal/firrtl/IR.scala b/core/src/main/scala/chisel3/internal/firrtl/IR.scala index 68f5f18e..1ee8842f 100644 --- a/core/src/main/scala/chisel3/internal/firrtl/IR.scala +++ b/core/src/main/scala/chisel3/internal/firrtl/IR.scala @@ -15,7 +15,6 @@ import scala.collection.immutable.NumericRange import scala.math.BigDecimal.RoundingMode import scala.annotation.nowarn - case class PrimOp(name: String) { override def toString: String = name } @@ -68,35 +67,36 @@ object PrimOp { sealed abstract class Arg { def localName: String = name def contextualName(ctx: Component): String = name - def fullName(ctx: Component): String = contextualName(ctx) + def fullName(ctx: Component): String = contextualName(ctx) def name: String } case class Node(id: HasId) extends Arg { override def contextualName(ctx: Component): String = id.getOptionRef match { case Some(arg) => arg.contextualName(ctx) - case None => id.instanceName + case None => id.instanceName } override def localName: String = id.getOptionRef match { case Some(arg) => arg.localName - case None => id.instanceName + case None => id.instanceName } def name: String = id.getOptionRef match { case Some(arg) => arg.name - case None => id.instanceName + case None => id.instanceName } } object Arg { def earlyLocalName(id: HasId): String = id.getOptionRef match { case Some(Index(Node(imm), Node(value))) => s"${earlyLocalName(imm)}[${earlyLocalName(imm)}]" - case Some(Index(Node(imm), arg)) => s"${earlyLocalName(imm)}[${arg.localName}]" - case Some(Slot(Node(imm), name)) => s"${earlyLocalName(imm)}.$name" - case Some(arg) => arg.name - case None => id match { - case data: Data => data._computeName(None, Some("?")).get - case _ => "?" - } + case Some(Index(Node(imm), arg)) => s"${earlyLocalName(imm)}[${arg.localName}]" + case Some(Slot(Node(imm), name)) => s"${earlyLocalName(imm)}.$name" + case Some(arg) => arg.name + case None => + id match { + case data: Data => data._computeName(None, Some("?")).get + case _ => "?" + } } } @@ -121,8 +121,10 @@ abstract class LitArg(val num: BigInt, widthArg: Width) extends Arg { protected def minWidth: Int if (forcedWidth) { - require(widthArg.get >= minWidth, - s"The literal value ${num} was elaborated with a specified width of ${widthArg.get} bits, but at least ${minWidth} bits are required.") + require( + widthArg.get >= minWidth, + s"The literal value ${num} was elaborated with a specified width of ${widthArg.get} bits, but at least ${minWidth} bits are required." + ) } } @@ -131,8 +133,8 @@ case class ILit(n: BigInt) extends Arg { } case class ULit(n: BigInt, w: Width) extends LitArg(n, w) { - def name: String = "UInt" + width + "(\"h0" + num.toString(16) + "\")" - def minWidth: Int = 1 max n.bitLength + def name: String = "UInt" + width + "(\"h0" + num.toString(16) + "\")" + def minWidth: Int = 1.max(n.bitLength) def cloneWithWidth(newWidth: Width): this.type = { ULit(n, newWidth).asInstanceOf[this.type] @@ -171,8 +173,11 @@ case class IntervalLit(n: BigInt, w: Width, binaryPoint: BinaryPoint) extends Li s"asInterval(${ULit(unsigned, width).name}, ${n}, ${n}, ${binaryPoint.asInstanceOf[KnownBinaryPoint].value})" } val range: IntervalRange = { - new IntervalRange(IntervalRange.getBound(isClosed = true, BigDecimal(n)), - IntervalRange.getBound(isClosed = true, BigDecimal(n)), IntervalRange.getRangeWidth(binaryPoint)) + new IntervalRange( + IntervalRange.getBound(isClosed = true, BigDecimal(n)), + IntervalRange.getBound(isClosed = true, BigDecimal(n)), + IntervalRange.getRangeWidth(binaryPoint) + ) } def minWidth: Int = 1 + n.bitLength @@ -182,6 +187,7 @@ case class IntervalLit(n: BigInt, w: Width, binaryPoint: BinaryPoint) extends Li } case class Ref(name: String) extends Arg + /** Arg for ports of Modules * @param mod the module this port belongs to * @param name the name of the port @@ -190,6 +196,7 @@ case class ModuleIO(mod: BaseModule, name: String) extends Arg { override def contextualName(ctx: Component): String = if (mod eq ctx.id) name else s"${mod.getRef.name}.$name" } + /** Ports of cloned modules (CloneModuleAsRecord) * @param mod The original module for which these ports are a clone * @param name the name of the module instance @@ -224,22 +231,22 @@ object Width { sealed abstract class Width { type W = Int - def min(that: Width): Width = this.op(that, _ min _) - def max(that: Width): Width = this.op(that, _ max _) - def + (that: Width): Width = this.op(that, _ + _) - def + (that: Int): Width = this.op(this, (a, b) => a + that) - def shiftRight(that: Int): Width = this.op(this, (a, b) => 0 max (a - that)) + def min(that: Width): Width = this.op(that, _ min _) + def max(that: Width): Width = this.op(that, _ max _) + def +(that: Width): Width = this.op(that, _ + _) + def +(that: Int): Width = this.op(this, (a, b) => a + that) + def shiftRight(that: Int): Width = this.op(this, (a, b) => 0.max(a - that)) def dynamicShiftLeft(that: Width): Width = this.op(that, (a, b) => a + (1 << b) - 1) def known: Boolean - def get: W + def get: W protected def op(that: Width, f: (W, W) => W): Width } sealed case class UnknownWidth() extends Width { def known: Boolean = false - def get: Int = None.get + def get: Int = None.get def op(that: Width, f: (W, W) => W): Width = this override def toString: String = "" } @@ -247,10 +254,10 @@ sealed case class UnknownWidth() extends Width { sealed case class KnownWidth(value: Int) extends Width { require(value >= 0) def known: Boolean = true - def get: Int = value + def get: Int = value def op(that: Width, f: (W, W) => W): Width = that match { case KnownWidth(x) => KnownWidth(f(value, x)) - case _ => that + case _ => that } override def toString: String = s"<${value.toString}>" } @@ -262,36 +269,35 @@ object BinaryPoint { sealed abstract class BinaryPoint { type W = Int - def max(that: BinaryPoint): BinaryPoint = this.op(that, _ max _) - def + (that: BinaryPoint): BinaryPoint = this.op(that, _ + _) - def + (that: Int): BinaryPoint = this.op(this, (a, b) => a + that) - def shiftRight(that: Int): BinaryPoint = this.op(this, (a, b) => 0 max (a - that)) + def max(that: BinaryPoint): BinaryPoint = this.op(that, _ max _) + def +(that: BinaryPoint): BinaryPoint = this.op(that, _ + _) + def +(that: Int): BinaryPoint = this.op(this, (a, b) => a + that) + def shiftRight(that: Int): BinaryPoint = this.op(this, (a, b) => 0.max(a - that)) def dynamicShiftLeft(that: BinaryPoint): BinaryPoint = this.op(that, (a, b) => a + (1 << b) - 1) def known: Boolean - def get: W + def get: W protected def op(that: BinaryPoint, f: (W, W) => W): BinaryPoint } case object UnknownBinaryPoint extends BinaryPoint { def known: Boolean = false - def get: Int = None.get + def get: Int = None.get def op(that: BinaryPoint, f: (W, W) => W): BinaryPoint = this override def toString: String = "" } sealed case class KnownBinaryPoint(value: Int) extends BinaryPoint { def known: Boolean = true - def get: Int = value + def get: Int = value def op(that: BinaryPoint, f: (W, W) => W): BinaryPoint = that match { case KnownBinaryPoint(x) => KnownBinaryPoint(f(value, x)) - case _ => that + case _ => that } override def toString: String = s"<<${value.toString}>>" } - sealed abstract class MemPortDirection(name: String) { override def toString: String = name } @@ -305,17 +311,18 @@ object MemPortDirection { sealed trait RangeType { def getWidth: Width - def * (that: IntervalRange): IntervalRange - def +& (that: IntervalRange): IntervalRange - def -& (that: IntervalRange): IntervalRange - def << (that: Int): IntervalRange - def >> (that: Int): IntervalRange - def << (that: KnownWidth): IntervalRange - def >> (that: KnownWidth): IntervalRange + def *(that: IntervalRange): IntervalRange + def +&(that: IntervalRange): IntervalRange + def -&(that: IntervalRange): IntervalRange + def <<(that: Int): IntervalRange + def >>(that: Int): IntervalRange + def <<(that: KnownWidth): IntervalRange + def >>(that: KnownWidth): IntervalRange def merge(that: IntervalRange): IntervalRange } object IntervalRange { + /** Creates an IntervalRange, this is used primarily by the range interpolator macro * @param lower lower bound * @param upper upper bound @@ -352,7 +359,9 @@ object IntervalRange { case KnownWidth(w) => val nearestPowerOf2 = BigInt("1" + ("0" * (w - 1)), 2) IntervalRange( - firrtlir.Closed(BigDecimal(-nearestPowerOf2)), firrtlir.Closed(BigDecimal(nearestPowerOf2 - 1)), binaryPoint + firrtlir.Closed(BigDecimal(-nearestPowerOf2)), + firrtlir.Closed(BigDecimal(nearestPowerOf2 - 1)), + binaryPoint ) case _ => IntervalRange(firrtlir.UnknownBound, firrtlir.UnknownBound, binaryPoint) @@ -365,22 +374,19 @@ object IntervalRange { } def getBound(isClosed: Boolean, value: String): firrtlir.Bound = { - if(value == "?") { + if (value == "?") { firrtlir.UnknownBound - } - else if(isClosed) { + } else if (isClosed) { firrtlir.Closed(BigDecimal(value)) - } - else { + } else { firrtlir.Open(BigDecimal(value)) } } def getBound(isClosed: Boolean, value: BigDecimal): firrtlir.Bound = { - if(isClosed) { + if (isClosed) { firrtlir.Closed(value) - } - else { + } else { firrtlir.Open(value) } } @@ -394,33 +400,30 @@ object IntervalRange { } def getBinaryPoint(n: Int): firrtlir.Width = { - if(n < 0) { + if (n < 0) { firrtlir.UnknownWidth - } - else { + } else { firrtlir.IntWidth(n) } } def getBinaryPoint(n: BinaryPoint): firrtlir.Width = { n match { - case UnknownBinaryPoint => firrtlir.UnknownWidth + case UnknownBinaryPoint => firrtlir.UnknownWidth case KnownBinaryPoint(w) => firrtlir.IntWidth(w) } } def getRangeWidth(w: Width): firrtlir.Width = { - if(w.known) { + if (w.known) { firrtlir.IntWidth(w.get) - } - else { + } else { firrtlir.UnknownWidth } } def getRangeWidth(binaryPoint: BinaryPoint): firrtlir.Width = { - if(binaryPoint.known) { + if (binaryPoint.known) { firrtlir.IntWidth(binaryPoint.get) - } - else { + } else { firrtlir.UnknownWidth } } @@ -428,47 +431,46 @@ object IntervalRange { def Unknown: IntervalRange = range"[?,?].?" } - sealed class IntervalRange( - val lowerBound: firrtlir.Bound, - val upperBound: firrtlir.Bound, - private[chisel3] val firrtlBinaryPoint: firrtlir.Width) - extends firrtlir.IntervalType(lowerBound, upperBound, firrtlBinaryPoint) + val lowerBound: firrtlir.Bound, + val upperBound: firrtlir.Bound, + private[chisel3] val firrtlBinaryPoint: firrtlir.Width) + extends firrtlir.IntervalType(lowerBound, upperBound, firrtlBinaryPoint) with RangeType { (lowerBound, upperBound) match { case (firrtlir.Open(begin), firrtlir.Open(end)) => - if(begin >= end) throw new ChiselException(s"Invalid range with ${serialize}") + if (begin >= end) throw new ChiselException(s"Invalid range with ${serialize}") binaryPoint match { case KnownBinaryPoint(bp) => - if(begin >= end - (BigDecimal(1) / BigDecimal(BigInt(1) << bp))) { + if (begin >= end - (BigDecimal(1) / BigDecimal(BigInt(1) << bp))) { throw new ChiselException(s"Invalid range with ${serialize}") } case _ => } case (firrtlir.Open(begin), firrtlir.Closed(end)) => - if(begin >= end) throw new ChiselException(s"Invalid range with ${serialize}") + if (begin >= end) throw new ChiselException(s"Invalid range with ${serialize}") case (firrtlir.Closed(begin), firrtlir.Open(end)) => - if(begin >= end) throw new ChiselException(s"Invalid range with ${serialize}") + if (begin >= end) throw new ChiselException(s"Invalid range with ${serialize}") case (firrtlir.Closed(begin), firrtlir.Closed(end)) => - if(begin > end) throw new ChiselException(s"Invalid range with ${serialize}") + if (begin > end) throw new ChiselException(s"Invalid range with ${serialize}") case _ => } override def toString: String = { val binaryPoint = firrtlBinaryPoint match { case firrtlir.IntWidth(n) => s"$n" - case _ => "?" + case _ => "?" } val lowerBoundString = lowerBound match { - case firrtlir.Closed(l) => s"[$l" - case firrtlir.Open(l) => s"($l" - case firrtlir.UnknownBound => s"[?" + case firrtlir.Closed(l) => s"[$l" + case firrtlir.Open(l) => s"($l" + case firrtlir.UnknownBound => s"[?" } val upperBoundString = upperBound match { - case firrtlir.Closed(l) => s"$l]" - case firrtlir.Open(l) => s"$l)" - case firrtlir.UnknownBound => s"?]" + case firrtlir.Closed(l) => s"$l]" + case firrtlir.Open(l) => s"$l)" + case firrtlir.UnknownBound => s"?]" } s"""range"$lowerBoundString,$upperBoundString.$binaryPoint"""" } @@ -487,8 +489,8 @@ sealed class IntervalRange( case Some(inc) => lower match { case firrtlir.Closed(n) => Some(n) - case firrtlir.Open(n) => Some(n + inc) - case _ => None + case firrtlir.Open(n) => Some(n + inc) + case _ => None } case _ => None @@ -503,8 +505,8 @@ sealed class IntervalRange( case Some(inc) => upper match { case firrtlir.Closed(n) => Some(n) - case firrtlir.Open(n) => Some(n - inc) - case _ => None + case firrtlir.Open(n) => Some(n - inc) + case _ => None } case _ => None @@ -528,16 +530,18 @@ sealed class IntervalRange( override def getWidth: Width = { width match { - case firrtlir.IntWidth(n) => KnownWidth(n.toInt) + case firrtlir.IntWidth(n) => KnownWidth(n.toInt) case firrtlir.UnknownWidth => UnknownWidth() } } private def doFirrtlOp(op: firrtlir.PrimOp, that: IntervalRange): IntervalRange = { - PrimOps.set_primop_type( - firrtlir.DoPrim(op, - Seq(firrtlir.Reference("a", this), firrtlir.Reference("b", that)), Nil,firrtlir.UnknownType) - ).tpe match { + PrimOps + .set_primop_type( + firrtlir + .DoPrim(op, Seq(firrtlir.Reference("a", this), firrtlir.Reference("b", that)), Nil, firrtlir.UnknownType) + ) + .tpe match { case i: firrtlir.IntervalType => IntervalRange(i.lower, i.upper, i.point) case other => sys.error("BAD!") } @@ -545,24 +549,27 @@ sealed class IntervalRange( private def doFirrtlDynamicShift(that: UInt, isLeft: Boolean): IntervalRange = { val uinttpe = that.widthOption match { - case None => firrtlir.UIntType(firrtlir.UnknownWidth) + case None => firrtlir.UIntType(firrtlir.UnknownWidth) case Some(w) => firrtlir.UIntType(firrtlir.IntWidth(w)) } - val op = if(isLeft) PrimOps.Dshl else PrimOps.Dshr - PrimOps.set_primop_type( - firrtlir.DoPrim(op, - Seq(firrtlir.Reference("a", this), firrtlir.Reference("b", uinttpe)), Nil,firrtlir.UnknownType) - ).tpe match { + val op = if (isLeft) PrimOps.Dshl else PrimOps.Dshr + PrimOps + .set_primop_type( + firrtlir + .DoPrim(op, Seq(firrtlir.Reference("a", this), firrtlir.Reference("b", uinttpe)), Nil, firrtlir.UnknownType) + ) + .tpe match { case i: firrtlir.IntervalType => IntervalRange(i.lower, i.upper, i.point) case other => sys.error("BAD!") } } private def doFirrtlOp(op: firrtlir.PrimOp, that: Int): IntervalRange = { - PrimOps.set_primop_type( - firrtlir.DoPrim(op, - Seq(firrtlir.Reference("a", this)), Seq(BigInt(that)), firrtlir.UnknownType) - ).tpe match { + PrimOps + .set_primop_type( + firrtlir.DoPrim(op, Seq(firrtlir.Reference("a", this)), Seq(BigInt(that)), firrtlir.UnknownType) + ) + .tpe match { case i: firrtlir.IntervalType => IntervalRange(i.lower, i.upper, i.point) case other => sys.error("BAD!") } @@ -596,7 +603,7 @@ sealed class IntervalRange( } private def adjustBoundValue(value: BigDecimal, binaryPointValue: Int): BigDecimal = { - if(binaryPointValue >= 0) { + if (binaryPointValue >= 0) { val maskFactor = BigDecimal(1 << binaryPointValue) val a = (value * maskFactor) val b = a.setScale(0, RoundingMode.DOWN) @@ -611,9 +618,9 @@ sealed class IntervalRange( binaryPoint match { case KnownBinaryPoint(binaryPointValue) => bound match { - case firrtlir.Open(value) => firrtlir.Open(adjustBoundValue(value, binaryPointValue)) + case firrtlir.Open(value) => firrtlir.Open(adjustBoundValue(value, binaryPointValue)) case firrtlir.Closed(value) => firrtlir.Closed(adjustBoundValue(value, binaryPointValue)) - case _ => bound + case _ => bound } case _ => firrtlir.UnknownBound } @@ -746,19 +753,22 @@ sealed class IntervalRange( override def merge(that: IntervalRange): IntervalRange = { val lowest = (this.getLowestPossibleValue, that.getLowestPossibleValue) match { case (Some(l1), Some(l2)) => - if(l1 < l2) { this.lower } else { that.lower } + if (l1 < l2) { this.lower } + else { that.lower } case _ => firrtlir.UnknownBound } val highest = (this.getHighestPossibleValue, that.getHighestPossibleValue) match { case (Some(l1), Some(l2)) => - if(l1 >= l2) { this.lower } else { that.lower } + if (l1 >= l2) { this.lower } + else { that.lower } case _ => firrtlir.UnknownBound } val newBinaryPoint = (this.firrtlBinaryPoint, that.firrtlBinaryPoint) match { case (firrtlir.IntWidth(b1), firrtlir.IntWidth(b2)) => - if(b1 > b2) { firrtlir.IntWidth(b1)} else { firrtlir.IntWidth(b2) } + if (b1 > b2) { firrtlir.IntWidth(b1) } + else { firrtlir.IntWidth(b2) } case _ => firrtlir.UnknownWidth } @@ -788,8 +798,21 @@ case class DefWire(sourceInfo: SourceInfo, id: Data) extends Definition case class DefReg(sourceInfo: SourceInfo, id: Data, clock: Arg) extends Definition case class DefRegInit(sourceInfo: SourceInfo, id: Data, clock: Arg, reset: Arg, init: Arg) extends Definition case class DefMemory(sourceInfo: SourceInfo, id: HasId, t: Data, size: BigInt) extends Definition -case class DefSeqMemory(sourceInfo: SourceInfo, id: HasId, t: Data, size: BigInt, readUnderWrite: fir.ReadUnderWrite.Value) extends Definition -case class DefMemPort[T <: Data](sourceInfo: SourceInfo, id: T, source: Node, dir: MemPortDirection, index: Arg, clock: Arg) extends Definition +case class DefSeqMemory( + sourceInfo: SourceInfo, + id: HasId, + t: Data, + size: BigInt, + readUnderWrite: fir.ReadUnderWrite.Value) + extends Definition +case class DefMemPort[T <: Data]( + sourceInfo: SourceInfo, + id: T, + source: Node, + dir: MemPortDirection, + index: Arg, + clock: Arg) + extends Definition @nowarn("msg=class Port") // delete when Port becomes private case class DefInstance(sourceInfo: SourceInfo, id: BaseModule, ports: Seq[Port]) extends Definition case class WhenBegin(sourceInfo: SourceInfo, pred: Arg) extends Command @@ -802,7 +825,10 @@ case class Attach(sourceInfo: SourceInfo, locs: Seq[Node]) extends Command case class ConnectInit(sourceInfo: SourceInfo, loc: Node, exp: Arg) extends Command case class Stop(id: stop.Stop, sourceInfo: SourceInfo, clock: Arg, ret: Int) extends Definition // Note this is just deprecated which will cause deprecation warnings, use @nowarn -@deprecated("This API should never have been public, for Module port reflection, use DataMirror.modulePorts", "Chisel 3.5") +@deprecated( + "This API should never have been public, for Module port reflection, use DataMirror.modulePorts", + "Chisel 3.5" +) case class Port(id: Data, dir: SpecifiedDirection) case class Printf(id: printf.Printf, sourceInfo: SourceInfo, clock: Arg, pable: Printable) extends Definition object Formal extends Enumeration { @@ -810,18 +836,30 @@ object Formal extends Enumeration { val Assume = Value("assume") val Cover = Value("cover") } -case class Verification[T <: VerificationStatement](id: T, op: Formal.Value, sourceInfo: SourceInfo, clock: Arg, - predicate: Arg, message: String) extends Definition +case class Verification[T <: VerificationStatement]( + id: T, + op: Formal.Value, + sourceInfo: SourceInfo, + clock: Arg, + predicate: Arg, + message: String) + extends Definition @nowarn("msg=class Port") // delete when Port becomes private abstract class Component extends Arg { - def id: BaseModule - def name: String + def id: BaseModule + def name: String def ports: Seq[Port] } @nowarn("msg=class Port") // delete when Port becomes private case class DefModule(id: RawModule, name: String, ports: Seq[Port], commands: Seq[Command]) extends Component @nowarn("msg=class Port") // delete when Port becomes private -case class DefBlackBox(id: BaseBlackBox, name: String, ports: Seq[Port], topDir: SpecifiedDirection, params: Map[String, Param]) extends Component +case class DefBlackBox( + id: BaseBlackBox, + name: String, + ports: Seq[Port], + topDir: SpecifiedDirection, + params: Map[String, Param]) + extends Component case class Circuit(name: String, components: Seq[Component], annotations: Seq[ChiselAnnotation], renames: RenameMap) { def firrtlAnnotations: Iterable[Annotation] = annotations.flatMap(_.toFirrtl.update(renames)) diff --git a/core/src/main/scala/chisel3/internal/prefix.scala b/core/src/main/scala/chisel3/internal/prefix.scala index 620d0864..1e4c5ff1 100644 --- a/core/src/main/scala/chisel3/internal/prefix.scala +++ b/core/src/main/scala/chisel3/internal/prefix.scala @@ -15,7 +15,6 @@ package chisel3.internal * } * * }}} - * */ private[chisel3] object prefix { // scalastyle:ignore @@ -51,7 +50,7 @@ private[chisel3] object prefix { // scalastyle:ignore // This causes extra prefixes to be added, and subsequently cleared in the // Module constructor. Thus, we need to just make sure if the previous push // was an incorrect one, to not pop off an empty stack - if(Builder.getPrefix.nonEmpty) Builder.popPrefix() + if (Builder.getPrefix.nonEmpty) Builder.popPrefix() ret } } @@ -65,7 +64,6 @@ private[chisel3] object prefix { // scalastyle:ignore * } * * }}} - * */ private[chisel3] object noPrefix { diff --git a/core/src/main/scala/chisel3/package.scala b/core/src/main/scala/chisel3/package.scala index faca3ae4..bd088e21 100644 --- a/core/src/main/scala/chisel3/package.scala +++ b/core/src/main/scala/chisel3/package.scala @@ -3,7 +3,7 @@ import chisel3.internal.firrtl.BinaryPoint /** This package contains the main chisel3 API. - */ + */ package object chisel3 { import internal.firrtl.{Port, Width} import internal.Builder @@ -28,22 +28,27 @@ package object chisel3 { * `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 { 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) + 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()) + /** Int to SInt conversion, recommended style for constants. */ def S: SInt = SInt.Lit(bigint, Width()) + /** Int to UInt conversion with specified width, recommended style for constants. */ def U(width: Width): UInt = UInt.Lit(bigint, width) + /** Int to SInt conversion with specified width, recommended style for constants. */ def S(width: Width): SInt = SInt.Lit(bigint, width) @@ -52,19 +57,26 @@ package object chisel3 { */ def asUInt: UInt = UInt.Lit(bigint, Width()) - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) def asUInt(dummy: Int*): UInt = asUInt /** Int to SInt conversion, recommended style for variables. */ def asSInt: SInt = SInt.Lit(bigint, Width()) - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) def asSInt(dummy: Int*): SInt = asSInt /** 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) @@ -74,9 +86,11 @@ package object chisel3 { 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 + /** String to UInt parse with specified width, recommended style for constants. */ def U(width: Width): UInt = str.asUInt(width) @@ -85,10 +99,13 @@ package object chisel3 { */ def asUInt: UInt = { val bigInt = parse(str) - UInt.Lit(bigInt, Width(bigInt.bitLength max 1)) + UInt.Lit(bigInt, Width(bigInt.bitLength.max(1))) } - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) def asUInt(dummy: Int*): UInt = asUInt /** String to UInt parse with specified width, recommended style for variables. @@ -99,10 +116,10 @@ package object chisel3 { 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 + case "d" => 10 + case "o" => 8 + case "b" => 2 + case _ => Builder.error(s"Invalid base $base"); 2 } BigInt(num.filterNot(_ == '_'), radix) } @@ -113,6 +130,7 @@ package object chisel3 { } implicit class fromBooleanToLiteral(boolean: Boolean) { + /** Boolean to Bool conversion, recommended style for constants. */ def B: Bool = Bool.Lit(boolean) @@ -121,34 +139,37 @@ package object chisel3 { */ def asBool: Bool = Bool.Lit(boolean) - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) def asBool(dummy: Int*): Bool = asBool } // Fixed Point is experimental for now, but we alias the implicit conversion classes here // to minimize disruption with existing code. implicit class fromDoubleToLiteral(double: Double) - extends experimental.FixedPoint.Implicits.fromDoubleToLiteral(double) + extends experimental.FixedPoint.Implicits.fromDoubleToLiteral(double) implicit class fromBigDecimalToLiteral(bigDecimal: BigDecimal) - extends experimental.FixedPoint.Implicits.fromBigDecimalToLiteral(bigDecimal) + extends experimental.FixedPoint.Implicits.fromBigDecimalToLiteral(bigDecimal) // Interval is experimental for now, but we alias the implicit conversion classes here // to minimize disruption with existing code. implicit class fromIntToLiteralInterval(int: Int) - extends experimental.Interval.Implicits.fromIntToLiteralInterval(int) + extends experimental.Interval.Implicits.fromIntToLiteralInterval(int) implicit class fromLongToLiteralInterval(long: Long) - extends experimental.Interval.Implicits.fromLongToLiteralInterval(long) + extends experimental.Interval.Implicits.fromLongToLiteralInterval(long) implicit class fromBigIntToLiteralInterval(bigInt: BigInt) - extends experimental.Interval.Implicits.fromBigIntToLiteralInterval(bigInt) + extends experimental.Interval.Implicits.fromBigIntToLiteralInterval(bigInt) implicit class fromDoubleToLiteralInterval(double: Double) - extends experimental.Interval.Implicits.fromDoubleToLiteralInterval(double) + extends experimental.Interval.Implicits.fromDoubleToLiteralInterval(double) implicit class fromBigDecimalToLiteralInterval(bigDecimal: BigDecimal) - extends experimental.Interval.Implicits.fromBigDecimalToLiteralInterval(bigDecimal) + extends experimental.Interval.Implicits.fromBigDecimalToLiteralInterval(bigDecimal) implicit class fromIntToWidth(int: Int) { def W: Width = Width(int) @@ -187,25 +208,27 @@ package object chisel3 { /** Implicit for custom Printable string interpolator */ implicit class PrintableHelper(val sc: StringContext) extends AnyVal { + /** Custom string interpolator for generating Printables: p"..." * Will call .toString on any non-Printable arguments (mimicking s"...") */ def p(args: Any*): Printable = { sc.checkLengths(args) // Enforce sc.parts.size == pargs.size + 1 - val pargs: Seq[Option[Printable]] = args map { + val pargs: Seq[Option[Printable]] = args.map { case p: Printable => Some(p) - case d: Data => Some(d.toPrintable) - case any => for { - v <- Option(any) // Handle null inputs - str = v.toString - if !str.isEmpty // Handle empty Strings - } yield PString(str) + case d: Data => Some(d.toPrintable) + case any => + for { + v <- Option(any) // Handle null inputs + str = v.toString + if !str.isEmpty // Handle empty Strings + } yield PString(str) } - val parts = sc.parts map StringContext.treatEscapes + val parts = sc.parts.map(StringContext.treatEscapes) // Zip sc.parts and pargs together ito flat Seq // eg. Seq(sc.parts(0), pargs(0), sc.parts(1), pargs(1), ...) val seq = for { // append None because sc.parts.size == pargs.size + 1 - (literal, arg) <- parts zip (pargs :+ None) + (literal, arg) <- parts.zip(pargs :+ None) optPable <- Seq(Some(PString(literal)), arg) pable <- optPable // Remove Option[_] } yield pable @@ -221,19 +244,26 @@ package object chisel3 { def getDataElements(a: Aggregate): Seq[Element] = { a.allElements } - @deprecated("duplicated with DataMirror.fullModulePorts, this returns an internal API, will be removed in Chisel 3.6", "Chisel 3.5") + @deprecated( + "duplicated with DataMirror.fullModulePorts, this returns an internal API, will be removed in Chisel 3.6", + "Chisel 3.5" + ) def getModulePorts(m: Module): Seq[Port] = m.getPorts 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 + + /** 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) diff --git a/docs/src/cookbooks/hierarchy.md b/docs/src/cookbooks/hierarchy.md index 350d20eb..b8d2db63 100644 --- a/docs/src/cookbooks/hierarchy.md +++ b/docs/src/cookbooks/hierarchy.md @@ -209,13 +209,14 @@ chisel3.stage.ChiselStage.emitVerilog(new AddTwo(Definition(new AddOne(10)))) Select functions can be applied after a module has been elaborated, either in a Chisel Aspect or in a parent module applied to a child module. -There are six hierarchy-specific functions, which either return `Instance`'s or `Definition`'s: +There are seven hierarchy-specific functions, which (with the exception of `ios`) either return `Instance`'s or `Definition`'s: - `instancesIn(parent)`: Return all instances directly instantiated locally within `parent` - `instancesOf[type](parent)`: Return all instances of provided `type` directly instantiated locally within `parent` - `allInstancesOf[type](root)`: Return all instances of provided `type` directly and indirectly instantiated, locally and deeply, starting from `root` - `definitionsIn`: Return definitions of all instances directly instantiated locally within `parent` - `definitionsOf[type]`: Return definitions of all instances of provided `type` directly instantiated locally within `parent` - `allDefinitionsOf[type]`: Return all definitions of instances of provided `type` directly and indirectly instantiated, locally and deeply, starting from `root` + - `ios`: Returns all the I/Os of the provided definition or instance. To demonstrate this, consider the following. We mock up an example where we are using the `Select.allInstancesOf` and `Select.allDefinitionsOf` to annotate instances and the definition of `EmptyModule`. When converting the `ChiselAnnotation` to firrtl's `Annotation`, we print out the resulting `Target`. As shown, despite `EmptyModule` actually only being elaborated once, we still provide different targets depending on how the instance or definition is selected. @@ -259,3 +260,51 @@ println("```") val x = chisel3.stage.ChiselStage.emitFirrtl(new Top) println("```") ``` + +You can also use `Select.ios` on either a `Definition` or an `Instance` to annotate the I/Os appropriately: + +```scala mdoc +case class MyIOAnnotation(m: Data, tag: String) extends experimental.ChiselAnnotation { + def toFirrtl = { + println(tag + ": " + m.toTarget) + EmptyAnnotation + } +} + +@instantiable +class InOutModule extends Module { + @public val in = IO(Input(Bool())) + @public val out = IO(Output(Bool())) + out := in +} + +@instantiable +class TwoInOutModules extends Module { + val in = IO(Input(Bool())) + val out = IO(Output(Bool())) + val definition = Definition(new InOutModule) + val i0 = Instance(definition) + val i1 = Instance(definition) + i0.in := in + i1.in := i0.out + out := i1.out +} + +class InOutTop extends Module { + val definition = Definition(new TwoInOutModules) + val instance = Instance(definition) + aop.Select.allInstancesOf[InOutModule](instance).foreach { i => + aop.Select.ios(i).foreach { io => + experimental.annotate(MyIOAnnotation(io, "instance io")) + }} + aop.Select.allDefinitionsOf[InOutModule](instance).foreach { d => + aop.Select.ios(d).foreach {io => + experimental.annotate(MyIOAnnotation(io, "definition io")) + }} +} +``` +```scala mdoc:passthrough +println("```") +val y = chisel3.stage.ChiselStage.emitFirrtl(new InOutTop) +println("```") +```
\ No newline at end of file diff --git a/docs/src/explanations/connection-operators.md b/docs/src/explanations/connection-operators.md new file mode 100644 index 00000000..8a2117e1 --- /dev/null +++ b/docs/src/explanations/connection-operators.md @@ -0,0 +1,364 @@ +--- + +layout: docs + +title: "Deep Dive into Connection Operators" + +section: "chisel3" + +--- + +# Deep Dive into Connection Operators + +Chisel contains two connection operators, `:=` and `<>`. This document provides a deeper explanation of the differences of the two and when to use one or the other. The differences are demonstrated with experiments using Scastie examples which use `DecoupledIO`. + + + +### Experiment Setup + +```scala mdoc +// Imports used by the following examples +import chisel3._ +import chisel3.stage.ChiselStage +import chisel3.util.DecoupledIO +``` + +The diagram for the experiment can be viewed [here](https://docs.google.com/document/d/14C918Hdahk2xOGSJJBT-ZVqAx99_hg3JQIq-vaaifQU/edit?usp=sharing). + + +```scala mdoc:silent + +class Wrapper extends Module{ + val io = IO(new Bundle { + val in = Flipped(DecoupledIO(UInt(8.W))) + val out = DecoupledIO(UInt(8.W)) + }) + val p = Module(new PipelineStage) + val c = Module(new PipelineStage) + // connect Producer to IO + p.io.a <> io.in + // connect producer to consumer + c.io.a <> p.io.b + // connect consumer to IO + io.out <> c.io.b +} +class PipelineStage extends Module{ + val io = IO(new Bundle{ + val a = Flipped(DecoupledIO(UInt(8.W))) + val b = DecoupledIO(UInt(8.W)) + }) + io.b <> io.a +} +``` +Below we can see the resulting Verilog for this example: +```scala mdoc +ChiselStage.emitVerilog(new Wrapper) +``` +## Concept 1: `<>` is Commutative + + + +This experiment is set up to test for the function of `<>` using the experiment above. + +Achieving this involves flipping the RHS and LHS of the `<>` operator and seeing how `<>` will react. +( Scastie link for the experiment:https://scastie.scala-lang.org/Shorla/LVhlbkFQQnq7X3trHfgZZQ ) + + + + +```scala mdoc:silent:reset +import chisel3._ +import chisel3.stage.ChiselStage +import chisel3.util.DecoupledIO + +class Wrapper extends Module{ + val io = IO(new Bundle { + val in = Flipped(DecoupledIO(UInt(8.W))) + val out = DecoupledIO(UInt(8.W)) + }) + val p = Module(new PipelineStage) + val c = Module(new PipelineStage) + // connect producer to I/O + io.in <> p.io.a + // connect producer to consumer + p.io.b <> c.io.a + // connect consumer to I/O + c.io.b <> io.out +} +class PipelineStage extends Module{ + val io = IO(new Bundle{ + val a = Flipped(DecoupledIO(UInt(8.W))) + val b = DecoupledIO(UInt(8.W)) + }) + io.a <> io.b +} +``` +Below we can see the resulting Verilog for this example: +```scala mdoc +ChiselStage.emitVerilog(new Wrapper) +``` +### Conclusion: +The Verilog remained the same without incurring errors, showing that the `<>` operator is commutative. + + + + +## Concept 2: `:=` means assign ALL LHS signals from the RHS, regardless of the direction on the LHS. +Using the same experiment code as above, we set to test for the function of `:=` +We replace all instances of `<>` with `:=` in the sample code above. +(Scastie link to the experiment: https://scastie.scala-lang.org/Shorla/o1ShdaY3RWKf0IIFwwQ1UQ/1) + +```scala mdoc:silent:reset +import chisel3._ +import chisel3.stage.ChiselStage +import chisel3.util.DecoupledIO + +class Wrapper extends Module{ + val io = IO(new Bundle { + val in = Flipped(DecoupledIO(UInt(8.W))) + val out = DecoupledIO(UInt(8.W)) + }) + val p = Module(new PipelineStage) + val c = Module(new PipelineStage) + // connect producer to I/O + p.io.a := io.in + // connect producer to consumer + c.io.a := p.io.b + // connect consumer to I/O + io.out := c.io.b +} +class PipelineStage extends Module{ + val io = IO(new Bundle{ + val a = Flipped(DecoupledIO(UInt(8.W))) + val b = DecoupledIO(UInt(8.W)) + }) + io.a := io.b +} +``` +Below we can see the resulting error message for this example: +```scala mdoc:crash +ChiselStage.emitVerilog(new Wrapper) +``` +### Conclusion: +The := operator goes field-by-field on the LHS and attempts to connect it to the same-named signal from the RHS. If something on the LHS is actually an Input, or the corresponding signal on the RHS is an Output, you will get an error as shown above. + +## Concept 3: Always Use `:=` to assign DontCare to Wires +When assigning `DontCare` to something that is not directioned, should you use `:=` or `<>`? +We will find out using the sample codes below: +( Scastie link for the experiment:https://scastie.scala-lang.org/Shorla/ZIGsWcylRqKJhZCkKWlSIA/1) + +```scala mdoc:silent:reset +import chisel3._ +import chisel3.stage.ChiselStage +import chisel3.util.DecoupledIO + +class Wrapper extends Module{ + val io = IO(new Bundle { + val in = Flipped(DecoupledIO(UInt(8.W))) + val out = DecoupledIO(UInt(8.W)) + }) + val p = Module(new PipelineStage) + val c = Module(new PipelineStage) + //connect Producer to IO + io.in := DontCare + p.io.a <> DontCare + val tmp = Wire(Flipped(DecoupledIO(UInt(8.W)))) + tmp := DontCare + p.io.a <> io.in + // connect producer to consumer + c.io.a <> p.io.b + //connect consumer to IO + io.out <> c.io.b +} +class PipelineStage extends Module{ + val io = IO(new Bundle{ + val a = Flipped(DecoupledIO(UInt(8.W))) + val b = DecoupledIO(UInt(8.W)) + }) + io.b <> io.a +} +``` +Below we can see the resulting Verilog for this example: +```scala mdoc +ChiselStage.emitVerilog(new Wrapper) +``` +### Conclusion: +If `<>` were used to assign the unidrectioned wire `tmp` to DontCare, we would get an error. But in the example above, we used `:=` and no errors occurred. +But when `:=` was used to assign the wire to DontCare, no errors will occur. + +Thus, when assigning `DontCare` to a `Wire`, always use `:=`. + + +## Concept 4: You can use `<>` or `:=` to assign `DontCare` to directioned things (IOs) +When assigning `DontCare` to something that is directioned, should you use `:=` or `<>`? +We will find out using the sample codes below: +( Scastie link for the experiment:https://scastie.scala-lang.org/Shorla/ZIGsWcylRqKJhZCkKWlSIA/1) + +```scala mdoc:silent:reset +import chisel3._ +import chisel3.stage.ChiselStage +import chisel3.util.DecoupledIO + +class Wrapper extends Module{ + val io = IO(new Bundle { + val in = Flipped(DecoupledIO(UInt(8.W))) + val out = DecoupledIO(UInt(8.W)) + }) + val p = Module(new PipelineStage) + val c = Module(new PipelineStage) + //connect Producer to IO + io.in := DontCare + p.io.a <> DontCare + val tmp = Wire(Flipped(DecoupledIO(UInt(8.W)))) + tmp := DontCare + p.io.a <> io.in + // connect producer to consumer + c.io.a <> p.io.b + //connect consumer to IO + io.out <> c.io.b +} +class PipelineStage extends Module{ + val io = IO(new Bundle{ + val a = Flipped(DecoupledIO(UInt(8.W))) + val b = DecoupledIO(UInt(8.W)) + }) + io.b <> io.a +} +``` +Below we can see the resulting Verilog for this example: +```scala mdoc +ChiselStage.emitVerilog(new Wrapper) +``` +### Conclusion: +Both `<>` and `:=` can be used to assign directioned things (IOs) to DontCare as shown in `io.in` and `p.io.a` respectively. This is basically equivalent because in this case both `<>` and `:=` will determine the direction from the LHS. + + +## Concept 5: `<>` works between things with at least one known flow (An IO or child's IO). + +If there is at least one known flow what will `<>` do? This will be shown using the experiment code below: +( Scastie link for the experiment:https://scastie.scala-lang.org/Shorla/gKx9ReLVTTqDTk9vmw5ozg) + +```scala mdoc:silent:reset +import chisel3._ +import chisel3.stage.ChiselStage +import chisel3.util.DecoupledIO + +class Wrapper extends Module{ + val io = IO(new Bundle { + val in = Flipped(DecoupledIO(UInt(8.W))) + val out = DecoupledIO(UInt(8.W)) + }) + val p = Module(new PipelineStage) + val c = Module(new PipelineStage) + //connect Producer to IO + // For this experiment, we add a temporary wire and see if it works... + //p.io.a <> io.in + val tmp = Wire(DecoupledIO(UInt(8.W))) + // connect intermediate wire + tmp <> io.in + p.io.a <> tmp + // connect producer to consumer + c.io.a <> p.io.b + //connect consumer to IO + io.out <> c.io.b +} +class PipelineStage extends Module{ + val io = IO(new Bundle{ + val a = Flipped(DecoupledIO(UInt(8.W))) + val b = DecoupledIO(UInt(8.W)) + }) + io.b <> io.a +} +``` +Below we can see the resulting Verilog for this example: +```scala mdoc +ChiselStage.emitVerilog(new Wrapper) +``` +### Conclusion: +The connection above went smoothly with no errors, this goes to show `<>` will work as long as there is at least one directioned thing (IO or submodule's IO) to "fix" the direction. + + +## Concept 6: `<>` and `:=` connect signals by field name. +This experiment creates a MockDecoupledIO which has the same fields by name as a DecoupledIO. Chisel lets us connect it and produces the same verilog, even though MockDecoupledIO and DecoupledIO are different types. +( Scastie link for the experiment:https://scastie.scala-lang.org/Uf4tQquvQYigZAW705NFIQ) + +```scala mdoc:silent:reset +import chisel3._ +import chisel3.stage.ChiselStage +import chisel3.util.DecoupledIO + +class MockDecoupledIO extends Bundle { + val valid = Output(Bool()) + val ready = Input(Bool()) + val bits = Output(UInt(8.W)) +} +class Wrapper extends Module{ + val io = IO(new Bundle { + val in = Flipped(new MockDecoupledIO()) + val out = new MockDecoupledIO() + }) + val p = Module(new PipelineStage) + val c = Module(new PipelineStage) + // connect producer to I/O + p.io.a <> io.in + // connect producer to consumer + c.io.a <> p.io.b + // connect consumer to I/O + io.out <> c.io.b +} +class PipelineStage extends Module{ + val io = IO(new Bundle{ + val a = Flipped(DecoupledIO(UInt(8.W))) + val b = DecoupledIO(UInt(8.W)) + }) + io.a <> io.b +} +``` +Below we can see the resulting Verilog for this example: +```scala mdoc +ChiselStage.emitVerilog(new Wrapper) +``` +And here is another experiment, where we remove one of the fields of MockDecoupledIO: +( Scastie link for the experiment:https://scastie.scala-lang.org/ChtkhKCpS9CvJkjjqpdeIA) + +```scala mdoc:silent:reset +import chisel3._ +import chisel3.stage.ChiselStage +import chisel3.util.DecoupledIO + +class MockDecoupledIO extends Bundle { + val valid = Output(Bool()) + val ready = Input(Bool()) + //val bits = Output(UInt(8.W)) +} +class Wrapper extends Module{ + val io = IO(new Bundle { + val in = Flipped(new MockDecoupledIO()) + val out = new MockDecoupledIO() + }) + val p = Module(new PipelineStage) + val c = Module(new PipelineStage) + // connect producer to I/O + p.io.a <> io.in + // connect producer to consumer + c.io.a <> p.io.b + // connect consumer to I/O + io.out <> c.io.b +} +class PipelineStage extends Module{ + val io = IO(new Bundle{ + val a = Flipped(DecoupledIO(UInt(8.W))) + val b = DecoupledIO(UInt(8.W)) + }) + io.a <> io.b +} +``` +Below we can see the resulting error for this example: +```scala mdoc:crash +ChiselStage.emitVerilog(new Wrapper) +``` +This one fails because there is a field `bits` missing. + +### Conclusion: +For `:=`, the Scala types do not need to match but all the signals on the LHS must be provided by the RHS or you will get a Chisel elaboration error. There may be additional signals on the RHS, these will be ignored. For `<>`, the Scala types do not need to match, but all signals must match exactly between LHS and RHS. In both cases, the order of the fields does not matter. + diff --git a/docs/src/explanations/explanations.md b/docs/src/explanations/explanations.md index 595bb48c..9e0227d5 100644 --- a/docs/src/explanations/explanations.md +++ b/docs/src/explanations/explanations.md @@ -28,7 +28,7 @@ read these documents in the following order: * [Memories](memories) * [Interfaces and Connections](interfaces-and-connections) * [Black Boxes](blackboxes) -* [Enumerations](enumerations) +* [Enumerations](chisel-enum) * [Functional Module Creation](functional-module-creation) * [Muxes and Input Selection](muxes-and-input-selection) * [Multiple Clock Domains](multi-clock) @@ -38,3 +38,4 @@ read these documents in the following order: * [Naming](naming) * [Unconnected Wires](unconnected-wires) * [Annotations](annotations) +* [Deep Dive into Connection Operators](connection-operators) diff --git a/docs/src/explanations/interfaces-and-connections.md b/docs/src/explanations/interfaces-and-connections.md index 9f48b642..0fb8bae8 100644 --- a/docs/src/explanations/interfaces-and-connections.md +++ b/docs/src/explanations/interfaces-and-connections.md @@ -4,7 +4,7 @@ title: "Interfaces and Connections" section: "chisel3" --- -# Interfaces & Bulk Connections +# Interfaces & Connections For more sophisticated modules it is often useful to define and instantiate interface classes while defining the IO for a module. First and foremost, interface classes promote reuse allowing users to capture once and for all common interfaces in a useful form. @@ -18,6 +18,7 @@ As we saw earlier, users can define their own interfaces by defining a class tha ```scala mdoc:invisible import chisel3._ +import chisel3.stage.ChiselStage ``` ```scala mdoc:silent @@ -67,8 +68,34 @@ class CrossbarIo(n: Int) extends Bundle { where Vec takes a size as the first argument and a block returning a port as the second argument. ## Bulk Connections +Once we have a defined Interface, we can connect to it via a [`MonoConnect`](https://www.chisel-lang.org/api/latest/chisel3/Data.html#:=) operator (`:=`) or [`BiConnect`](https://www.chisel-lang.org/api/latest/chisel3/Data.html#%3C%3E) operator (`<>`). -We can now compose two filters into a filter block as follows: +### `MonoConnect` Algorithm +`MonoConnect.connect`, or `:=`, 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 fields. +Vecs must still be exactly the same size. + +Note that the LHS element 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 the RHS element 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 + + +### `BiConnect` Algorithm +`BiConnect.connect`, or `<>`, 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. + +Using the biconnect `<>` operator, we can now compose two filters into a filter block as follows: ```scala mdoc:silent class Block extends Module { val io = IO(new FilterIO) @@ -79,11 +106,53 @@ class Block extends Module { f2.io.y <> io.y } ``` -where <> bulk connects interfaces of opposite gender between sibling modules or interfaces of the same gender between parent/child modules. -Bulk connections connect leaf ports of the same name to each other. If the names do not match or are missing, Chisel does not generate a connection. +The bidirectional bulk connection operator `<>` connects leaf ports of the same name to each other. The Scala types of the Bundles are not required to match. If one named signal is missing from either side, Chisel will give an error such as in the following example: + +```scala mdoc:silent + +class NotReallyAFilterIO extends Bundle { + val x = Flipped(new PLink) + val y = new PLink + val z = Output(new Bool()) +} +class Block2 extends Module { + val io1 = IO(new FilterIO) + val io2 = IO(Flipped(new NotReallyAFilterIO)) + + io1 <> io2 +} +``` +Below we can see the resulting error for this example: +```scala mdoc:crash +ChiselStage.emitVerilog(new Block2) +``` +Bidirectional connections should only be used with **directioned elements** (like IOs), e.g. connecting two wires isn't supported since Chisel can't necessarily figure out the directions automatically. +For example, putting two temporary wires and connecting them here will not work, even though the directions could be known from the endpoints: + +```scala mdoc:silent + +class BlockWithTemporaryWires extends Module { + val io = IO(new FilterIO) + val f1 = Module(new Filter) + val f2 = Module(new Filter) + f1.io.x <> io.x + val tmp1 = Wire(new FilterIO) + val tmp2 = Wire(new FilterIO) + f1.io.y <> tmp1 + tmp1 <> tmp2 + tmp2 <> f2.io.x + f2.io.y <> io.y +} + +``` +Below we can see the resulting error for this example: +```scala mdoc:crash +ChiselStage.emitVerilog(new BlockWithTemporaryWires) +``` +For more details and information, see [Deep Dive into Connection Operators](connection-operators.md) -Caution: bulk connections should only be used with **directioned elements** (like IOs), and is not magical (e.g. connecting two wires isn't supported since Chisel can't necessarily figure out the directions automatically [chisel3#603](https://github.com/freechipsproject/chisel3/issues/603)). +NOTE: When using `Chisel._` (compatibility mode) instead of `chisel3._`, the `:=` operator works in a bidirectional fashion similar to `<>`, but not exactly the same. ## The standard ready-valid interface (ReadyValidIO / Decoupled) @@ -144,6 +213,6 @@ class ConsumingData extends Module { That means `ready` and `valid` can also be deasserted without a data transfer. `IrrevocableIO` is a ready-valid interface with the *convention* that the value of `bits` will not change while `valid` is asserted and `ready` is deasserted. -Also the consumer shall keep `ready` asserted after a cycle where `ready` was high and `valid` was low. +Also, the consumer shall keep `ready` asserted after a cycle where `ready` was high and `valid` was low. Note that the *irrevocable* constraint *is only a convention* and cannot be enforced by the interface. Chisel does not automatically generate checkers or assertions to enforce the *irrevocable* convention. diff --git a/docs/src/images/chisel_01.png b/docs/src/images/chisel_01.png Binary files differnew file mode 100644 index 00000000..8fb1c8bf --- /dev/null +++ b/docs/src/images/chisel_01.png diff --git a/macros/src/main/scala/chisel3/internal/InstantiableMacro.scala b/macros/src/main/scala/chisel3/internal/InstantiableMacro.scala index 18c6c7aa..d66b51ac 100644 --- a/macros/src/main/scala/chisel3/internal/InstantiableMacro.scala +++ b/macros/src/main/scala/chisel3/internal/InstantiableMacro.scala @@ -6,7 +6,6 @@ import scala.language.experimental.macros import scala.annotation.StaticAnnotation import scala.reflect.macros.whitebox - private[chisel3] object instantiableMacro { def impl(c: whitebox.Context)(annottees: c.Expr[Any]*): c.Expr[Any] = { @@ -38,7 +37,7 @@ private[chisel3] object instantiableMacro { val result = { val (clz, objOpt) = annottees.map(_.tree).toList match { case Seq(c, o) => (c, Some(o)) - case Seq(c) => (c, None) + case Seq(c) => (c, None) } val (newClz, implicitClzs, tpname) = clz match { case q"$mods class $tpname[..$tparams] $ctorMods(...$paramss) extends { ..$earlydefns } with ..$parents { $self => ..$stats }" => @@ -46,19 +45,27 @@ private[chisel3] object instantiableMacro { val instname = TypeName(tpname + c.freshName()) val (newStats, extensions) = processBody(stats) val argTParams = tparams.map(_.name) - (q""" $mods class $tpname[..$tparams] $ctorMods(...$paramss) extends { ..$earlydefns } with ..$parents with chisel3.experimental.hierarchy.IsInstantiable { $self => ..$newStats } """, - Seq(q"""implicit class $defname[..$tparams](___module: chisel3.experimental.hierarchy.Definition[$tpname[..$argTParams]]) { ..$extensions }""", - q"""implicit class $instname[..$tparams](___module: chisel3.experimental.hierarchy.Instance[$tpname[..$argTParams]]) { ..$extensions } """), - tpname) + ( + q""" $mods class $tpname[..$tparams] $ctorMods(...$paramss) extends { ..$earlydefns } with ..$parents with chisel3.experimental.hierarchy.IsInstantiable { $self => ..$newStats } """, + Seq( + q"""implicit class $defname[..$tparams](___module: chisel3.experimental.hierarchy.Definition[$tpname[..$argTParams]]) { ..$extensions }""", + q"""implicit class $instname[..$tparams](___module: chisel3.experimental.hierarchy.Instance[$tpname[..$argTParams]]) { ..$extensions } """ + ), + tpname + ) case q"$mods trait $tpname[..$tparams] extends { ..$earlydefns } with ..$parents { $self => ..$stats }" => val defname = TypeName(tpname + c.freshName()) val instname = TypeName(tpname + c.freshName()) val (newStats, extensions) = processBody(stats) val argTParams = tparams.map(_.name) - (q"$mods trait $tpname[..$tparams] extends { ..$earlydefns } with ..$parents with chisel3.experimental.hierarchy.IsInstantiable { $self => ..$newStats }", - Seq(q"""implicit class $defname[..$tparams](___module: chisel3.experimental.hierarchy.Definition[$tpname[..$argTParams]]) { ..$extensions }""", - q"""implicit class $instname[..$tparams](___module: chisel3.experimental.hierarchy.Instance[$tpname[..$argTParams]]) { ..$extensions } """), - tpname) + ( + q"$mods trait $tpname[..$tparams] extends { ..$earlydefns } with ..$parents with chisel3.experimental.hierarchy.IsInstantiable { $self => ..$newStats }", + Seq( + q"""implicit class $defname[..$tparams](___module: chisel3.experimental.hierarchy.Definition[$tpname[..$argTParams]]) { ..$extensions }""", + q"""implicit class $instname[..$tparams](___module: chisel3.experimental.hierarchy.Instance[$tpname[..$argTParams]]) { ..$extensions } """ + ), + tpname + ) } val newObj = objOpt match { case None => q"""object ${tpname.toTermName} { ..$implicitClzs } """ diff --git a/macros/src/main/scala/chisel3/internal/RangeTransform.scala b/macros/src/main/scala/chisel3/internal/RangeTransform.scala index b9a2d2aa..f401241d 100644 --- a/macros/src/main/scala/chisel3/internal/RangeTransform.scala +++ b/macros/src/main/scala/chisel3/internal/RangeTransform.scala @@ -12,8 +12,8 @@ import scala.util.matching.Regex // Workaround for https://github.com/sbt/sbt/issues/3966 object RangeTransform { val UnspecifiedNumber: Regex = """(\?).*""".r - val IntegerNumber: Regex = """(-?\d+).*""".r - val DecimalNumber: Regex = """(-?\d+\.\d+).*""".r + val IntegerNumber: Regex = """(-?\d+).*""".r + val DecimalNumber: Regex = """(-?\d+\.\d+).*""".r } /** Convert the string to IntervalRange, with unknown, open or closed endpoints and a binary point @@ -48,8 +48,8 @@ class RangeTransform(val c: blackbox.Context) { } var nextStringIndex: Int = 1 - var nextArgIndex: Int = 0 - var currString: String = strings.head + var nextArgIndex: Int = 0 + var currString: String = strings.head /** Mutably gets the next numeric value in the range specifier. */ diff --git a/macros/src/main/scala/chisel3/internal/RuntimeDeprecationTransform.scala b/macros/src/main/scala/chisel3/internal/RuntimeDeprecationTransform.scala index e7eb7162..ff41bd30 100644 --- a/macros/src/main/scala/chisel3/internal/RuntimeDeprecationTransform.scala +++ b/macros/src/main/scala/chisel3/internal/RuntimeDeprecationTransform.scala @@ -3,7 +3,7 @@ package chisel3.internal import scala.reflect.macros.whitebox.Context -import scala.annotation.{StaticAnnotation, compileTimeOnly} +import scala.annotation.{compileTimeOnly, StaticAnnotation} import scala.language.experimental.macros // Workaround for https://github.com/sbt/sbt/issues/3966 @@ -14,24 +14,34 @@ class RuntimeDeprecatedTransform(val c: Context) { /** Adds a Builder.deprecated(...) call based on the contents of a plain @deprecated annotation. */ def runtimeDeprecated(annottees: c.Tree*): c.Tree = { - val transformed = annottees.map(annottee => annottee match { - case q"$mods def $tname[..$tparams](...$paramss): $tpt = $expr" => { - val Modifiers(_, _, annotations) = mods - val annotationMessage = annotations.collect { // get all messages from deprecated annotations - case q"new deprecated($desc, $since)" => desc - } match { // ensure there's only one and return it - case msg :: Nil => msg - case _ => c.abort(c.enclosingPosition, s"@chiselRuntimeDeprecated annotion must be used with exactly one @deprecated annotation, got annotations $annotations") - } - val message = s"$tname is deprecated: $annotationMessage" - val transformedExpr = q""" { + val transformed = annottees.map(annottee => + annottee match { + case q"$mods def $tname[..$tparams](...$paramss): $tpt = $expr" => { + val Modifiers(_, _, annotations) = mods + val annotationMessage = annotations.collect { // get all messages from deprecated annotations + case q"new deprecated($desc, $since)" => desc + } match { // ensure there's only one and return it + case msg :: Nil => msg + case _ => + c.abort( + c.enclosingPosition, + s"@chiselRuntimeDeprecated annotion must be used with exactly one @deprecated annotation, got annotations $annotations" + ) + } + val message = s"$tname is deprecated: $annotationMessage" + val transformedExpr = q""" { _root_.chisel3.internal.Builder.deprecated($message) $expr } """ - q"$mods def $tname[..$tparams](...$paramss): $tpt = $transformedExpr" + q"$mods def $tname[..$tparams](...$paramss): $tpt = $transformedExpr" + } + case other => + c.abort( + c.enclosingPosition, + s"@chiselRuntimeDeprecated annotion may only be used on defs, got ${showCode(other)}" + ) } - case other => c.abort(c.enclosingPosition, s"@chiselRuntimeDeprecated annotion may only be used on defs, got ${showCode(other)}") - }) + ) q"..$transformed" } } diff --git a/macros/src/main/scala/chisel3/internal/naming/NamingAnnotations.scala b/macros/src/main/scala/chisel3/internal/naming/NamingAnnotations.scala index 0c400a07..82223d78 100644 --- a/macros/src/main/scala/chisel3/internal/naming/NamingAnnotations.scala +++ b/macros/src/main/scala/chisel3/internal/naming/NamingAnnotations.scala @@ -13,7 +13,7 @@ package chisel3.internal.naming import scala.reflect.macros.whitebox.Context -import scala.annotation.{StaticAnnotation, compileTimeOnly} +import scala.annotation.{compileTimeOnly, StaticAnnotation} import scala.language.experimental.macros // Workaround for https://github.com/sbt/sbt/issues/3966 @@ -79,13 +79,13 @@ class NamingTransforms(val c: Context) { class ClassBodyTransformer(val contextVar: TermName) extends ValNameTransformer { override def transform(tree: Tree): Tree = tree match { case q"$mods class $tpname[..$tparams] $ctorMods(...$paramss) extends { ..$earlydefns } with ..$parents { $self => ..$stats }" => - tree // don't recurse into inner classes + tree // don't recurse into inner classes case q"$mods trait $tpname[..$tparams] extends { ..$earlydefns } with ..$parents { $self => ..$stats }" => - tree // don't recurse into inner classes + tree // don't recurse into inner classes case q"$mods def $tname[..$tparams](...$paramss): $tpt = $expr" => { val Modifiers(_, _, annotations) = mods // don't apply naming transform twice - val containsChiselName = annotations.map({q"new chiselName()" equalsStructure _}).fold(false)({_||_}) + val containsChiselName = annotations.map({ q"new chiselName()" equalsStructure _ }).fold(false)({ _ || _ }) // transforming overloaded initializers causes errors, and the transform isn't helpful val isInitializer = tname == TermName("<init>") if (containsChiselName || isInitializer) { @@ -108,7 +108,7 @@ class NamingTransforms(val c: Context) { case q"return $expr" => q"return $globalNamingStack.popReturnContext($expr, $contextVar)" // Do not recurse into methods case q"$mods def $tname[..$tparams](...$paramss): $tpt = $expr" => tree - case other => super.transform(other) + case other => super.transform(other) } } @@ -163,26 +163,35 @@ class NamingTransforms(val c: Context) { def chiselName(annottees: c.Tree*): c.Tree = { var namedElts: Int = 0 - val transformed = annottees.map(annottee => annottee match { - case q"$mods class $tpname[..$tparams] $ctorMods(...$paramss) extends { ..$earlydefns } with ..$parents { $self => ..$stats }" => { - val transformedStats = transformClassBody(stats) - namedElts += 1 - q"$mods class $tpname[..$tparams] $ctorMods(...$paramss) extends { ..$earlydefns } with ..$parents { $self => ..$transformedStats }" - } - case q"$mods object $tname extends { ..$earlydefns } with ..$parents { $self => ..$body }" => { - annottee // Don't fail noisly when a companion object is passed in with the actual class def - } - // Currently disallow on traits, this won't work well with inheritance. - case q"$mods def $tname[..$tparams](...$paramss): $tpt = $expr" => { - val transformedExpr = transformHierarchicalMethod(expr) - namedElts += 1 - q"$mods def $tname[..$tparams](...$paramss): $tpt = $transformedExpr" + val transformed = annottees.map(annottee => + annottee match { + case q"$mods class $tpname[..$tparams] $ctorMods(...$paramss) extends { ..$earlydefns } with ..$parents { $self => ..$stats }" => { + val transformedStats = transformClassBody(stats) + namedElts += 1 + q"$mods class $tpname[..$tparams] $ctorMods(...$paramss) extends { ..$earlydefns } with ..$parents { $self => ..$transformedStats }" + } + case q"$mods object $tname extends { ..$earlydefns } with ..$parents { $self => ..$body }" => { + annottee // Don't fail noisly when a companion object is passed in with the actual class def + } + // Currently disallow on traits, this won't work well with inheritance. + case q"$mods def $tname[..$tparams](...$paramss): $tpt = $expr" => { + val transformedExpr = transformHierarchicalMethod(expr) + namedElts += 1 + q"$mods def $tname[..$tparams](...$paramss): $tpt = $transformedExpr" + } + case other => + c.abort( + c.enclosingPosition, + s"@chiselName annotion may only be used on classes and methods, got ${showCode(other)}" + ) } - case other => c.abort(c.enclosingPosition, s"@chiselName annotion may only be used on classes and methods, got ${showCode(other)}") - }) + ) if (namedElts != 1) { - c.abort(c.enclosingPosition, s"@chiselName annotation did not match exactly one valid tree, got:\r\n${annottees.map(tree => showCode(tree)).mkString("\r\n\r\n")}") + c.abort( + c.enclosingPosition, + s"@chiselName annotation did not match exactly one valid tree, got:\r\n${annottees.map(tree => showCode(tree)).mkString("\r\n\r\n")}" + ) } q"..$transformed" diff --git a/macros/src/main/scala/chisel3/internal/sourceinfo/SourceInfoTransform.scala b/macros/src/main/scala/chisel3/internal/sourceinfo/SourceInfoTransform.scala index ac3e236c..01e0acd6 100644 --- a/macros/src/main/scala/chisel3/internal/sourceinfo/SourceInfoTransform.scala +++ b/macros/src/main/scala/chisel3/internal/sourceinfo/SourceInfoTransform.scala @@ -9,7 +9,6 @@ import scala.language.experimental.macros import scala.reflect.macros.blackbox.Context import scala.reflect.macros.whitebox - /** Transforms a function call so that it can both provide implicit-style source information and * have a chained apply call. Without macros, only one is possible, since having a implicit * argument in the definition will cause the compiler to interpret a chained apply as an @@ -65,7 +64,6 @@ class DefinitionWrapTransform(val c: Context) extends SourceInfoTransformMacro { } } - // Workaround for https://github.com/sbt/sbt/issues/3966 object InstanceTransform // Module instantiation transform @@ -138,7 +136,7 @@ class VecTransform(val c: Context) extends SourceInfoTransformMacro { def reduceTree(redOp: c.Tree, layerOp: c.Tree): c.Tree = { q"$thisObj.do_reduceTree($redOp,$layerOp)($implicitSourceInfo, $implicitCompileOptions)" } - def reduceTreeDefault(redOp: c.Tree ): c.Tree = { + def reduceTreeDefault(redOp: c.Tree): c.Tree = { q"$thisObj.do_reduceTree($redOp)($implicitSourceInfo, $implicitCompileOptions)" } } @@ -148,13 +146,17 @@ class VecTransform(val c: Context) extends SourceInfoTransformMacro { */ abstract class AutoSourceTransform extends SourceInfoTransformMacro { import c.universe._ + /** Returns the TermName of the transformed function, which is the applied function name with do_ * prepended. */ def doFuncTerm: TermName = { val funcName = c.macroApplication match { case q"$_.$funcName[..$_](...$_)" => funcName - case _ => throw new Exception(s"Chisel Internal Error: Could not resolve function name from macro application: ${showCode(c.macroApplication)}") + case _ => + throw new Exception( + s"Chisel Internal Error: Could not resolve function name from macro application: ${showCode(c.macroApplication)}" + ) } TermName("do_" + funcName) } @@ -223,6 +225,7 @@ class CompileOptionsTransform(val c: Context) extends AutoSourceTransform { // Workaround for https://github.com/sbt/sbt/issues/3966 object SourceInfoWhiteboxTransform + /** Special whitebox version of the blackbox SourceInfoTransform, used when fun things need to * happen to satisfy the type system while preventing the use of macro overrides. */ diff --git a/plugin/src/main/scala/chisel3/internal/plugin/BundleComponent.scala b/plugin/src/main/scala/chisel3/internal/plugin/BundleComponent.scala index 67d744fc..2d3a2cae 100644 --- a/plugin/src/main/scala/chisel3/internal/plugin/BundleComponent.scala +++ b/plugin/src/main/scala/chisel3/internal/plugin/BundleComponent.scala @@ -22,20 +22,8 @@ private[plugin] class BundleComponent(val global: Global, arguments: ChiselPlugi private class BundlePhase(prev: Phase) extends StdPhase(prev) { override def name: String = phaseName def apply(unit: CompilationUnit): Unit = { - // This plugin doesn't work on Scala 2.11 nor Scala 3. Rather than complicate the sbt build flow, - // instead we just check the version and if its an early Scala version, the plugin does nothing - val scalaVersion = scala.util.Properties.versionNumberString.split('.') - val scalaVersionOk = scalaVersion(0).toInt == 2 && scalaVersion(1).toInt >= 12 - if (scalaVersionOk && arguments.useBundlePlugin) { + if (ChiselPlugin.runComponent(global, arguments)(unit)) { unit.body = new MyTypingTransformer(unit).transform(unit.body) - } else { - val reason = if (!scalaVersionOk) { - s"invalid Scala version '${scala.util.Properties.versionNumberString}'" - } else { - s"not enabled via '${arguments.useBundlePluginFullOpt}'" - } - // Enable this with scalacOption '-Ylog:chiselbundlephase' - global.log(s"Skipping BundleComponent on account of $reason.") } } } @@ -82,11 +70,9 @@ private[plugin] class BundleComponent(val global: Global, arguments: ChiselPlugi (primaryConstructor, paramAccessors.toList) } - override def transform(tree: Tree): Tree = tree match { case bundle: ClassDef if isBundle(bundle.symbol) && !bundle.mods.hasFlag(Flag.ABSTRACT) => - // ==================== Generate _cloneTypeImpl ==================== val (con, params) = getConstructorAndParams(bundle.impl.body) if (con.isEmpty) { @@ -111,13 +97,14 @@ private[plugin] class BundleComponent(val global: Global, arguments: ChiselPlugi if (isData(vp.symbol)) cloneTypeFull(select) else select }) - val tparamList = bundle.tparams.map{ t => Ident(t.symbol) } - val ttpe = if(tparamList.nonEmpty) AppliedTypeTree(Ident(bundle.symbol), tparamList) else Ident(bundle.symbol) + val tparamList = bundle.tparams.map { t => Ident(t.symbol) } + val ttpe = if (tparamList.nonEmpty) AppliedTypeTree(Ident(bundle.symbol), tparamList) else Ident(bundle.symbol) val newUntyped = New(ttpe, conArgs) val neww = localTyper.typed(newUntyped) // Create the symbol for the method and have it be associated with the Bundle class - val cloneTypeSym = bundle.symbol.newMethod(TermName("_cloneTypeImpl"), bundle.symbol.pos.focus, Flag.OVERRIDE | Flag.PROTECTED) + val cloneTypeSym = + bundle.symbol.newMethod(TermName("_cloneTypeImpl"), bundle.symbol.pos.focus, Flag.OVERRIDE | Flag.PROTECTED) // Handwritten cloneTypes don't have the Method flag set, unclear if it matters cloneTypeSym.resetFlag(Flags.METHOD) // Need to set the type to chisel3.Bundle for the override to work diff --git a/plugin/src/main/scala/chisel3/internal/plugin/ChiselComponent.scala b/plugin/src/main/scala/chisel3/internal/plugin/ChiselComponent.scala index af22e6a7..eced652b 100644 --- a/plugin/src/main/scala/chisel3/internal/plugin/ChiselComponent.scala +++ b/plugin/src/main/scala/chisel3/internal/plugin/ChiselComponent.scala @@ -11,7 +11,9 @@ import scala.tools.nsc.transform.TypingTransformers // The component of the chisel plugin. Not sure exactly what the difference is between // a Plugin and a PluginComponent. -class ChiselComponent(val global: Global) extends PluginComponent with TypingTransformers { +class ChiselComponent(val global: Global, arguments: ChiselPluginArguments) + extends PluginComponent + with TypingTransformers { import global._ val runsAfter: List[String] = List[String]("typer") val phaseName: String = "chiselcomponent" @@ -19,17 +21,13 @@ class ChiselComponent(val global: Global) extends PluginComponent with TypingTra class ChiselComponentPhase(prev: Phase) extends StdPhase(prev) { override def name: String = phaseName def apply(unit: CompilationUnit): Unit = { - // This plugin doesn't work on Scala 2.11 nor Scala 3. Rather than complicate the sbt build flow, - // instead we just check the version and if its an early Scala version, the plugin does nothing - val scalaVersion = scala.util.Properties.versionNumberString.split('.') - if (scalaVersion(0).toInt == 2 && scalaVersion(1).toInt >= 12) { + if (ChiselPlugin.runComponent(global, arguments)(unit)) { unit.body = new MyTypingTransformer(unit).transform(unit.body) } } } - class MyTypingTransformer(unit: CompilationUnit) - extends TypingTransformer(unit) { + class MyTypingTransformer(unit: CompilationUnit) extends TypingTransformer(unit) { private def shouldMatchGen(bases: Tree*): Type => Boolean = { val cache = mutable.HashMap.empty[Type, Boolean] @@ -54,7 +52,7 @@ class ChiselComponent(val global: Global) extends PluginComponent with TypingTra recShouldMatch(s.typeArgs.head, seen + s) } else { // This is the standard inheritance hierarchy, Scalac catches loops here - s.parents.exists( p => recShouldMatch(p, seen) ) + s.parents.exists(p => recShouldMatch(p, seen)) } } @@ -65,24 +63,25 @@ class ChiselComponent(val global: Global) extends PluginComponent with TypingTra // Return function so that it captures the cache { q: Type => - cache.getOrElseUpdate(q, { - // First check if a match, then check early exit, then recurse - if(terminate(q)){ - true - } else if(earlyExit(q)) { - false - } else { - recShouldMatch(q, Set.empty) + cache.getOrElseUpdate( + q, { + // First check if a match, then check early exit, then recurse + if (terminate(q)) { + true + } else if (earlyExit(q)) { + false + } else { + recShouldMatch(q, Set.empty) + } } - }) + ) } } - - private val shouldMatchData : Type => Boolean = shouldMatchGen(tq"chisel3.Data") - private val shouldMatchDataOrMem : Type => Boolean = shouldMatchGen(tq"chisel3.Data", tq"chisel3.MemBase[_]") - private val shouldMatchModule : Type => Boolean = shouldMatchGen(tq"chisel3.experimental.BaseModule") - private val shouldMatchInstance : Type => Boolean = shouldMatchGen(tq"chisel3.experimental.hierarchy.Instance[_]") + private val shouldMatchData: Type => Boolean = shouldMatchGen(tq"chisel3.Data") + private val shouldMatchDataOrMem: Type => Boolean = shouldMatchGen(tq"chisel3.Data", tq"chisel3.MemBase[_]") + private val shouldMatchModule: Type => Boolean = shouldMatchGen(tq"chisel3.experimental.BaseModule") + private val shouldMatchInstance: Type => Boolean = shouldMatchGen(tq"chisel3.experimental.hierarchy.Instance[_]") // Given a type tree, infer the type and return it private def inferType(t: Tree): Type = localTyper.typed(t, nsc.Mode.TYPEmode).tpe @@ -100,13 +99,13 @@ class ChiselComponent(val global: Global) extends PluginComponent with TypingTra Flags.CASEACCESSOR, Flags.PARAMACCESSOR ) - badFlags.forall{ x => !mods.hasFlag(x)} + badFlags.forall { x => !mods.hasFlag(x) } } // Ensure expression isn't null, as you can't call `null.autoName("myname")` val isNull = dd.rhs match { case Literal(Constant(null)) => true - case _ => false + case _ => false } okFlags(dd.mods) && !isNull && dd.rhs != EmptyTree @@ -133,7 +132,7 @@ class ChiselComponent(val global: Global) extends PluginComponent with TypingTra // Ensure expression isn't null, as you can't call `null.autoName("myname")` val isNull = dd.rhs match { case Literal(Constant(null)) => true - case _ => false + case _ => false } val tpe = inferType(dd.tpt) definitions.isTupleType(tpe) && okFlags(dd.mods) && !isNull && dd.rhs != EmptyTree @@ -142,7 +141,7 @@ class ChiselComponent(val global: Global) extends PluginComponent with TypingTra private def findUnapplyNames(tree: Tree): Option[List[String]] = { val applyArgs: Option[List[Tree]] = tree match { case Match(_, List(CaseDef(_, _, Apply(_, args)))) => Some(args) - case _ => None + case _ => None } applyArgs.flatMap { args => var ok = true @@ -150,7 +149,7 @@ class ChiselComponent(val global: Global) extends PluginComponent with TypingTra args.foreach { case Ident(TermName(name)) => result += name // Anything unexpected and we abort - case _ => ok = false + case _ => ok = false } if (ok) Some(result.toList) else None } @@ -172,9 +171,9 @@ class ChiselComponent(val global: Global) extends PluginComponent with TypingTra // If a Data and in a Bundle, just get the name but not a prefix if (shouldMatchData(tpe) && inBundle(dd)) { val str = stringFromTermName(name) - val newRHS = transform(rhs) // chisel3.internal.plugin.autoNameRecursively + val newRHS = transform(rhs) // chisel3.internal.plugin.autoNameRecursively val named = q"chisel3.internal.plugin.autoNameRecursively($str)($newRHS)" - treeCopy.ValDef(dd, mods, name, tpt, localTyper typed named) + treeCopy.ValDef(dd, mods, name, tpt, localTyper.typed(named)) } // If a Data or a Memory, get the name and a prefix else if (shouldMatchDataOrMem(tpe)) { @@ -182,18 +181,18 @@ class ChiselComponent(val global: Global) extends PluginComponent with TypingTra val newRHS = transform(rhs) val prefixed = q"chisel3.experimental.prefix.apply[$tpt](name=$str)(f=$newRHS)" val named = q"chisel3.internal.plugin.autoNameRecursively($str)($prefixed)" - treeCopy.ValDef(dd, mods, name, tpt, localTyper typed named) + treeCopy.ValDef(dd, mods, name, tpt, localTyper.typed(named)) // If an instance, just get a name but no prefix } else if (shouldMatchModule(tpe)) { val str = stringFromTermName(name) val newRHS = transform(rhs) val named = q"chisel3.internal.plugin.autoNameRecursively($str)($newRHS)" - treeCopy.ValDef(dd, mods, name, tpt, localTyper typed named) + treeCopy.ValDef(dd, mods, name, tpt, localTyper.typed(named)) } else if (shouldMatchInstance(tpe)) { val str = stringFromTermName(name) val newRHS = transform(rhs) val named = q"chisel3.internal.plugin.autoNameRecursively($str)($newRHS)" - treeCopy.ValDef(dd, mods, name, tpt, localTyper typed named) + treeCopy.ValDef(dd, mods, name, tpt, localTyper.typed(named)) } else { // Otherwise, continue super.transform(tree) @@ -205,9 +204,10 @@ class ChiselComponent(val global: Global) extends PluginComponent with TypingTra if (fieldsOfInterest.reduce(_ || _)) { findUnapplyNames(rhs) match { case Some(names) => - val onames: List[Option[String]] = fieldsOfInterest.zip(names).map { case (ok, name) => if (ok) Some(name) else None } + val onames: List[Option[String]] = + fieldsOfInterest.zip(names).map { case (ok, name) => if (ok) Some(name) else None } val named = q"chisel3.internal.plugin.autoNameRecursivelyProduct($onames)($rhs)" - treeCopy.ValDef(dd, mods, name, tpt, localTyper typed named) + treeCopy.ValDef(dd, mods, name, tpt, localTyper.typed(named)) case None => // It's not clear how this could happen but we don't want to crash super.transform(tree) } diff --git a/plugin/src/main/scala/chisel3/internal/plugin/ChiselPlugin.scala b/plugin/src/main/scala/chisel3/internal/plugin/ChiselPlugin.scala index 23082329..bd02d50c 100644 --- a/plugin/src/main/scala/chisel3/internal/plugin/ChiselPlugin.scala +++ b/plugin/src/main/scala/chisel3/internal/plugin/ChiselPlugin.scala @@ -6,19 +6,53 @@ import scala.tools.nsc import nsc.Global import nsc.plugins.{Plugin, PluginComponent} import scala.reflect.internal.util.NoPosition +import scala.collection.mutable -private[plugin] case class ChiselPluginArguments(var useBundlePlugin: Boolean = true) { +private[plugin] case class ChiselPluginArguments(val skipFiles: mutable.HashSet[String] = mutable.HashSet.empty) { def useBundlePluginOpt = "useBundlePlugin" - def useBundlePluginFullOpt = s"-P:chiselplugin:$useBundlePluginOpt" + def useBundlePluginFullOpt = s"-P:${ChiselPlugin.name}:$useBundlePluginOpt" + + // Annoying because this shouldn't be used by users + def skipFilePluginOpt = "INTERNALskipFile:" + def skipFilePluginFullOpt = s"-P:${ChiselPlugin.name}:$skipFilePluginOpt" +} + +object ChiselPlugin { + val name = "chiselplugin" + + // Also logs why the compoennt was not run + private[plugin] def runComponent( + global: Global, + arguments: ChiselPluginArguments + )(unit: global.CompilationUnit + ): Boolean = { + // This plugin doesn't work on Scala 2.11 nor Scala 3. Rather than complicate the sbt build flow, + // instead we just check the version and if its an early Scala version, the plugin does nothing + val scalaVersion = scala.util.Properties.versionNumberString.split('.') + val scalaVersionOk = scalaVersion(0).toInt == 2 && scalaVersion(1).toInt >= 12 + val skipFile = arguments.skipFiles(unit.source.file.path) + if (scalaVersionOk && !skipFile) { + true + } else { + val reason = if (!scalaVersionOk) { + s"invalid Scala version '${scala.util.Properties.versionNumberString}'" + } else { + s"file skipped via '${arguments.skipFilePluginFullOpt}'" + } + // Enable this with scalacOption '-Ylog:chiselbundlephase' + global.log(s"Skipping BundleComponent on account of $reason.") + false + } + } } // The plugin to be run by the Scala compiler during compilation of Chisel code class ChiselPlugin(val global: Global) extends Plugin { - val name = "chiselplugin" + val name = ChiselPlugin.name val description = "Plugin for Chisel 3 Hardware Description Language" private val arguments = ChiselPluginArguments() val components: List[PluginComponent] = List[PluginComponent]( - new ChiselComponent(global), + new ChiselComponent(global, arguments), new BundleComponent(global, arguments) ) @@ -27,6 +61,12 @@ class ChiselPlugin(val global: Global) extends Plugin { if (option == arguments.useBundlePluginOpt) { val msg = s"'${arguments.useBundlePluginFullOpt}' is now default behavior, you can stop using the scalacOption." global.reporter.warning(NoPosition, msg) + } else if (option.startsWith(arguments.skipFilePluginOpt)) { + val filename = option.stripPrefix(arguments.skipFilePluginOpt) + arguments.skipFiles += filename + // Be annoying and warn because users are not supposed to use this + val msg = s"Option -P:${ChiselPlugin.name}:$option should only be used for internal chisel3 compiler purposes!" + global.reporter.warning(NoPosition, msg) } else { error(s"Option not understood: '$option'") } @@ -34,6 +74,4 @@ class ChiselPlugin(val global: Global) extends Plugin { true } - } - diff --git a/project/plugins.sbt b/project/plugins.sbt index 8c19290c..f09e1a1b 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -24,5 +24,7 @@ addSbtPlugin("com.typesafe" % "sbt-mima-plugin" % "1.0.1") addSbtPlugin("com.github.sbt" % "sbt-ci-release" % "1.5.10") +addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.6") + // From FIRRTL for building from source addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.9.33") diff --git a/src/main/scala/chisel3/Driver.scala b/src/main/scala/chisel3/Driver.scala index aa379629..30a97df6 100644 --- a/src/main/scala/chisel3/Driver.scala +++ b/src/main/scala/chisel3/Driver.scala @@ -17,7 +17,8 @@ trait BackendCompilationUtilities extends LazyLogging { lazy val TestDirectory = FirrtlBackendCompilationUtilities.TestDirectory def timeStamp: String = FirrtlBackendCompilationUtilities.timeStamp def loggingProcessLogger: ProcessLogger = FirrtlBackendCompilationUtilities.loggingProcessLogger - def copyResourceToFile(name: String, file: File): Unit = FirrtlBackendCompilationUtilities.copyResourceToFile(name, file) + def copyResourceToFile(name: String, file: File): Unit = + FirrtlBackendCompilationUtilities.copyResourceToFile(name, file) def createTestDirectory(testName: String): File = FirrtlBackendCompilationUtilities.createTestDirectory(testName) def makeHarness(template: String => String, post: String)(f: File): File = FirrtlBackendCompilationUtilities.makeHarness(template, post)(f) @@ -98,10 +99,9 @@ trait BackendCompilationUtilities extends LazyLogging { import firrtl.stage.FirrtlCircuitAnnotation options.collectFirst { case a: FirrtlCircuitAnnotation => a.circuit } match { - case None => false + case None => false case Some(_) => true } // ********************************************************************************************* } } - diff --git a/src/main/scala/chisel3/aop/AspectLibrary.scala b/src/main/scala/chisel3/aop/AspectLibrary.scala index 1a16b61f..04ac2384 100644 --- a/src/main/scala/chisel3/aop/AspectLibrary.scala +++ b/src/main/scala/chisel3/aop/AspectLibrary.scala @@ -8,7 +8,7 @@ import firrtl.options.{OptionsException, RegisteredLibrary, ShellOption} /** Enables adding aspects to a design from the commandline, e.g. * sbt> runMain chisel3.stage.ChiselMain --module <module> --with-aspect <aspect> */ -final class AspectLibrary() extends RegisteredLibrary { +final class AspectLibrary() extends RegisteredLibrary { val name = "AspectLibrary" import scala.reflect.runtime.universe._ @@ -34,16 +34,20 @@ final class AspectLibrary() extends RegisteredLibrary { throw new OptionsException(s"Unable to locate aspect '$aspectName'! (Did you misspell it?)", e) case e: InstantiationException => throw new OptionsException( - s"Unable to create instance of aspect '$aspectName'! (Does this class take parameters?)", e) + s"Unable to create instance of aspect '$aspectName'! (Does this class take parameters?)", + e + ) } } - val options = Seq(new ShellOption[String]( - longOption = "with-aspect", - toAnnotationSeq = { - case aspectName: String => Seq(apply(aspectName)) - }, - helpText = "The name/class of an aspect to compile with (must be a class/object without arguments!)", - helpValueName = Some("<package>.<aspect>") - )) + val options = Seq( + new ShellOption[String]( + longOption = "with-aspect", + toAnnotationSeq = { + case aspectName: String => Seq(apply(aspectName)) + }, + helpText = "The name/class of an aspect to compile with (must be a class/object without arguments!)", + helpValueName = Some("<package>.<aspect>") + ) + ) } diff --git a/src/main/scala/chisel3/aop/Select.scala b/src/main/scala/chisel3/aop/Select.scala index 8f5a2577..3a2a8931 100644 --- a/src/main/scala/chisel3/aop/Select.scala +++ b/src/main/scala/chisel3/aop/Select.scala @@ -47,17 +47,18 @@ object Select { */ def instancesIn(parent: Hierarchy[BaseModule]): Seq[Instance[BaseModule]] = { check(parent) - implicit val mg = new chisel3.internal.MacroGenerated{} + implicit val mg = new chisel3.internal.MacroGenerated {} parent.proto._component.get match { - case d: DefModule => d.commands.collect { - case d: DefInstance => - d.id match { - case p: chisel3.internal.BaseModule.IsClone[_] => - parent._lookup { x => new Instance(Clone(p)).asInstanceOf[Instance[BaseModule]] } - case other: BaseModule => - parent._lookup { x => other } - } - } + case d: DefModule => + d.commands.collect { + case d: DefInstance => + d.id match { + case p: chisel3.internal.BaseModule.IsClone[_] => + parent._lookup { x => new Instance(Clone(p)).asInstanceOf[Instance[BaseModule]] } + case other: BaseModule => + parent._lookup { x => other } + } + } case other => Nil } } @@ -65,24 +66,27 @@ object Select { /** Selects all Instances of instances/modules directly instantiated within given module, of provided type * * @note IMPORTANT: this function requires summoning a TypeTag[T], which will fail if T is an inner class. + * @note IMPORTANT: this function ignores type parameters. E.g. instancesOf[List[Int]] would return List[String]. + * * @param parent hierarchy which instantiates the returned Definitions */ - def instancesOf[T <: BaseModule : TypeTag](parent: Hierarchy[BaseModule]): Seq[Instance[T]] = { + def instancesOf[T <: BaseModule: TypeTag](parent: Hierarchy[BaseModule]): Seq[Instance[T]] = { check(parent) - implicit val mg = new chisel3.internal.MacroGenerated{} + implicit val mg = new chisel3.internal.MacroGenerated {} parent.proto._component.get match { - case d: DefModule => d.commands.flatMap { - case d: DefInstance => - d.id match { - case p: chisel3.internal.BaseModule.IsClone[_] => - val i = parent._lookup { x => new Instance(Clone(p)).asInstanceOf[Instance[BaseModule]] } - if(i.isA[T]) Some(i.asInstanceOf[Instance[T]]) else None - case other: BaseModule => - val i = parent._lookup { x => other } - if(i.isA[T]) Some(i.asInstanceOf[Instance[T]]) else None - } - case other => None - } + case d: DefModule => + d.commands.flatMap { + case d: DefInstance => + d.id match { + case p: chisel3.internal.BaseModule.IsClone[_] => + val i = parent._lookup { x => new Instance(Clone(p)).asInstanceOf[Instance[BaseModule]] } + if (i.isA[T]) Some(i.asInstanceOf[Instance[T]]) else None + case other: BaseModule => + val i = parent._lookup { x => other } + if (i.isA[T]) Some(i.asInstanceOf[Instance[T]]) else None + } + case other => None + } case other => Nil } } @@ -90,66 +94,73 @@ object Select { /** Selects all Instances directly and indirectly instantiated within given root hierarchy, of provided type * * @note IMPORTANT: this function requires summoning a TypeTag[T], which will fail if T is an inner class. + * @note IMPORTANT: this function ignores type parameters. E.g. allInstancesOf[List[Int]] would return List[String]. + * * @param root top of the hierarchy to search for instances/modules of given type */ - def allInstancesOf[T <: BaseModule : TypeTag](root: Hierarchy[BaseModule]): Seq[Instance[T]] = { - val soFar = if(root.isA[T]) Seq(root.toInstance.asInstanceOf[Instance[T]]) else Nil + def allInstancesOf[T <: BaseModule: TypeTag](root: Hierarchy[BaseModule]): Seq[Instance[T]] = { + val soFar = if (root.isA[T]) Seq(root.toInstance.asInstanceOf[Instance[T]]) else Nil val allLocalInstances = instancesIn(root) soFar ++ (allLocalInstances.flatMap(allInstancesOf[T])) } /** Selects the Definitions of all instances/modules directly instantiated within given module - * + * * @param parent */ def definitionsIn(parent: Hierarchy[BaseModule]): Seq[Definition[BaseModule]] = { type DefType = Definition[BaseModule] - implicit val mg = new chisel3.internal.MacroGenerated{} + implicit val mg = new chisel3.internal.MacroGenerated {} check(parent) val defs = parent.proto._component.get match { - case d: DefModule => d.commands.collect { - case i: DefInstance => - i.id match { - case p: chisel3.internal.BaseModule.IsClone[_] => - parent._lookup { x => new Definition(Proto(p.getProto)).asInstanceOf[Definition[BaseModule]] } - case other: BaseModule => - parent._lookup { x => other.toDefinition } - } - } + case d: DefModule => + d.commands.collect { + case i: DefInstance => + i.id match { + case p: chisel3.internal.BaseModule.IsClone[_] => + parent._lookup { x => new Definition(Proto(p.getProto)).asInstanceOf[Definition[BaseModule]] } + case other: BaseModule => + parent._lookup { x => other.toDefinition } + } + } case other => Nil } - val (_, defList) = defs.foldLeft((Set.empty[DefType], List.empty[DefType])) { case ((set, list), definition: Definition[BaseModule]) => - if(set.contains(definition)) (set, list) else (set + definition, definition +: list) + val (_, defList) = defs.foldLeft((Set.empty[DefType], List.empty[DefType])) { + case ((set, list), definition: Definition[BaseModule]) => + if (set.contains(definition)) (set, list) else (set + definition, definition +: list) } defList.reverse } - /** Selects all Definitions of instances/modules directly instantiated within given module, of provided type * * @note IMPORTANT: this function requires summoning a TypeTag[T], which will fail if T is an inner class. + * @note IMPORTANT: this function ignores type parameters. E.g. definitionsOf[List[Int]] would return List[String]. + * * @param parent hierarchy which instantiates the returned Definitions */ - def definitionsOf[T <: BaseModule : TypeTag](parent: Hierarchy[BaseModule]): Seq[Definition[T]] = { + def definitionsOf[T <: BaseModule: TypeTag](parent: Hierarchy[BaseModule]): Seq[Definition[T]] = { check(parent) - implicit val mg = new chisel3.internal.MacroGenerated{} + implicit val mg = new chisel3.internal.MacroGenerated {} type DefType = Definition[T] val defs = parent.proto._component.get match { - case d: DefModule => d.commands.flatMap { - case d: DefInstance => - d.id match { - case p: chisel3.internal.BaseModule.IsClone[_] => - val d = parent._lookup { x => new Definition(Clone(p)).asInstanceOf[Definition[BaseModule]] } - if(d.isA[T]) Some(d.asInstanceOf[Definition[T]]) else None - case other: BaseModule => - val d = parent._lookup { x => other.toDefinition } - if(d.isA[T]) Some(d.asInstanceOf[Definition[T]]) else None - } - case other => None - } + case d: DefModule => + d.commands.flatMap { + case d: DefInstance => + d.id match { + case p: chisel3.internal.BaseModule.IsClone[_] => + val d = parent._lookup { x => new Definition(Clone(p)).asInstanceOf[Definition[BaseModule]] } + if (d.isA[T]) Some(d.asInstanceOf[Definition[T]]) else None + case other: BaseModule => + val d = parent._lookup { x => other.toDefinition } + if (d.isA[T]) Some(d.asInstanceOf[Definition[T]]) else None + } + case other => None + } } - val (_, defList) = defs.foldLeft((Set.empty[DefType], List.empty[DefType])) { case ((set, list), definition: Definition[T]) => - if(set.contains(definition)) (set, list) else (set + definition, definition +: list) + val (_, defList) = defs.foldLeft((Set.empty[DefType], List.empty[DefType])) { + case ((set, list), definition: Definition[T]) => + if (set.contains(definition)) (set, list) else (set + definition, definition +: list) } defList.reverse } @@ -158,16 +169,18 @@ object Select { * * @note IMPORTANT: this function requires summoning a TypeTag[T], which will fail if T is an inner class, i.e. * a class defined within another class. + * @note IMPORTANT: this function ignores type parameters. E.g. allDefinitionsOf[List[Int]] would return List[String]. + * * @param root top of the hierarchy to search for definitions of given type */ - def allDefinitionsOf[T <: BaseModule : TypeTag](root: Hierarchy[BaseModule]): Seq[Definition[T]] = { + def allDefinitionsOf[T <: BaseModule: TypeTag](root: Hierarchy[BaseModule]): Seq[Definition[T]] = { type DefType = Definition[T] val allDefSet = mutable.HashSet[Definition[BaseModule]]() val defSet = mutable.HashSet[DefType]() val defList = mutable.ArrayBuffer[DefType]() def rec(hier: Definition[BaseModule]): Unit = { - if(hier.isA[T] && !defSet.contains(hier.asInstanceOf[DefType])) { - defSet += hier.asInstanceOf[DefType] + if (hier.isA[T] && !defSet.contains(hier.asInstanceOf[DefType])) { + defSet += hier.asInstanceOf[DefType] defList += hier.asInstanceOf[DefType] } allDefSet += hier @@ -180,7 +193,6 @@ object Select { defList.toList } - /** Collects all components selected by collector within module and all children modules it instantiates * directly or indirectly * Accepts a collector function, rather than a collector partial function (see [[collectDeep]]) @@ -195,8 +207,8 @@ object Select { def getDeep[T](module: BaseModule)(collector: BaseModule => Seq[T]): Seq[T] = { check(module) val myItems = collector(module) - val deepChildrenItems = instances(module).flatMap { - i => getDeep(i)(collector) + val deepChildrenItems = instances(module).flatMap { i => + getDeep(i)(collector) } myItems ++ deepChildrenItems } @@ -215,8 +227,8 @@ object Select { def collectDeep[T](module: BaseModule)(collector: PartialFunction[BaseModule, T]): Iterable[T] = { check(module) val myItems = collector.lift(module) - val deepChildrenItems = instances(module).flatMap { - i => collectDeep(i)(collector) + val deepChildrenItems = instances(module).flatMap { i => + collectDeep(i)(collector) } myItems ++ deepChildrenItems } @@ -230,14 +242,19 @@ object Select { def instances(module: BaseModule): Seq[BaseModule] = { check(module) module._component.get match { - case d: DefModule => d.commands.flatMap { - case i: DefInstance => i.id match { - case m: ModuleClone[_] if !m._madeFromDefinition => None - case _: PseudoModule => throw new Exception("instances, collectDeep, and getDeep are currently incompatible with Definition/Instance!") - case other => Some(other) + case d: DefModule => + d.commands.flatMap { + case i: DefInstance => + i.id match { + case m: ModuleClone[_] if !m._madeFromDefinition => None + case _: PseudoModule => + throw new Exception( + "instances, collectDeep, and getDeep are currently incompatible with Definition/Instance!" + ) + case other => Some(other) + } + case _ => None } - case _ => None - } case other => Nil } } @@ -248,12 +265,12 @@ object Select { def registers(module: BaseModule): Seq[Data] = { check(module) module._component.get.asInstanceOf[DefModule].commands.collect { - case r: DefReg => r.id + case r: DefReg => r.id case r: DefRegInit => r.id } } - /** Selects all ios directly contained within given module + /** Selects all ios on a given module * @param module */ def ios(module: BaseModule): Seq[Data] = { @@ -261,6 +278,15 @@ object Select { module._component.get.asInstanceOf[DefModule].ports.map(_.id) } + /** Selects all ios directly on a given Instance or Definition of a module + * @param parent the Definition or Instance to get the IOs of + */ + def ios[T <: BaseModule](parent: Hierarchy[T]): Seq[Data] = { + check(parent) + implicit val mg = new chisel3.internal.MacroGenerated {} + parent._lookup { x => ios(parent.proto) } + } + /** Selects all SyncReadMems directly contained within given module * @param module */ @@ -349,9 +375,14 @@ object Select { */ def attachedTo(module: BaseModule)(signal: Data): Set[Data] = { check(module) - module._component.get.asInstanceOf[DefModule].commands.collect { - case Attach(_, seq) if seq.contains(signal) => seq - }.flatMap { seq => seq.map(_.id.asInstanceOf[Data]) }.toSet + module._component.get + .asInstanceOf[DefModule] + .commands + .collect { + case Attach(_, seq) if seq.contains(signal) => seq + } + .flatMap { seq => seq.map(_.id.asInstanceOf[Data]) } + .toSet } /** Selects all connections to a signal or its parent signal(s) (if the signal is an element of an aggregate signal) @@ -365,31 +396,42 @@ object Select { check(module) val sensitivitySignals = getIntermediateAndLeafs(signal).toSet val predicatedConnects = mutable.ArrayBuffer[PredicatedConnect]() - val isPort = module._component.get.asInstanceOf[DefModule].ports.flatMap{ p => getIntermediateAndLeafs(p.id) }.contains(signal) + val isPort = module._component.get + .asInstanceOf[DefModule] + .ports + .flatMap { p => getIntermediateAndLeafs(p.id) } + .contains(signal) var prePredicates: Seq[Predicate] = Nil var seenDef = isPort - searchWhens(module, (cmd: Command, preds) => { - cmd match { - case cmd: DefinitionIR if cmd.id.isInstanceOf[Data] => - val x = getIntermediateAndLeafs(cmd.id.asInstanceOf[Data]) - if(x.contains(signal)) prePredicates = preds - case Connect(_, loc@Node(d: Data), exp) => - val effected = getEffected(loc).toSet - if(sensitivitySignals.intersect(effected).nonEmpty) { - val expData = getData(exp) - prePredicates.reverse.zip(preds.reverse).foreach(x => assert(x._1 == x._2, s"Prepredicates $x must match for signal $signal")) - predicatedConnects += PredicatedConnect(preds.dropRight(prePredicates.size), d, expData, isBulk = false) - } - case BulkConnect(_, loc@Node(d: Data), exp) => - val effected = getEffected(loc).toSet - if(sensitivitySignals.intersect(effected).nonEmpty) { - val expData = getData(exp) - prePredicates.reverse.zip(preds.reverse).foreach(x => assert(x._1 == x._2, s"Prepredicates $x must match for signal $signal")) - predicatedConnects += PredicatedConnect(preds.dropRight(prePredicates.size), d, expData, isBulk = true) - } - case other => + searchWhens( + module, + (cmd: Command, preds) => { + cmd match { + case cmd: DefinitionIR if cmd.id.isInstanceOf[Data] => + val x = getIntermediateAndLeafs(cmd.id.asInstanceOf[Data]) + if (x.contains(signal)) prePredicates = preds + case Connect(_, loc @ Node(d: Data), exp) => + val effected = getEffected(loc).toSet + if (sensitivitySignals.intersect(effected).nonEmpty) { + val expData = getData(exp) + prePredicates.reverse + .zip(preds.reverse) + .foreach(x => assert(x._1 == x._2, s"Prepredicates $x must match for signal $signal")) + predicatedConnects += PredicatedConnect(preds.dropRight(prePredicates.size), d, expData, isBulk = false) + } + case BulkConnect(_, loc @ Node(d: Data), exp) => + val effected = getEffected(loc).toSet + if (sensitivitySignals.intersect(effected).nonEmpty) { + val expData = getData(exp) + prePredicates.reverse + .zip(preds.reverse) + .foreach(x => assert(x._1 == x._2, s"Prepredicates $x must match for signal $signal")) + predicatedConnects += PredicatedConnect(preds.dropRight(prePredicates.size), d, expData, isBulk = true) + } + case other => + } } - }) + ) predicatedConnects.toSeq } @@ -397,14 +439,18 @@ object Select { * * @param module */ - def stops(module: BaseModule): Seq[Stop] = { + def stops(module: BaseModule): Seq[Stop] = { val stops = mutable.ArrayBuffer[Stop]() - searchWhens(module, (cmd: Command, preds: Seq[Predicate]) => { - cmd match { - case chisel3.internal.firrtl.Stop(_, _, clock, ret) => stops += Stop(preds, ret, getId(clock).asInstanceOf[Clock]) - case other => + searchWhens( + module, + (cmd: Command, preds: Seq[Predicate]) => { + cmd match { + case chisel3.internal.firrtl.Stop(_, _, clock, ret) => + stops += Stop(preds, ret, getId(clock).asInstanceOf[Clock]) + case other => + } } - }) + ) stops.toSeq } @@ -414,12 +460,16 @@ object Select { */ def printfs(module: BaseModule): Seq[Printf] = { val printfs = mutable.ArrayBuffer[Printf]() - searchWhens(module, (cmd: Command, preds: Seq[Predicate]) => { - cmd match { - case chisel3.internal.firrtl.Printf(id, _, clock, pable) => printfs += Printf(id, preds, pable, getId(clock).asInstanceOf[Clock]) - case other => + searchWhens( + module, + (cmd: Command, preds: Seq[Predicate]) => { + cmd match { + case chisel3.internal.firrtl.Printf(id, _, clock, pable) => + printfs += Printf(id, preds, pable, getId(clock).asInstanceOf[Clock]) + case other => + } } - }) + ) printfs.toSeq } @@ -433,15 +483,15 @@ object Select { // Given a loc, return all subcomponents of id that could be assigned to in connect private def getEffected(a: Arg): Seq[Data] = a match { case Node(id: Data) => getIntermediateAndLeafs(id) - case Slot(imm, name) => Seq(imm.id.asInstanceOf[Record].elements(name)) + case Slot(imm, name) => Seq(imm.id.asInstanceOf[Record].elements(name)) case Index(imm, value) => getEffected(imm) } // Given an arg, return the corresponding id. Don't use on a loc of a connect. private def getId(a: Arg): HasId = a match { case Node(id) => id - case l: ULit => l.num.U(l.w) - case l: SLit => l.num.S(l.w) + case l: ULit => l.num.U(l.w) + case l: SLit => l.num.S(l.w) case l: FPLit => FixedPoint(l.num, l.w, l.binaryPoint) case other => sys.error(s"Something went horribly wrong! I was expecting ${other} to be a lit or a node!") @@ -461,9 +511,10 @@ object Select { str.splitAt(str.indexOf('>'))._2.drop(1) } } catch { - case e: ChiselException => i.getOptionRef.get match { - case l: LitArg => l.num.intValue.toString - } + case e: ChiselException => + i.getOptionRef.get match { + case l: LitArg => l.num.intValue.toString + } } // Collects when predicates as it searches through a module, then applying processCommand to non-when related commands @@ -472,21 +523,22 @@ object Select { module._component.get.asInstanceOf[DefModule].commands.foldLeft((Seq.empty[Predicate], Option.empty[Predicate])) { (blah, cmd) => (blah, cmd) match { - case ((preds, o), cmd) => cmd match { - case WhenBegin(_, Node(pred: Bool)) => (When(pred) +: preds, None) - case WhenBegin(_, l: LitArg) if l.num == BigInt(1) => (When(true.B) +: preds, None) - case WhenBegin(_, l: LitArg) if l.num == BigInt(0) => (When(false.B) +: preds, None) - case other: WhenBegin => - sys.error(s"Something went horribly wrong! I was expecting ${other.pred} to be a lit or a bool!") - case _: WhenEnd => (preds.tail, Some(preds.head)) - case AltBegin(_) if o.isDefined => (o.get.not +: preds, o) - case _: AltBegin => - sys.error(s"Something went horribly wrong! I was expecting ${o} to be nonEmpty!") - case OtherwiseEnd(_, _) => (preds.tail, None) - case other => - processCommand(cmd, preds) - (preds, o) - } + case ((preds, o), cmd) => + cmd match { + case WhenBegin(_, Node(pred: Bool)) => (When(pred) +: preds, None) + case WhenBegin(_, l: LitArg) if l.num == BigInt(1) => (When(true.B) +: preds, None) + case WhenBegin(_, l: LitArg) if l.num == BigInt(0) => (When(false.B) +: preds, None) + case other: WhenBegin => + sys.error(s"Something went horribly wrong! I was expecting ${other.pred} to be a lit or a bool!") + case _: WhenEnd => (preds.tail, Some(preds.head)) + case AltBegin(_) if o.isDefined => (o.get.not +: preds, o) + case _: AltBegin => + sys.error(s"Something went horribly wrong! I was expecting ${o} to be nonEmpty!") + case OtherwiseEnd(_, _) => (preds.tail, None) + case other => + processCommand(cmd, preds) + (preds, o) + } } } } @@ -507,7 +559,7 @@ object Select { * @param bool the when predicate */ case class When(bool: Bool) extends Predicate { - def not: WhenNot = WhenNot(bool) + def not: WhenNot = WhenNot(bool) def serialize: String = s"${getName(bool)}" } @@ -516,7 +568,7 @@ object Select { * @param bool the when predicate corresponding to this otherwise predicate */ case class WhenNot(bool: Bool) extends Predicate { - def not: When = When(bool) + def not: When = When(bool) def serialize: String = s"!${getName(bool)}" } @@ -532,7 +584,7 @@ object Select { case class PredicatedConnect(preds: Seq[Predicate], loc: Data, exp: Data, isBulk: Boolean) extends Serializeable { def serialize: String = { val moduleTarget = loc.toTarget.moduleTarget.serialize - s"$moduleTarget: when(${preds.map(_.serialize).mkString(" & ")}): ${getName(loc)} ${if(isBulk) "<>" else ":="} ${getName(exp)}" + s"$moduleTarget: when(${preds.map(_.serialize).mkString(" & ")}): ${getName(loc)} ${if (isBulk) "<>" else ":="} ${getName(exp)}" } } diff --git a/src/main/scala/chisel3/aop/injecting/InjectStatement.scala b/src/main/scala/chisel3/aop/injecting/InjectStatement.scala index 92e24ba1..dbe1fd7b 100644 --- a/src/main/scala/chisel3/aop/injecting/InjectStatement.scala +++ b/src/main/scala/chisel3/aop/injecting/InjectStatement.scala @@ -15,7 +15,12 @@ import firrtl.annotations.{Annotation, ModuleTarget, NoTargetAnnotation, SingleT * @param modules Additional modules that may be instantiated by s * @param annotations Additional annotations that should be passed down compiler */ -case class InjectStatement(module: ModuleTarget, s: firrtl.ir.Statement, modules: Seq[firrtl.ir.DefModule], annotations: Seq[Annotation]) extends SingleTargetAnnotation[ModuleTarget] { +case class InjectStatement( + module: ModuleTarget, + s: firrtl.ir.Statement, + modules: Seq[firrtl.ir.DefModule], + annotations: Seq[Annotation]) + extends SingleTargetAnnotation[ModuleTarget] { val target: ModuleTarget = module override def duplicate(n: ModuleTarget): Annotation = this.copy(module = n) } diff --git a/src/main/scala/chisel3/aop/injecting/InjectingAspect.scala b/src/main/scala/chisel3/aop/injecting/InjectingAspect.scala index dc7e6487..abe208cf 100644 --- a/src/main/scala/chisel3/aop/injecting/InjectingAspect.scala +++ b/src/main/scala/chisel3/aop/injecting/InjectingAspect.scala @@ -2,9 +2,8 @@ package chisel3.aop.injecting -import chisel3.{Module, ModuleAspect, RawModule, withClockAndReset} +import chisel3.{withClockAndReset, Module, ModuleAspect, RawModule} import chisel3.aop._ -import chisel3.experimental.hierarchy.IsInstantiable import chisel3.internal.{Builder, DynamicContext} import chisel3.internal.firrtl.DefModule import chisel3.stage.DesignAnnotation @@ -23,12 +22,12 @@ import scala.collection.mutable * @tparam M Type of root module (join point) */ case class InjectingAspect[T <: RawModule, M <: RawModule]( - selectRoots: T => Iterable[M], - injection: M => Unit -) extends InjectorAspect[T, M]( - selectRoots, - injection -) + selectRoots: T => Iterable[M], + injection: M => Unit) + extends InjectorAspect[T, M]( + selectRoots, + injection + ) /** Extend to inject Chisel code into a module of type M * @@ -39,11 +38,12 @@ case class InjectingAspect[T <: RawModule, M <: RawModule]( * @tparam M Type of root module (join point) */ abstract class InjectorAspect[T <: RawModule, M <: RawModule]( - selectRoots: T => Iterable[M], - injection: M => Unit -) extends Aspect[T] { + selectRoots: T => Iterable[M], + injection: M => Unit) + extends Aspect[T] { final def toAnnotation(top: T): AnnotationSeq = { - val moduleNames = Select.allDefinitionsOf[chisel3.experimental.BaseModule](top.toDefinition).map{i => i.toTarget.module }.toSeq + val moduleNames = + Select.allDefinitionsOf[chisel3.experimental.BaseModule](top.toDefinition).map { i => i.toTarget.module }.toSeq toAnnotation(selectRoots(top), top.name, moduleNames) } @@ -63,22 +63,26 @@ abstract class InjectorAspect[T <: RawModule, M <: RawModule]( dynamicContext.globalNamespace.name(n) } - val (chiselIR, _) = Builder.build(Module(new ModuleAspect(module) { - module match { - case x: Module => withClockAndReset(x.clock, x.reset) { injection(module) } - case x: RawModule => injection(module) - } - }), dynamicContext) + val (chiselIR, _) = Builder.build( + Module(new ModuleAspect(module) { + module match { + case x: Module => withClockAndReset(x.clock, x.reset) { injection(module) } + case x: RawModule => injection(module) + } + }), + dynamicContext + ) val comps = chiselIR.components.map { case x: DefModule if x.name == module.name => x.copy(id = module) case other => other } - val annotations = chiselIR.annotations.map(_.toFirrtl).filterNot{ a => a.isInstanceOf[DesignAnnotation[_]] } + val annotations = chiselIR.annotations.map(_.toFirrtl).filterNot { a => a.isInstanceOf[DesignAnnotation[_]] } /** Statements to be injected via aspect. */ val stmts = mutable.ArrayBuffer[ir.Statement]() + /** Modules to be injected via aspect. */ val modules = Aspect.getFirrtl(chiselIR.copy(components = comps)).modules.flatMap { // for "container" modules, inject their statements @@ -94,4 +98,3 @@ abstract class InjectorAspect[T <: RawModule, M <: RawModule]( }.toSeq } } - diff --git a/src/main/scala/chisel3/aop/injecting/InjectingTransform.scala b/src/main/scala/chisel3/aop/injecting/InjectingTransform.scala index cc5601b1..8a0b6ecb 100644 --- a/src/main/scala/chisel3/aop/injecting/InjectingTransform.scala +++ b/src/main/scala/chisel3/aop/injecting/InjectingTransform.scala @@ -2,7 +2,7 @@ package chisel3.aop.injecting -import firrtl.{ChirrtlForm, CircuitForm, CircuitState, Transform, ir} +import firrtl.{ir, ChirrtlForm, CircuitForm, CircuitState, Transform} import scala.collection.mutable @@ -11,7 +11,7 @@ import scala.collection.mutable * Implemented with Chisel Aspects and the [[chisel3.aop.injecting]] library */ class InjectingTransform extends Transform { - override def inputForm: CircuitForm = ChirrtlForm + override def inputForm: CircuitForm = ChirrtlForm override def outputForm: CircuitForm = ChirrtlForm override def execute(state: CircuitState): CircuitState = { diff --git a/src/main/scala/chisel3/aop/inspecting/InspectingAspect.scala b/src/main/scala/chisel3/aop/inspecting/InspectingAspect.scala index a9752426..1340f253 100644 --- a/src/main/scala/chisel3/aop/inspecting/InspectingAspect.scala +++ b/src/main/scala/chisel3/aop/inspecting/InspectingAspect.scala @@ -13,7 +13,6 @@ import firrtl.AnnotationSeq */ case class InspectingAspect[T <: RawModule](inspect: T => Unit) extends InspectorAspect[T](inspect) - /** Extend to make custom inspections of an elaborated design and printing out results * * @param inspect Given top-level design, print things and return nothing diff --git a/src/main/scala/chisel3/compatibility.scala b/src/main/scala/chisel3/compatibility.scala index ccb4ec1f..f3754e00 100644 --- a/src/main/scala/chisel3/compatibility.scala +++ b/src/main/scala/chisel3/compatibility.scala @@ -3,10 +3,10 @@ /** The Chisel compatibility package allows legacy users to continue using the `Chisel` (capital C) package name * while moving to the more standard package naming convention `chisel3` (lowercase c). */ -import chisel3._ // required for implicit conversions. +import chisel3._ // required for implicit conversions. import chisel3.experimental.chiselName import chisel3.util.random.FibonacciLFSR -import chisel3.stage.{ChiselCircuitAnnotation, ChiselOutputFileAnnotation, ChiselStage, phases} +import chisel3.stage.{phases, ChiselCircuitAnnotation, ChiselOutputFileAnnotation, ChiselStage} package object Chisel { import chisel3.internal.firrtl.Width @@ -23,23 +23,26 @@ package object Chisel { case object OUTPUT extends Direction case object NODIR extends Direction - val Input = chisel3.Input - val Output = chisel3.Output + val Input = chisel3.Input + val Output = chisel3.Output object Flipped { - def apply[T<:Data](target: T): T = chisel3.Flipped[T](target) + def apply[T <: Data](target: T): T = chisel3.Flipped[T](target) } - implicit class AddDirectionToData[T<:Data](target: T) { - def asInput: T = Input(target) + implicit class AddDirectionToData[T <: Data](target: T) { + def asInput: T = Input(target) def asOutput: T = Output(target) - def flip: T = Flipped(target) + def flip: T = Flipped(target) - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) def flip(dummy: Int*): T = flip } - implicit class AddDirMethodToData[T<:Data](target: T) { + implicit class AddDirMethodToData[T <: Data](target: T) { import chisel3.ActualDirection import chisel3.experimental.DataMirror import chisel3.internal.requireIsHardware @@ -47,11 +50,12 @@ package object Chisel { def dir: Direction = { requireIsHardware(target) // This has the side effect of calling _autoWrapPorts target match { - case e: Element => DataMirror.directionOf(e) match { - case ActualDirection.Output => OUTPUT - case ActualDirection.Input => INPUT - case _ => NODIR - } + case e: Element => + DataMirror.directionOf(e) match { + case ActualDirection.Output => OUTPUT + case ActualDirection.Input => INPUT + case _ => NODIR + } case _ => NODIR } } @@ -81,9 +85,9 @@ package object Chisel { def apply(dir: Direction): Clock = { val result = apply() dir match { - case INPUT => Input(result) + case INPUT => Input(result) case OUTPUT => Output(result) - case _ => result + case _ => result } } } @@ -130,20 +134,33 @@ package object Chisel { apply(Seq.fill(n)(gen)) 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] = chisel3.VecInit(elts) 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] = + def do_apply[T <: Data]( + elt0: T, + elts: T* + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Vec[T] = chisel3.VecInit(elt0 +: elts.toSeq) 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] = + def do_tabulate[T <: Data]( + n: Int + )(gen: (Int) => T + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Vec[T] = chisel3.VecInit.tabulate(n)(gen) } type Vec[T <: Data] = chisel3.Vec[T] @@ -157,8 +174,10 @@ package object Chisel { /** This contains literal constructor factory methods that are deprecated as of Chisel3. */ trait UIntFactory extends chisel3.UIntFactory { + /** Create a UInt literal with inferred width. */ def apply(n: String): UInt = n.asUInt + /** Create a UInt literal with fixed width. */ def apply(n: String, width: Int): UInt = n.asUInt(width.W) @@ -171,19 +190,21 @@ package object Chisel { /** Create a UInt with a specified width - compatibility with Chisel2. */ // NOTE: This resolves UInt(width = 32) def apply(dir: Option[Direction] = None, width: Int): UInt = apply(width.W) + /** Create a UInt literal with inferred width.- compatibility with Chisel2. */ def apply(value: BigInt): UInt = value.asUInt /** Create a UInt with a specified direction and width - compatibility with Chisel2. */ def apply(dir: Direction, width: Int): UInt = apply(dir, width.W) + /** Create a UInt with a specified direction, but unspecified width - compatibility with Chisel2. */ def apply(dir: Direction): UInt = apply(dir, Width()) def apply(dir: Direction, width: Width): UInt = { val result = apply(width) dir match { - case INPUT => Input(result) + case INPUT => Input(result) case OUTPUT => Output(result) - case NODIR => result + case NODIR => result } } @@ -197,13 +218,16 @@ package object Chisel { /** This contains literal constructor factory methods that are deprecated as of Chisel3. */ trait SIntFactory extends chisel3.SIntFactory { + /** Create a SInt type or port with fixed width. */ def width(width: Int): SInt = apply(width.W) + /** Create an SInt type with specified width. */ def width(width: Width): SInt = apply(width) /** Create an SInt literal with inferred width. */ def apply(value: BigInt): SInt = value.asSInt + /** Create an SInt literal with fixed width. */ def apply(value: BigInt, width: Int): SInt = value.asSInt(width.W) @@ -215,16 +239,18 @@ package object Chisel { /** Create a SInt with a specified width - compatibility with Chisel2. */ def apply(dir: Option[Direction] = None, width: Int): SInt = apply(width.W) + /** Create a SInt with a specified direction and width - compatibility with Chisel2. */ def apply(dir: Direction, width: Int): SInt = apply(dir, width.W) + /** Create a SInt with a specified direction, but unspecified width - compatibility with Chisel2. */ def apply(dir: Direction): SInt = apply(dir, Width()) def apply(dir: Direction, width: Width): SInt = { val result = apply(width) dir match { - case INPUT => Input(result) + case INPUT => Input(result) case OUTPUT => Output(result) - case NODIR => result + case NODIR => result } } } @@ -232,6 +258,7 @@ package object Chisel { /** This contains literal constructor factory methods that are deprecated as of Chisel3. */ trait BoolFactory extends chisel3.BoolFactory { + /** Creates Bool literal. */ def apply(x: Boolean): Bool = x.B @@ -240,9 +267,9 @@ package object Chisel { def apply(dir: Direction): Bool = { val result = apply() dir match { - case INPUT => Input(result) + case INPUT => Input(result) case OUTPUT => Output(result) - case NODIR => result + case NODIR => result } } } @@ -286,12 +313,22 @@ package object Chisel { implicit class SeqMemCompatibility(a: SeqMem.type) { import chisel3.internal.sourceinfo.SourceInfo - def apply[T <: Data](t: T, size: BigInt) - (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SyncReadMem[T] = + def apply[T <: Data]( + t: T, + size: BigInt + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): SyncReadMem[T] = a.do_apply(size, t) - def apply[T <: Data](t: T, size: Int) - (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SyncReadMem[T] = + def apply[T <: Data]( + t: T, + size: Int + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): SyncReadMem[T] = a.do_apply(size, t) } @@ -329,8 +366,14 @@ package object Chisel { * is a valid value. In those cases, you can either use the outType only Reg * constructor or pass in `null.asInstanceOf[T]`. */ - def apply[T <: Data](t: T = null, next: T = null, init: T = null) - (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T = { + def apply[T <: Data]( + t: T = null, + next: T = null, + init: T = null + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): T = { if (t ne null) { val reg = if (init ne null) { RegInit(t, init) @@ -386,19 +429,19 @@ package object Chisel { def apply[T <: Module](args: Array[String], gen: () => T): Unit = Predef.assert(false, "No more chiselMain in Chisel3") - def run[T <: Module] (args: Array[String], gen: () => T): Unit = { + def run[T <: Module](args: Array[String], gen: () => T): Unit = { val circuit = ChiselStage.elaborate(gen()) parseArgs(args) val output_file = new File(target_dir.getOrElse(new File(".").getCanonicalPath) + "/" + circuit.name + ".fir") - (new phases.Emitter).transform(Seq(ChiselCircuitAnnotation(circuit), - ChiselOutputFileAnnotation(output_file.toString))) + (new phases.Emitter) + .transform(Seq(ChiselCircuitAnnotation(circuit), ChiselOutputFileAnnotation(output_file.toString))) } } @deprecated("debug doesn't do anything in Chisel3 as no pruning happens in the frontend", "chisel3") object debug { - def apply (arg: Data): Data = arg + def apply(arg: Data): Data = arg } // Deprecated as of Chsiel3 @@ -423,7 +466,7 @@ package object Chisel { object log2Up { def apply(in: BigInt): Int = { require(in >= 0) - 1 max (in-1).bitLength + 1.max((in - 1).bitLength) } def apply(in: Int): Int = apply(BigInt(in)) } @@ -431,7 +474,7 @@ package object Chisel { /** Compute the log2 rounded down with min value of 1 */ object log2Down { def apply(in: BigInt): Int = log2Up(in) - (if (isPow2(in)) 0 else 1) - def apply(in: Int): Int = apply(BigInt(in)) + def apply(in: Int): Int = apply(BigInt(in)) } val BitPat = chisel3.util.BitPat @@ -472,8 +515,13 @@ package object Chisel { val Queue = chisel3.util.Queue type Queue[T <: Data] = QueueCompatibility[T] - sealed class QueueCompatibility[T <: Data](gen: T, entries: Int, pipe: Boolean = false, flow: Boolean = false) - (implicit compileOptions: chisel3.CompileOptions) + sealed class QueueCompatibility[T <: Data]( + gen: T, + entries: Int, + pipe: Boolean = false, + flow: Boolean = false + )( + implicit compileOptions: chisel3.CompileOptions) extends chisel3.util.Queue[T](gen, entries, pipe, flow)(compileOptions) { def this(gen: T, entries: Int, pipe: Boolean, flow: Boolean, override_reset: Option[Bool]) = { @@ -489,6 +537,7 @@ package object Chisel { } object Enum extends chisel3.util.Enum { + /** Returns n unique values of the specified type. Can be used with unpacking to define enums. * * nodeType must be of UInt type (note that Bits() creates a UInt) with unspecified width. @@ -522,10 +571,10 @@ package object Chisel { * Deprecation is only to nag users to do something safer. */ @deprecated("Use list-based Enum", "not soon enough") - def apply[T <: Bits](nodeType: T, l: Symbol *): Map[Symbol, T] = { + def apply[T <: Bits](nodeType: T, l: Symbol*): Map[Symbol, T] = { require(nodeType.isInstanceOf[UInt], "Only UInt supported for enums") require(!nodeType.widthKnown, "Bit width may no longer be specified for enums") - (l zip createValues(l.length)).toMap.asInstanceOf[Map[Symbol, T]] + (l.zip(createValues(l.length))).toMap.asInstanceOf[Map[Symbol, T]] } /** An old Enum API that returns a map of symbols to UInts. @@ -541,7 +590,7 @@ package object Chisel { def apply[T <: Bits](nodeType: T, l: List[Symbol]): Map[Symbol, T] = { require(nodeType.isInstanceOf[UInt], "Only UInt supported for enums") require(!nodeType.widthKnown, "Bit width may no longer be specified for enums") - (l zip createValues(l.length)).toMap.asInstanceOf[Map[Symbol, T]] + (l.zip(createValues(l.length))).toMap.asInstanceOf[Map[Symbol, T]] } } @@ -564,16 +613,18 @@ package object Chisel { * }}} */ object LFSR16 { + /** Generates a 16-bit linear feedback shift register, returning the register contents. * @param increment optional control to gate when the LFSR updates. */ @chiselName def apply(increment: Bool = true.B): UInt = - VecInit( FibonacciLFSR - .maxPeriod(16, increment, seed = Some(BigInt(1) << 15)) - .asBools - .reverse ) - .asUInt + VecInit( + FibonacciLFSR + .maxPeriod(16, increment, seed = Some(BigInt(1) << 15)) + .asBools + .reverse + ).asUInt } @@ -598,7 +649,6 @@ package object Chisel { val Pipe = chisel3.util.Pipe type Pipe[T <: Data] = chisel3.util.Pipe[T] - /** Package for experimental features, which may have their API changed, be removed, etc. * * Because its contents won't necessarily have the same level of stability and support as @@ -638,7 +688,8 @@ package object Chisel { final def toUInt(implicit compileOptions: CompileOptions): UInt = a.do_asUInt(DeprecatedSourceInfo, compileOptions) - final def toBools(implicit compileOptions: CompileOptions): Seq[Bool] = a.do_asBools(DeprecatedSourceInfo, compileOptions) + final def toBools(implicit compileOptions: CompileOptions): Seq[Bool] = + a.do_asBools(DeprecatedSourceInfo, compileOptions) } } diff --git a/src/main/scala/chisel3/experimental/conversions/package.scala b/src/main/scala/chisel3/experimental/conversions/package.scala index 574f9f96..7374f223 100644 --- a/src/main/scala/chisel3/experimental/conversions/package.scala +++ b/src/main/scala/chisel3/experimental/conversions/package.scala @@ -1,4 +1,3 @@ - package chisel3.experimental import chisel3._ @@ -12,116 +11,229 @@ import scala.language.implicitConversions package object conversions { /** Implicit conversion between `Seq` and `Vec` */ - implicit def seq2vec[A : DataProduct, B <: Data](xs: Seq[A])(implicit dv: DataView[A, B]): Vec[B] = + implicit def seq2vec[A: DataProduct, B <: Data](xs: Seq[A])(implicit dv: DataView[A, B]): Vec[B] = xs.viewAs[Vec[B]] /** Implicit conversion between [[Tuple2]] and [[HWTuple2]] */ - implicit def tuple2hwtuple[T1 : DataProduct, T2 : DataProduct, V1 <: Data, V2 <: Data]( + implicit def tuple2hwtuple[T1: DataProduct, T2: DataProduct, V1 <: Data, V2 <: Data]( tup: (T1, T2) )( - implicit v1: DataView[T1, V1], v2: DataView[T2, V2] + implicit v1: DataView[T1, V1], + v2: DataView[T2, V2] ): HWTuple2[V1, V2] = { tup.viewAs[HWTuple2[V1, V2]] } /** Implicit conversion between [[Tuple3]] and [[HWTuple3]] */ - implicit def tuple3hwtuple[T1 : DataProduct, T2 : DataProduct, T3 : DataProduct, V1 <: Data, V2 <: Data, V3 <: Data]( + implicit def tuple3hwtuple[T1: DataProduct, T2: DataProduct, T3: DataProduct, V1 <: Data, V2 <: Data, V3 <: Data]( tup: (T1, T2, T3) )( - implicit v1: DataView[T1, V1], v2: DataView[T2, V2], v3: DataView[T3, V3] + implicit v1: DataView[T1, V1], + v2: DataView[T2, V2], + v3: DataView[T3, V3] ): HWTuple3[V1, V2, V3] = { tup.viewAs[HWTuple3[V1, V2, V3]] } /** Implicit conversion between [[Tuple4]] and [[HWTuple4]] */ implicit def tuple4hwtuple[ - T1 : DataProduct, T2 : DataProduct, T3 : DataProduct, T4 : DataProduct, - V1 <: Data, V2 <: Data, V3 <: Data, V4 <: Data - ]( - tup: (T1, T2, T3, T4) + T1: DataProduct, + T2: DataProduct, + T3: DataProduct, + T4: DataProduct, + V1 <: Data, + V2 <: Data, + V3 <: Data, + V4 <: Data + ](tup: (T1, T2, T3, T4) )( - implicit v1: DataView[T1, V1], v2: DataView[T2, V2], v3: DataView[T3, V3], v4: DataView[T4, V4] + implicit v1: DataView[T1, V1], + v2: DataView[T2, V2], + v3: DataView[T3, V3], + v4: DataView[T4, V4] ): HWTuple4[V1, V2, V3, V4] = { tup.viewAs[HWTuple4[V1, V2, V3, V4]] } /** Implicit conversion between [[Tuple5]] and [[HWTuple5]] */ implicit def tuple5hwtuple[ - T1 : DataProduct, T2 : DataProduct, T3 : DataProduct, T4 : DataProduct, T5 : DataProduct, - V1 <: Data, V2 <: Data, V3 <: Data, V4 <: Data, V5 <: Data - ]( - tup: (T1, T2, T3, T4, T5) + T1: DataProduct, + T2: DataProduct, + T3: DataProduct, + T4: DataProduct, + T5: DataProduct, + V1 <: Data, + V2 <: Data, + V3 <: Data, + V4 <: Data, + V5 <: Data + ](tup: (T1, T2, T3, T4, T5) )( - implicit v1: DataView[T1, V1], v2: DataView[T2, V2], v3: DataView[T3, V3], v4: DataView[T4, V4], v5: DataView[T5, V5] + implicit v1: DataView[T1, V1], + v2: DataView[T2, V2], + v3: DataView[T3, V3], + v4: DataView[T4, V4], + v5: DataView[T5, V5] ): HWTuple5[V1, V2, V3, V4, V5] = { tup.viewAs[HWTuple5[V1, V2, V3, V4, V5]] } /** Implicit conversion between [[Tuple6]] and [[HWTuple6]] */ implicit def tuple6hwtuple[ - T1 : DataProduct, T2 : DataProduct, T3 : DataProduct, T4 : DataProduct, T5 : DataProduct, T6 : DataProduct, - V1 <: Data, V2 <: Data, V3 <: Data, V4 <: Data, V5 <: Data, V6 <: Data - ]( - tup: (T1, T2, T3, T4, T5, T6) + T1: DataProduct, + T2: DataProduct, + T3: DataProduct, + T4: DataProduct, + T5: DataProduct, + T6: DataProduct, + V1 <: Data, + V2 <: Data, + V3 <: Data, + V4 <: Data, + V5 <: Data, + V6 <: Data + ](tup: (T1, T2, T3, T4, T5, T6) )( - implicit v1: DataView[T1, V1], v2: DataView[T2, V2], v3: DataView[T3, V3], v4: DataView[T4, V4], v5: DataView[T5, V5], - v6: DataView[T6, V6] + implicit v1: DataView[T1, V1], + v2: DataView[T2, V2], + v3: DataView[T3, V3], + v4: DataView[T4, V4], + v5: DataView[T5, V5], + v6: DataView[T6, V6] ): HWTuple6[V1, V2, V3, V4, V5, V6] = { tup.viewAs[HWTuple6[V1, V2, V3, V4, V5, V6]] } /** Implicit conversion between [[Tuple7]] and [[HWTuple7]] */ implicit def tuple7hwtuple[ - T1 : DataProduct, T2 : DataProduct, T3 : DataProduct, T4 : DataProduct, T5 : DataProduct, - T6 : DataProduct, T7 : DataProduct, - V1 <: Data, V2 <: Data, V3 <: Data, V4 <: Data, V5 <: Data, V6 <: Data, V7 <: Data - ]( - tup: (T1, T2, T3, T4, T5, T6, T7) + T1: DataProduct, + T2: DataProduct, + T3: DataProduct, + T4: DataProduct, + T5: DataProduct, + T6: DataProduct, + T7: DataProduct, + V1 <: Data, + V2 <: Data, + V3 <: Data, + V4 <: Data, + V5 <: Data, + V6 <: Data, + V7 <: Data + ](tup: (T1, T2, T3, T4, T5, T6, T7) )( - implicit v1: DataView[T1, V1], v2: DataView[T2, V2], v3: DataView[T3, V3], v4: DataView[T4, V4], v5: DataView[T5, V5], - v6: DataView[T6, V6], v7: DataView[T7, V7] + implicit v1: DataView[T1, V1], + v2: DataView[T2, V2], + v3: DataView[T3, V3], + v4: DataView[T4, V4], + v5: DataView[T5, V5], + v6: DataView[T6, V6], + v7: DataView[T7, V7] ): HWTuple7[V1, V2, V3, V4, V5, V6, V7] = { tup.viewAs[HWTuple7[V1, V2, V3, V4, V5, V6, V7]] } /** Implicit conversion between [[Tuple8]] and [[HWTuple8]] */ implicit def tuple8hwtuple[ - T1 : DataProduct, T2 : DataProduct, T3 : DataProduct, T4 : DataProduct, T5 : DataProduct, - T6 : DataProduct, T7 : DataProduct, T8 : DataProduct, - V1 <: Data, V2 <: Data, V3 <: Data, V4 <: Data, V5 <: Data, V6 <: Data, V7 <: Data, V8 <: Data - ]( - tup: (T1, T2, T3, T4, T5, T6, T7, T8) + T1: DataProduct, + T2: DataProduct, + T3: DataProduct, + T4: DataProduct, + T5: DataProduct, + T6: DataProduct, + T7: DataProduct, + T8: DataProduct, + V1 <: Data, + V2 <: Data, + V3 <: Data, + V4 <: Data, + V5 <: Data, + V6 <: Data, + V7 <: Data, + V8 <: Data + ](tup: (T1, T2, T3, T4, T5, T6, T7, T8) )( - implicit v1: DataView[T1, V1], v2: DataView[T2, V2], v3: DataView[T3, V3], v4: DataView[T4, V4], v5: DataView[T5, V5], - v6: DataView[T6, V6], v7: DataView[T7, V7], v8: DataView[T8, V8] + implicit v1: DataView[T1, V1], + v2: DataView[T2, V2], + v3: DataView[T3, V3], + v4: DataView[T4, V4], + v5: DataView[T5, V5], + v6: DataView[T6, V6], + v7: DataView[T7, V7], + v8: DataView[T8, V8] ): HWTuple8[V1, V2, V3, V4, V5, V6, V7, V8] = { tup.viewAs[HWTuple8[V1, V2, V3, V4, V5, V6, V7, V8]] } /** Implicit conversion between [[Tuple9]] and [[HWTuple9]] */ implicit def tuple9hwtuple[ - T1 : DataProduct, T2 : DataProduct, T3 : DataProduct, T4 : DataProduct, T5 : DataProduct, - T6 : DataProduct, T7 : DataProduct, T8 : DataProduct, T9 : DataProduct, - V1 <: Data, V2 <: Data, V3 <: Data, V4 <: Data, V5 <: Data, V6 <: Data, V7 <: Data, V8 <: Data, V9 <: Data - ]( - tup: (T1, T2, T3, T4, T5, T6, T7, T8, T9) + T1: DataProduct, + T2: DataProduct, + T3: DataProduct, + T4: DataProduct, + T5: DataProduct, + T6: DataProduct, + T7: DataProduct, + T8: DataProduct, + T9: DataProduct, + V1 <: Data, + V2 <: Data, + V3 <: Data, + V4 <: Data, + V5 <: Data, + V6 <: Data, + V7 <: Data, + V8 <: Data, + V9 <: Data + ](tup: (T1, T2, T3, T4, T5, T6, T7, T8, T9) )( - implicit v1: DataView[T1, V1], v2: DataView[T2, V2], v3: DataView[T3, V3], v4: DataView[T4, V4], v5: DataView[T5, V5], - v6: DataView[T6, V6], v7: DataView[T7, V7], v8: DataView[T8, V8], v9: DataView[T9, V9] + implicit v1: DataView[T1, V1], + v2: DataView[T2, V2], + v3: DataView[T3, V3], + v4: DataView[T4, V4], + v5: DataView[T5, V5], + v6: DataView[T6, V6], + v7: DataView[T7, V7], + v8: DataView[T8, V8], + v9: DataView[T9, V9] ): HWTuple9[V1, V2, V3, V4, V5, V6, V7, V8, V9] = { tup.viewAs[HWTuple9[V1, V2, V3, V4, V5, V6, V7, V8, V9]] } /** Implicit conversion between [[Tuple10]] and [[HWTuple10]] */ implicit def tuple10hwtuple[ - T1 : DataProduct, T2 : DataProduct, T3 : DataProduct, T4 : DataProduct, T5 : DataProduct, - T6 : DataProduct, T7 : DataProduct, T8 : DataProduct, T9 : DataProduct, T10 : DataProduct, - V1 <: Data, V2 <: Data, V3 <: Data, V4 <: Data, V5 <: Data, V6 <: Data, V7 <: Data, V8 <: Data, V9 <: Data, V10 <: Data - ]( - tup: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) + T1: DataProduct, + T2: DataProduct, + T3: DataProduct, + T4: DataProduct, + T5: DataProduct, + T6: DataProduct, + T7: DataProduct, + T8: DataProduct, + T9: DataProduct, + T10: DataProduct, + V1 <: Data, + V2 <: Data, + V3 <: Data, + V4 <: Data, + V5 <: Data, + V6 <: Data, + V7 <: Data, + V8 <: Data, + V9 <: Data, + V10 <: Data + ](tup: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) )( - implicit v1: DataView[T1, V1], v2: DataView[T2, V2], v3: DataView[T3, V3], v4: DataView[T4, V4], v5: DataView[T5, V5], - v6: DataView[T6, V6], v7: DataView[T7, V7], v8: DataView[T8, V8], v9: DataView[T9, V9], v10: DataView[T10, V10] + implicit v1: DataView[T1, V1], + v2: DataView[T2, V2], + v3: DataView[T3, V3], + v4: DataView[T4, V4], + v5: DataView[T5, V5], + v6: DataView[T6, V6], + v7: DataView[T7, V7], + v8: DataView[T8, V8], + v9: DataView[T9, V9], + v10: DataView[T10, V10] ): HWTuple10[V1, V2, V3, V4, V5, V6, V7, V8, V9, V10] = { tup.viewAs[HWTuple10[V1, V2, V3, V4, V5, V6, V7, V8, V9, V10]] } diff --git a/src/main/scala/chisel3/experimental/verification/package.scala b/src/main/scala/chisel3/experimental/verification/package.scala index a026542d..1cedb8da 100644 --- a/src/main/scala/chisel3/experimental/verification/package.scala +++ b/src/main/scala/chisel3/experimental/verification/package.scala @@ -8,20 +8,44 @@ import chisel3.internal.sourceinfo.SourceInfo package object verification { object assert { - @deprecated("Please use chisel3.assert instead. The chisel3.experimental.verification package will be removed.", "Chisel 3.5") - def apply(predicate: Bool, msg: String = "") - (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): chisel3.assert.Assert = chisel3.assert(predicate, msg) + @deprecated( + "Please use chisel3.assert instead. The chisel3.experimental.verification package will be removed.", + "Chisel 3.5" + ) + def apply( + predicate: Bool, + msg: String = "" + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): chisel3.assert.Assert = chisel3.assert(predicate, msg) } object assume { - @deprecated("Please use chisel3.assume instead. The chisel3.experimental.verification package will be removed.", "Chisel 3.5") - def apply(predicate: Bool, msg: String = "") - (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): chisel3.assume.Assume = chisel3.assume(predicate, msg) + @deprecated( + "Please use chisel3.assume instead. The chisel3.experimental.verification package will be removed.", + "Chisel 3.5" + ) + def apply( + predicate: Bool, + msg: String = "" + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): chisel3.assume.Assume = chisel3.assume(predicate, msg) } object cover { - @deprecated("Please use chisel3.cover instead. The chisel3.experimental.verification package will be removed.", "Chisel 3.5") - def apply(predicate: Bool, msg: String = "") - (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): chisel3.cover.Cover = chisel3.cover(predicate, msg) + @deprecated( + "Please use chisel3.cover instead. The chisel3.experimental.verification package will be removed.", + "Chisel 3.5" + ) + def apply( + predicate: Bool, + msg: String = "" + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): chisel3.cover.Cover = chisel3.cover(predicate, msg) } } diff --git a/src/main/scala/chisel3/internal/firrtl/Emitter.scala b/src/main/scala/chisel3/internal/firrtl/Emitter.scala index a94558ce..bbf43a45 100644 --- a/src/main/scala/chisel3/internal/firrtl/Emitter.scala +++ b/src/main/scala/chisel3/internal/firrtl/Emitter.scala @@ -20,4 +20,3 @@ private[chisel3] object Emitter { result ++ moduleStrings } } - diff --git a/src/main/scala/chisel3/stage/ChiselAnnotations.scala b/src/main/scala/chisel3/stage/ChiselAnnotations.scala index de47ef36..c5811813 100644 --- a/src/main/scala/chisel3/stage/ChiselAnnotations.scala +++ b/src/main/scala/chisel3/stage/ChiselAnnotations.scala @@ -3,7 +3,15 @@ package chisel3.stage import firrtl.annotations.{Annotation, NoTargetAnnotation} -import firrtl.options.{BufferedCustomFileEmission, CustomFileEmission, HasShellOptions, OptionsException, ShellOption, StageOptions, Unserializable} +import firrtl.options.{ + BufferedCustomFileEmission, + CustomFileEmission, + HasShellOptions, + OptionsException, + ShellOption, + StageOptions, + Unserializable +} import firrtl.options.Viewer.view import chisel3.{ChiselException, Module} import chisel3.RawModule @@ -29,7 +37,9 @@ case object NoRunFirrtlCompilerAnnotation longOption = "no-run-firrtl", toAnnotationSeq = _ => Seq(NoRunFirrtlCompilerAnnotation), helpText = "Do not run the FIRRTL compiler (generate FIRRTL IR from Chisel and exit)", - shortOption = Some("chnrf") ) ) + shortOption = Some("chnrf") + ) + ) } @@ -45,7 +55,9 @@ case object PrintFullStackTraceAnnotation new ShellOption[Unit]( longOption = "full-stacktrace", toAnnotationSeq = _ => Seq(PrintFullStackTraceAnnotation), - helpText = "Show full stack trace when an exception is thrown" ) ) + helpText = "Show full stack trace when an exception is thrown" + ) + ) } @@ -68,15 +80,18 @@ object ChiselGeneratorAnnotation extends HasShellOptions { * that Module is found */ def apply(name: String): ChiselGeneratorAnnotation = { - val gen = () => try { - Class.forName(name).asInstanceOf[Class[_ <: RawModule]].newInstance() - } catch { - case e: ClassNotFoundException => - throw new OptionsException(s"Unable to locate module '$name'! (Did you misspell it?)", e) - case e: InstantiationException => - throw new OptionsException( - s"Unable to create instance of module '$name'! (Does this class take parameters?)", e) - } + val gen = () => + try { + Class.forName(name).asInstanceOf[Class[_ <: RawModule]].newInstance() + } catch { + case e: ClassNotFoundException => + throw new OptionsException(s"Unable to locate module '$name'! (Did you misspell it?)", e) + case e: InstantiationException => + throw new OptionsException( + s"Unable to create instance of module '$name'! (Does this class take parameters?)", + e + ) + } ChiselGeneratorAnnotation(gen) } @@ -85,17 +100,16 @@ object ChiselGeneratorAnnotation extends HasShellOptions { longOption = "module", toAnnotationSeq = (a: String) => Seq(ChiselGeneratorAnnotation(a)), helpText = "The name of a Chisel module to elaborate (module must be in the classpath)", - helpValueName = Some("<package>.<module>") ) ) + helpValueName = Some("<package>.<module>") + ) + ) } /** Stores a Chisel Circuit * @param circuit a Chisel Circuit */ -case class ChiselCircuitAnnotation(circuit: Circuit) - extends NoTargetAnnotation - with ChiselOption - with Unserializable { +case class ChiselCircuitAnnotation(circuit: Circuit) extends NoTargetAnnotation with ChiselOption with Unserializable { /* Caching the hashCode for a large circuit is necessary due to repeated queries. * Not caching the hashCode will cause severe performance degredations for large [[Circuit]]s. */ @@ -135,8 +149,9 @@ case class CircuitSerializationAnnotation(circuit: Circuit, filename: String, fo override def getBytesBuffered: Iterable[Array[Byte]] = format match { case FirrtlFileFormat => - OldEmitter.emitLazily(circuit) - .map(_.getBytes) + OldEmitter + .emitLazily(circuit) + .map(_.getBytes) // TODO Use lazy Iterables so that we don't have to materialize full intermediate data structures case ProtoBufFileFormat => val ostream = new java.io.ByteArrayOutputStream @@ -155,7 +170,9 @@ object ChiselOutputFileAnnotation extends HasShellOptions { longOption = "chisel-output-file", toAnnotationSeq = (a: String) => Seq(ChiselOutputFileAnnotation(a)), helpText = "Write Chisel-generated FIRRTL to this file (default: <circuit-main>.fir)", - helpValueName = Some("<file>") ) ) + helpValueName = Some("<file>") + ) + ) } diff --git a/src/main/scala/chisel3/stage/ChiselCli.scala b/src/main/scala/chisel3/stage/ChiselCli.scala index 8e1974ed..26b032bf 100644 --- a/src/main/scala/chisel3/stage/ChiselCli.scala +++ b/src/main/scala/chisel3/stage/ChiselCli.scala @@ -6,9 +6,11 @@ import firrtl.options.Shell trait ChiselCli { this: Shell => parser.note("Chisel Front End Options") - Seq( NoRunFirrtlCompilerAnnotation, - PrintFullStackTraceAnnotation, - ChiselOutputFileAnnotation, - ChiselGeneratorAnnotation ) + Seq( + NoRunFirrtlCompilerAnnotation, + PrintFullStackTraceAnnotation, + ChiselOutputFileAnnotation, + ChiselGeneratorAnnotation + ) .foreach(_.addOptions(parser)) } diff --git a/src/main/scala/chisel3/stage/ChiselOptions.scala b/src/main/scala/chisel3/stage/ChiselOptions.scala index 46a68f64..ed4d0a2f 100644 --- a/src/main/scala/chisel3/stage/ChiselOptions.scala +++ b/src/main/scala/chisel3/stage/ChiselOptions.scala @@ -5,22 +5,24 @@ package chisel3.stage import chisel3.internal.firrtl.Circuit class ChiselOptions private[stage] ( - val runFirrtlCompiler: Boolean = true, - val printFullStackTrace: Boolean = false, - val outputFile: Option[String] = None, + val runFirrtlCompiler: Boolean = true, + val printFullStackTrace: Boolean = false, + val outputFile: Option[String] = None, val chiselCircuit: Option[Circuit] = None) { private[stage] def copy( - runFirrtlCompiler: Boolean = runFirrtlCompiler, - printFullStackTrace: Boolean = printFullStackTrace, - outputFile: Option[String] = outputFile, - chiselCircuit: Option[Circuit] = chiselCircuit ): ChiselOptions = { + runFirrtlCompiler: Boolean = runFirrtlCompiler, + printFullStackTrace: Boolean = printFullStackTrace, + outputFile: Option[String] = outputFile, + chiselCircuit: Option[Circuit] = chiselCircuit + ): ChiselOptions = { new ChiselOptions( - runFirrtlCompiler = runFirrtlCompiler, + runFirrtlCompiler = runFirrtlCompiler, printFullStackTrace = printFullStackTrace, - outputFile = outputFile, - chiselCircuit = chiselCircuit ) + outputFile = outputFile, + chiselCircuit = chiselCircuit + ) } diff --git a/src/main/scala/chisel3/stage/ChiselPhase.scala b/src/main/scala/chisel3/stage/ChiselPhase.scala index aa37f3b1..6c7affbc 100644 --- a/src/main/scala/chisel3/stage/ChiselPhase.scala +++ b/src/main/scala/chisel3/stage/ChiselPhase.scala @@ -2,28 +2,26 @@ package chisel3.stage -import firrtl.options.{ - Dependency, - Phase, - PhaseManager -} +import firrtl.options.{Dependency, Phase, PhaseManager} import firrtl.options.phases.DeletedWrapper private[chisel3] class ChiselPhase extends PhaseManager(ChiselPhase.targets) { - override val wrappers = Seq( (a: Phase) => DeletedWrapper(a) ) + override val wrappers = Seq((a: Phase) => DeletedWrapper(a)) } private[chisel3] object ChiselPhase { val targets: Seq[PhaseManager.PhaseDependency] = - Seq( Dependency[chisel3.stage.phases.Checks], - Dependency[chisel3.stage.phases.AddImplicitOutputFile], - Dependency[chisel3.stage.phases.AddImplicitOutputAnnotationFile], - Dependency[chisel3.stage.phases.MaybeAspectPhase], - Dependency[chisel3.stage.phases.AddSerializationAnnotations], - Dependency[chisel3.stage.phases.Convert], - Dependency[chisel3.stage.phases.MaybeFirrtlStage] ) + Seq( + Dependency[chisel3.stage.phases.Checks], + Dependency[chisel3.stage.phases.AddImplicitOutputFile], + Dependency[chisel3.stage.phases.AddImplicitOutputAnnotationFile], + Dependency[chisel3.stage.phases.MaybeAspectPhase], + Dependency[chisel3.stage.phases.AddSerializationAnnotations], + Dependency[chisel3.stage.phases.Convert], + Dependency[chisel3.stage.phases.MaybeFirrtlStage] + ) } diff --git a/src/main/scala/chisel3/stage/ChiselStage.scala b/src/main/scala/chisel3/stage/ChiselStage.scala index 0c76f411..1224a8f1 100644 --- a/src/main/scala/chisel3/stage/ChiselStage.scala +++ b/src/main/scala/chisel3/stage/ChiselStage.scala @@ -22,7 +22,7 @@ import chisel3.{ChiselException, RawModule} import chisel3.internal.{firrtl => cir, ErrorLog} import chisel3.stage.CircuitSerializationAnnotation.FirrtlFileFormat -import java.io.{StringWriter, PrintWriter} +import java.io.{PrintWriter, StringWriter} class ChiselStage extends Stage { @@ -51,17 +51,16 @@ class ChiselStage extends Stage { * @return a string containing the Verilog output */ final def emitChirrtl( - gen: => RawModule, - args: Array[String] = Array.empty, - annotations: AnnotationSeq = Seq.empty): String = { + gen: => RawModule, + args: Array[String] = Array.empty, + annotations: AnnotationSeq = Seq.empty + ): String = { val annos = execute(Array("--no-run-firrtl") ++ args, ChiselGeneratorAnnotation(() => gen) +: annotations) - annos - .collectFirst { - case a: ChiselCircuitAnnotation => CircuitSerializationAnnotation(a.circuit, "", FirrtlFileFormat).getBytes - } - .get + annos.collectFirst { + case a: ChiselCircuitAnnotation => CircuitSerializationAnnotation(a.circuit, "", FirrtlFileFormat).getBytes + }.get .map(_.toChar) .mkString @@ -74,15 +73,15 @@ class ChiselStage extends Stage { * @return a string containing the FIRRTL output */ final def emitFirrtl( - gen: => RawModule, - args: Array[String] = Array.empty, - annotations: AnnotationSeq = Seq.empty): String = { - - execute(Array("-X", "high") ++ args, ChiselGeneratorAnnotation(() => gen) +: annotations) - .collect { - case EmittedFirrtlCircuitAnnotation(a) => a - case EmittedFirrtlModuleAnnotation(a) => a - }.map(_.value) + gen: => RawModule, + args: Array[String] = Array.empty, + annotations: AnnotationSeq = Seq.empty + ): String = { + + execute(Array("-X", "high") ++ args, ChiselGeneratorAnnotation(() => gen) +: annotations).collect { + case EmittedFirrtlCircuitAnnotation(a) => a + case EmittedFirrtlModuleAnnotation(a) => a + }.map(_.value) .mkString("") } @@ -94,15 +93,15 @@ class ChiselStage extends Stage { * @return a string containing the Verilog output */ final def emitVerilog( - gen: => RawModule, - args: Array[String] = Array.empty, - annotations: AnnotationSeq = Seq.empty): String = { - - execute(Array("-X", "verilog") ++ args, ChiselGeneratorAnnotation(() => gen) +: annotations) - .collectFirst { - case EmittedVerilogCircuitAnnotation(a) => a - case EmittedVerilogModuleAnnotation(a) => a - }.map(_.value) + gen: => RawModule, + args: Array[String] = Array.empty, + annotations: AnnotationSeq = Seq.empty + ): String = { + + execute(Array("-X", "verilog") ++ args, ChiselGeneratorAnnotation(() => gen) +: annotations).collectFirst { + case EmittedVerilogCircuitAnnotation(a) => a + case EmittedVerilogModuleAnnotation(a) => a + }.map(_.value) .mkString("") } @@ -114,15 +113,15 @@ class ChiselStage extends Stage { * @return a string containing the SystemVerilog output */ final def emitSystemVerilog( - gen: => RawModule, - args: Array[String] = Array.empty, - annotations: AnnotationSeq = Seq.empty): String = { - - execute(Array("-X", "sverilog") ++ args, ChiselGeneratorAnnotation(() => gen) +: annotations) - .collectFirst { - case EmittedVerilogCircuitAnnotation(a) => a - case EmittedVerilogModuleAnnotation(a) => a - }.map(_.value) + gen: => RawModule, + args: Array[String] = Array.empty, + annotations: AnnotationSeq = Seq.empty + ): String = { + + execute(Array("-X", "sverilog") ++ args, ChiselGeneratorAnnotation(() => gen) +: annotations).collectFirst { + case EmittedVerilogCircuitAnnotation(a) => a + case EmittedVerilogModuleAnnotation(a) => a + }.map(_.value) .mkString("") } @@ -138,8 +137,7 @@ object ChiselStage { */ def elaborate(gen: => RawModule): cir.Circuit = { val phase = new ChiselPhase { - override val targets = Seq( Dependency[chisel3.stage.phases.Checks], - Dependency[chisel3.stage.phases.Elaborate] ) + override val targets = Seq(Dependency[chisel3.stage.phases.Checks], Dependency[chisel3.stage.phases.Elaborate]) } phase @@ -161,7 +159,8 @@ object ChiselStage { Dependency[chisel3.stage.phases.AddImplicitOutputFile], Dependency[chisel3.stage.phases.AddImplicitOutputAnnotationFile], Dependency[chisel3.stage.phases.MaybeAspectPhase], - Dependency[chisel3.stage.phases.Convert] ) + Dependency[chisel3.stage.phases.Convert] + ) } phase @@ -181,7 +180,8 @@ object ChiselStage { Dependency[chisel3.stage.phases.AddImplicitOutputFile], Dependency[chisel3.stage.phases.AddImplicitOutputAnnotationFile], Dependency[chisel3.stage.phases.MaybeAspectPhase], - Dependency[chisel3.stage.phases.Convert] ) + Dependency[chisel3.stage.phases.Convert] + ) } phase @@ -209,14 +209,16 @@ object ChiselStage { Dependency[chisel3.stage.phases.AddImplicitOutputAnnotationFile], Dependency[chisel3.stage.phases.MaybeAspectPhase], Dependency[chisel3.stage.phases.Convert], - Dependency[firrtl.stage.phases.Compiler] ) + Dependency[firrtl.stage.phases.Compiler] + ) ) phase .transform(Seq(ChiselGeneratorAnnotation(() => gen), RunFirrtlTransformAnnotation(new HighFirrtlEmitter))) .collectFirst { case EmittedFirrtlCircuitAnnotation(a) => a - }.get + } + .get .value } @@ -233,14 +235,16 @@ object ChiselStage { Dependency[chisel3.stage.phases.AddImplicitOutputAnnotationFile], Dependency[chisel3.stage.phases.MaybeAspectPhase], Dependency[chisel3.stage.phases.Convert], - Dependency[firrtl.stage.phases.Compiler] ) + Dependency[firrtl.stage.phases.Compiler] + ) ) phase .transform(Seq(ChiselGeneratorAnnotation(() => gen), RunFirrtlTransformAnnotation(new VerilogEmitter))) .collectFirst { case EmittedVerilogCircuitAnnotation(a) => a - }.get + } + .get .value } @@ -256,14 +260,16 @@ object ChiselStage { Dependency[chisel3.stage.phases.AddImplicitOutputAnnotationFile], Dependency[chisel3.stage.phases.MaybeAspectPhase], Dependency[chisel3.stage.phases.Convert], - Dependency[firrtl.stage.phases.Compiler] ) + Dependency[firrtl.stage.phases.Compiler] + ) ) phase .transform(Seq(ChiselGeneratorAnnotation(() => gen), RunFirrtlTransformAnnotation(new SystemVerilogEmitter))) .collectFirst { case EmittedVerilogCircuitAnnotation(a) => a - }.get + } + .get .value } diff --git a/src/main/scala/chisel3/stage/package.scala b/src/main/scala/chisel3/stage/package.scala index c307d3ae..bf03e2df 100644 --- a/src/main/scala/chisel3/stage/package.scala +++ b/src/main/scala/chisel3/stage/package.scala @@ -12,14 +12,13 @@ package object stage { implicit object ChiselOptionsView extends OptionsView[ChiselOptions] { - def view(options: AnnotationSeq): ChiselOptions = options - .collect { case a: ChiselOption => a } - .foldLeft(new ChiselOptions()){ (c, x) => + def view(options: AnnotationSeq): ChiselOptions = options.collect { case a: ChiselOption => a } + .foldLeft(new ChiselOptions()) { (c, x) => x match { case _: NoRunFirrtlCompilerAnnotation.type => c.copy(runFirrtlCompiler = false) case _: PrintFullStackTraceAnnotation.type => c.copy(printFullStackTrace = true) - case ChiselOutputFileAnnotation(f) => c.copy(outputFile = Some(f)) - case ChiselCircuitAnnotation(a) => c.copy(chiselCircuit = Some(a)) + case ChiselOutputFileAnnotation(f) => c.copy(outputFile = Some(f)) + case ChiselCircuitAnnotation(a) => c.copy(chiselCircuit = Some(a)) } } diff --git a/src/main/scala/chisel3/stage/phases/AddImplicitOutputAnnotationFile.scala b/src/main/scala/chisel3/stage/phases/AddImplicitOutputAnnotationFile.scala index 3ce9dacd..6874e2a2 100644 --- a/src/main/scala/chisel3/stage/phases/AddImplicitOutputAnnotationFile.scala +++ b/src/main/scala/chisel3/stage/phases/AddImplicitOutputAnnotationFile.scala @@ -16,15 +16,16 @@ class AddImplicitOutputAnnotationFile extends Phase { override def optionalPrerequisiteOf = Seq.empty override def invalidates(a: Phase) = false - def transform(annotations: AnnotationSeq): AnnotationSeq = annotations - .collectFirst{ case _: OutputAnnotationFileAnnotation => annotations } - .getOrElse{ + def transform(annotations: AnnotationSeq): AnnotationSeq = annotations.collectFirst { + case _: OutputAnnotationFileAnnotation => annotations + }.getOrElse { - val x: Option[AnnotationSeq] = annotations - .collectFirst{ case a: ChiselCircuitAnnotation => - OutputAnnotationFileAnnotation(a.circuit.name) +: annotations } - - x.getOrElse(annotations) + val x: Option[AnnotationSeq] = annotations.collectFirst { + case a: ChiselCircuitAnnotation => + OutputAnnotationFileAnnotation(a.circuit.name) +: annotations } + x.getOrElse(annotations) + } + } diff --git a/src/main/scala/chisel3/stage/phases/AddImplicitOutputFile.scala b/src/main/scala/chisel3/stage/phases/AddImplicitOutputFile.scala index e39d4d54..2507c2c8 100644 --- a/src/main/scala/chisel3/stage/phases/AddImplicitOutputFile.scala +++ b/src/main/scala/chisel3/stage/phases/AddImplicitOutputFile.scala @@ -18,11 +18,12 @@ class AddImplicitOutputFile extends Phase { override def invalidates(a: Phase) = false def transform(annotations: AnnotationSeq): AnnotationSeq = - annotations.collectFirst{ case _: ChiselOutputFileAnnotation => annotations }.getOrElse{ + annotations.collectFirst { case _: ChiselOutputFileAnnotation => annotations }.getOrElse { - val x: Option[AnnotationSeq] = annotations - .collectFirst{ case a: ChiselCircuitAnnotation => - ChiselOutputFileAnnotation(a.circuit.name) +: annotations } + val x: Option[AnnotationSeq] = annotations.collectFirst { + case a: ChiselCircuitAnnotation => + ChiselOutputFileAnnotation(a.circuit.name) +: annotations + } x.getOrElse(annotations) } diff --git a/src/main/scala/chisel3/stage/phases/AddSerializationAnnotations.scala b/src/main/scala/chisel3/stage/phases/AddSerializationAnnotations.scala index 93425b07..d35b2f2e 100644 --- a/src/main/scala/chisel3/stage/phases/AddSerializationAnnotations.scala +++ b/src/main/scala/chisel3/stage/phases/AddSerializationAnnotations.scala @@ -22,7 +22,9 @@ class AddSerializationAnnotations extends Phase { def transform(annotations: AnnotationSeq): AnnotationSeq = { val chiselOptions = view[ChiselOptions](annotations) val circuit = chiselOptions.chiselCircuit.getOrElse { - throw new ChiselException(s"Unable to locate the elaborated circuit, did ${classOf[Elaborate].getName} run correctly") + throw new ChiselException( + s"Unable to locate the elaborated circuit, did ${classOf[Elaborate].getName} run correctly" + ) } val baseFilename = chiselOptions.outputFile.getOrElse(circuit.name) diff --git a/src/main/scala/chisel3/stage/phases/AspectPhase.scala b/src/main/scala/chisel3/stage/phases/AspectPhase.scala index 72965861..efe2c3a4 100644 --- a/src/main/scala/chisel3/stage/phases/AspectPhase.scala +++ b/src/main/scala/chisel3/stage/phases/AspectPhase.scala @@ -28,7 +28,7 @@ class AspectPhase extends Phase { Nil case other => Seq(other) } - if(dut.isDefined) { + if (dut.isDefined) { val newAnnotations = aspects.flatMap { _.resolveAspect(dut.get, remainingAnnotations) } remainingAnnotations ++ newAnnotations } else annotations diff --git a/src/main/scala/chisel3/stage/phases/Checks.scala b/src/main/scala/chisel3/stage/phases/Checks.scala index 1ff7f64c..55c90ccb 100644 --- a/src/main/scala/chisel3/stage/phases/Checks.scala +++ b/src/main/scala/chisel3/stage/phases/Checks.scala @@ -31,21 +31,24 @@ class Checks extends Phase { throw new OptionsException( s"""|At most one NoRunFirrtlCompilerAnnotation can be specified, but found '${noF.size}'. Did you duplicate: | - option or annotation: -chnrf, --no-run-firrtl, NoRunFirrtlCompilerAnnotation - |""".stripMargin) + |""".stripMargin + ) } if (st.size > 1) { throw new OptionsException( s"""|At most one PrintFullStackTraceAnnotation can be specified, but found '${noF.size}'. Did you duplicate: | - option or annotation: --full-stacktrace, PrintFullStackTraceAnnotation - |""".stripMargin) + |""".stripMargin + ) } if (outF.size > 1) { throw new OptionsException( s"""|At most one Chisel output file can be specified but found '${outF.size}'. Did you duplicate: | - option or annotation: --chisel-output-file, ChiselOutputFileAnnotation - |""".stripMargin) + |""".stripMargin + ) } annotations diff --git a/src/main/scala/chisel3/stage/phases/Convert.scala b/src/main/scala/chisel3/stage/phases/Convert.scala index b5b01b8d..014ed3f2 100644 --- a/src/main/scala/chisel3/stage/phases/Convert.scala +++ b/src/main/scala/chisel3/stage/phases/Convert.scala @@ -24,20 +24,13 @@ class Convert extends Phase { def transform(annotations: AnnotationSeq): AnnotationSeq = annotations.flatMap { case a: ChiselCircuitAnnotation => Some(a) ++ - /* Convert this Chisel Circuit to a FIRRTL Circuit */ - Some(FirrtlCircuitAnnotation(Converter.convert(a.circuit))) ++ - /* Convert all Chisel Annotations to FIRRTL Annotations */ - a - .circuit - .firrtlAnnotations ++ - a - .circuit - .annotations - .collect { + /* Convert this Chisel Circuit to a FIRRTL Circuit */ + Some(FirrtlCircuitAnnotation(Converter.convert(a.circuit))) ++ + /* Convert all Chisel Annotations to FIRRTL Annotations */ + a.circuit.firrtlAnnotations ++ + a.circuit.annotations.collect { case anno: RunFirrtlTransform => anno.transformClass - } - .distinct - .map { c: Class[_ <: Transform] => RunFirrtlTransformAnnotation(c.newInstance()) } + }.distinct.map { c: Class[_ <: Transform] => RunFirrtlTransformAnnotation(c.newInstance()) } case a => Some(a) } diff --git a/src/main/scala/chisel3/stage/phases/Elaborate.scala b/src/main/scala/chisel3/stage/phases/Elaborate.scala index e8f2623e..2cfb3200 100644 --- a/src/main/scala/chisel3/stage/phases/Elaborate.scala +++ b/src/main/scala/chisel3/stage/phases/Elaborate.scala @@ -20,18 +20,19 @@ class Elaborate extends Phase { override def invalidates(a: Phase) = false def transform(annotations: AnnotationSeq): AnnotationSeq = annotations.flatMap { - case ChiselGeneratorAnnotation(gen) => try { - val (circuit, dut) = Builder.build(Module(gen()), new DynamicContext(annotations)) - Seq(ChiselCircuitAnnotation(circuit), DesignAnnotation(dut)) - } catch { - /* if any throwable comes back and we're in "stack trace trimming" mode, then print an error and trim the stack trace - */ - case scala.util.control.NonFatal(a) => - if (!view[ChiselOptions](annotations).printFullStackTrace) { - a.trimStackTraceToUserCode() - } - throw(a) - } + case ChiselGeneratorAnnotation(gen) => + try { + val (circuit, dut) = Builder.build(Module(gen()), new DynamicContext(annotations)) + Seq(ChiselCircuitAnnotation(circuit), DesignAnnotation(dut)) + } catch { + /* if any throwable comes back and we're in "stack trace trimming" mode, then print an error and trim the stack trace + */ + case scala.util.control.NonFatal(a) => + if (!view[ChiselOptions](annotations).printFullStackTrace) { + a.trimStackTraceToUserCode() + } + throw (a) + } case a => Some(a) } diff --git a/src/main/scala/chisel3/stage/phases/Emitter.scala b/src/main/scala/chisel3/stage/phases/Emitter.scala index 756c5db4..254f8add 100644 --- a/src/main/scala/chisel3/stage/phases/Emitter.scala +++ b/src/main/scala/chisel3/stage/phases/Emitter.scala @@ -25,10 +25,12 @@ import java.io.{File, FileWriter} class Emitter extends Phase { override def prerequisites = - Seq( Dependency[Elaborate], - Dependency[AddImplicitOutputFile], - Dependency[AddImplicitOutputAnnotationFile], - Dependency[MaybeAspectPhase] ) + Seq( + Dependency[Elaborate], + Dependency[AddImplicitOutputFile], + Dependency[AddImplicitOutputAnnotationFile], + Dependency[MaybeAspectPhase] + ) override def optionalPrerequisites = Seq.empty override def optionalPrerequisiteOf = Seq(Dependency[Convert]) override def invalidates(a: Phase) = false diff --git a/src/main/scala/chisel3/stage/phases/MaybeAspectPhase.scala b/src/main/scala/chisel3/stage/phases/MaybeAspectPhase.scala index c26cbd82..dcd0dfe0 100644 --- a/src/main/scala/chisel3/stage/phases/MaybeAspectPhase.scala +++ b/src/main/scala/chisel3/stage/phases/MaybeAspectPhase.scala @@ -16,7 +16,7 @@ class MaybeAspectPhase extends Phase { override def invalidates(a: Phase) = false def transform(annotations: AnnotationSeq): AnnotationSeq = { - if(annotations.collectFirst { case a: Aspect[_] => annotations }.isDefined) { + if (annotations.collectFirst { case a: Aspect[_] => annotations }.isDefined) { new AspectPhase().transform(annotations) } else annotations } diff --git a/src/main/scala/chisel3/stage/phases/MaybeFirrtlStage.scala b/src/main/scala/chisel3/stage/phases/MaybeFirrtlStage.scala index cd68e04c..3533d8d1 100644 --- a/src/main/scala/chisel3/stage/phases/MaybeFirrtlStage.scala +++ b/src/main/scala/chisel3/stage/phases/MaybeFirrtlStage.scala @@ -17,8 +17,8 @@ class MaybeFirrtlStage extends Phase { override def optionalPrerequisiteOf = Seq.empty override def invalidates(a: Phase) = false - def transform(annotations: AnnotationSeq): AnnotationSeq = annotations - .collectFirst { case NoRunFirrtlCompilerAnnotation => annotations } - .getOrElse { (new FirrtlStage).transform(annotations) } + def transform(annotations: AnnotationSeq): AnnotationSeq = annotations.collectFirst { + case NoRunFirrtlCompilerAnnotation => annotations + }.getOrElse { (new FirrtlStage).transform(annotations) } } diff --git a/src/main/scala/chisel3/testers/BasicTester.scala b/src/main/scala/chisel3/testers/BasicTester.scala index 99002660..5e28a523 100644 --- a/src/main/scala/chisel3/testers/BasicTester.scala +++ b/src/main/scala/chisel3/testers/BasicTester.scala @@ -13,7 +13,7 @@ class BasicTester extends Module() { // The testbench has no IOs, rather it should communicate using printf, assert, and stop. val io = IO(new Bundle() {}) - def popCount(n: Long): Int = n.toBinaryString.count(_=='1') + def popCount(n: Long): Int = n.toBinaryString.count(_ == '1') /** Ends the test reporting success. * diff --git a/src/main/scala/chisel3/testers/TesterDriver.scala b/src/main/scala/chisel3/testers/TesterDriver.scala index e87aceca..9c4b2da9 100644 --- a/src/main/scala/chisel3/testers/TesterDriver.scala +++ b/src/main/scala/chisel3/testers/TesterDriver.scala @@ -16,24 +16,27 @@ import firrtl.transforms.BlackBoxSourceHelper.writeResourceToDirectory object TesterDriver extends BackendCompilationUtilities { private[chisel3] trait Backend extends NoTargetAnnotation with Unserializable { - def execute(t: () => BasicTester, - additionalVResources: Seq[String] = Seq(), - annotations: AnnotationSeq = Seq(), - nameHint: Option[String] = None - ): Boolean + def execute( + t: () => BasicTester, + additionalVResources: Seq[String] = Seq(), + annotations: AnnotationSeq = Seq(), + nameHint: Option[String] = None + ): Boolean } case object VerilatorBackend extends Backend { + /** For use with modules that should successfully be elaborated by the - * frontend, and which can be turned into executables with assertions. */ - def execute(t: () => BasicTester, - additionalVResources: Seq[String] = Seq(), - annotations: AnnotationSeq = Seq(), - nameHint: Option[String] = None - ): Boolean = { + * frontend, and which can be turned into executables with assertions. + */ + def execute( + t: () => BasicTester, + additionalVResources: Seq[String] = Seq(), + annotations: AnnotationSeq = Seq(), + nameHint: Option[String] = None + ): Boolean = { val pm = new PhaseManager( - targets = Seq(Dependency[AddImplicitTesterDirectory], - Dependency[Emitter], - Dependency[Convert])) + targets = Seq(Dependency[AddImplicitTesterDirectory], Dependency[Emitter], Dependency[Convert]) + ) val annotationsx = pm.transform(ChiselGeneratorAnnotation(finishWrapper(t)) +: annotations) @@ -41,7 +44,7 @@ object TesterDriver extends BackendCompilationUtilities { val path = annotationsx.collectFirst { case TargetDirAnnotation(dir) => dir }.map(new File(_)).get // Copy CPP harness and other Verilog sources from resources into files - val cppHarness = new File(path, "top.cpp") + val cppHarness = new File(path, "top.cpp") copyResourceToFile("/chisel3/top.cpp", cppHarness) // NOTE: firrtl.Driver.execute() may end up copying these same resources in its BlackBoxSourceHelper code. // As long as the same names are used for the output files, and we avoid including duplicate files @@ -54,8 +57,10 @@ object TesterDriver extends BackendCompilationUtilities { (new FirrtlStage).execute(Array("--compiler", "verilog"), annotationsx) // Use sys.Process to invoke a bunch of backend stuff, then run the resulting exe - if ((verilogToCpp(target, path, additionalVFiles, cppHarness) #&& - cppToExe(target, path)).! == 0) { + if ( + (verilogToCpp(target, path, additionalVFiles, cppHarness) #&& + cppToExe(target, path)).! == 0 + ) { executeExpectingSuccess(target, path) } else { false @@ -77,21 +82,26 @@ object TesterDriver extends BackendCompilationUtilities { override def invalidates(a: Phase) = false override def transform(a: AnnotationSeq) = a.flatMap { - case a@ ChiselCircuitAnnotation(circuit) => - Seq(a, TargetDirAnnotation( - firrtl.util.BackendCompilationUtilities.createTestDirectory(circuit.name) - .getAbsolutePath - .toString)) + case a @ ChiselCircuitAnnotation(circuit) => + Seq( + a, + TargetDirAnnotation( + firrtl.util.BackendCompilationUtilities.createTestDirectory(circuit.name).getAbsolutePath.toString + ) + ) case a => Seq(a) } } /** For use with modules that should successfully be elaborated by the - * frontend, and which can be turned into executables with assertions. */ - def execute(t: () => BasicTester, - additionalVResources: Seq[String] = Seq(), - annotations: AnnotationSeq = Seq(), - nameHint: Option[String] = None): Boolean = { + * frontend, and which can be turned into executables with assertions. + */ + def execute( + t: () => BasicTester, + additionalVResources: Seq[String] = Seq(), + annotations: AnnotationSeq = Seq(), + nameHint: Option[String] = None + ): Boolean = { val backendAnnotations = annotations.collect { case anno: Backend => anno } val backendAnnotation = if (backendAnnotations.length == 1) { @@ -109,11 +119,11 @@ object TesterDriver extends BackendCompilationUtilities { * The finish method is a hook for code that augments the circuit built in the constructor. */ def finishWrapper(test: () => BasicTester): () => BasicTester = { () => - { - val tester = test() - tester.finish() - tester - } + { + val tester = test() + tester.finish() + tester + } } } diff --git a/src/main/scala/chisel3/testers/package.scala b/src/main/scala/chisel3/testers/package.scala index f60f7cc2..f20a7977 100644 --- a/src/main/scala/chisel3/testers/package.scala +++ b/src/main/scala/chisel3/testers/package.scala @@ -3,8 +3,5 @@ package chisel3 /** The testers package provides the basic interface for chisel testers. - * */ -package object testers { - -} +package object testers {} diff --git a/src/main/scala/chisel3/util/Arbiter.scala b/src/main/scala/chisel3/util/Arbiter.scala index b68acae1..220a12b1 100644 --- a/src/main/scala/chisel3/util/Arbiter.scala +++ b/src/main/scala/chisel3/util/Arbiter.scala @@ -6,7 +6,7 @@ package chisel3.util import chisel3._ -import chisel3.internal.naming.chiselName // can't use chisel3_ version because of compile order +import chisel3.internal.naming.chiselName // can't use chisel3_ version because of compile order /** IO bundle definition for an Arbiter, which takes some number of ready-valid inputs and outputs * (selects) at most one. @@ -18,20 +18,22 @@ import chisel3.internal.naming.chiselName // can't use chisel3_ version because class ArbiterIO[T <: Data](private val gen: T, val n: Int) extends Bundle { // See github.com/freechipsproject/chisel3/issues/765 for why gen is a private val and proposed replacement APIs. -/** Input data, one per potential sender - * - * @group Signals - */ - val in = Flipped(Vec(n, Decoupled(gen))) -/** Output data after arbitration - * - * @group Signals - */ + /** Input data, one per potential sender + * + * @group Signals + */ + val in = Flipped(Vec(n, Decoupled(gen))) + + /** Output data after arbitration + * + * @group Signals + */ val out = Decoupled(gen) -/** One-Hot vector indicating which output was chosen - * - * @group Signals - */ + + /** One-Hot vector indicating which output was chosen + * + * @group Signals + */ val chosen = Output(UInt(log2Ceil(n).W)) } @@ -46,7 +48,7 @@ private object ArbiterCtrl { } abstract class LockingArbiterLike[T <: Data](gen: T, n: Int, count: Int, needsLock: Option[T => Bool]) extends Module { - def grant: Seq[Bool] + def grant: Seq[Bool] def choice: UInt val io = IO(new ArbiterIO(gen, n)) @@ -60,16 +62,16 @@ abstract class LockingArbiterLike[T <: Data](gen: T, n: Int, count: Int, needsLo val locked = lockCount.value =/= 0.U val wantsLock = needsLock.map(_(io.out.bits)).getOrElse(true.B) - when (io.out.fire && wantsLock) { + when(io.out.fire && wantsLock) { lockIdx := io.chosen lockCount.inc() } - when (locked) { io.chosen := lockIdx } - for ((in, (g, i)) <- io.in zip grant.zipWithIndex) + when(locked) { io.chosen := lockIdx } + for ((in, (g, i)) <- io.in.zip(grant.zipWithIndex)) in.ready := Mux(locked, lockIdx === i.asUInt, g) && io.out.ready } else { - for ((in, g) <- io.in zip grant) + for ((in, g) <- io.in.zip(grant)) in.ready := g && io.out.ready } } @@ -78,27 +80,27 @@ class LockingRRArbiter[T <: Data](gen: T, n: Int, count: Int, needsLock: Option[ extends LockingArbiterLike[T](gen, n, count, needsLock) { lazy val lastGrant = RegEnable(io.chosen, io.out.fire) lazy val grantMask = (0 until n).map(_.asUInt > lastGrant) - lazy val validMask = io.in zip grantMask map { case (in, g) => in.valid && g } + lazy val validMask = io.in.zip(grantMask).map { case (in, g) => in.valid && g } override def grant: Seq[Bool] = { val ctrl = ArbiterCtrl((0 until n).map(i => validMask(i)) ++ io.in.map(_.valid)) (0 until n).map(i => ctrl(i) && grantMask(i) || ctrl(i + n)) } - override lazy val choice = WireDefault((n-1).asUInt) - for (i <- n-2 to 0 by -1) - when (io.in(i).valid) { choice := i.asUInt } - for (i <- n-1 to 1 by -1) - when (validMask(i)) { choice := i.asUInt } + override lazy val choice = WireDefault((n - 1).asUInt) + for (i <- n - 2 to 0 by -1) + when(io.in(i).valid) { choice := i.asUInt } + for (i <- n - 1 to 1 by -1) + when(validMask(i)) { choice := i.asUInt } } class LockingArbiter[T <: Data](gen: T, n: Int, count: Int, needsLock: Option[T => Bool] = None) extends LockingArbiterLike[T](gen, n, count, needsLock) { def grant: Seq[Bool] = ArbiterCtrl(io.in.map(_.valid)) - override lazy val choice = WireDefault((n-1).asUInt) - for (i <- n-2 to 0 by -1) - when (io.in(i).valid) { choice := i.asUInt } + override lazy val choice = WireDefault((n - 1).asUInt) + for (i <- n - 2 to 0 by -1) + when(io.in(i).valid) { choice := i.asUInt } } /** Hardware module that is used to sequence n producers into 1 consumer. @@ -133,17 +135,17 @@ class RRArbiter[T <: Data](val gen: T, val n: Int) extends LockingRRArbiter[T](g class Arbiter[T <: Data](val gen: T, val n: Int) extends Module { val io = IO(new ArbiterIO(gen, n)) - io.chosen := (n-1).asUInt - io.out.bits := io.in(n-1).bits - for (i <- n-2 to 0 by -1) { - when (io.in(i).valid) { + io.chosen := (n - 1).asUInt + io.out.bits := io.in(n - 1).bits + for (i <- n - 2 to 0 by -1) { + when(io.in(i).valid) { io.chosen := i.asUInt io.out.bits := io.in(i).bits } } val grant = ArbiterCtrl(io.in.map(_.valid)) - for ((in, g) <- io.in zip grant) + for ((in, g) <- io.in.zip(grant)) in.ready := g && io.out.ready io.out.valid := !grant.last || io.in.last.valid } diff --git a/src/main/scala/chisel3/util/BitPat.scala b/src/main/scala/chisel3/util/BitPat.scala index 808245de..d27fee14 100644 --- a/src/main/scala/chisel3/util/BitPat.scala +++ b/src/main/scala/chisel3/util/BitPat.scala @@ -6,12 +6,11 @@ import scala.language.experimental.macros import chisel3._ import chisel3.internal.sourceinfo.{SourceInfo, SourceInfoTransform} - object BitPat { private[chisel3] implicit val bitPatOrder = new Ordering[BitPat] { import scala.math.Ordered.orderingToOrdered - def compare(x: BitPat, y: BitPat): Int = (x.getWidth, x.value, x.mask) compare (y.getWidth, y.value, y.mask) + def compare(x: BitPat, y: BitPat): Int = (x.getWidth, x.value, x.mask).compare(y.getWidth, y.value, y.mask) } /** Parses a bit pattern string into (bits, mask, width). @@ -33,7 +32,7 @@ object BitPat { var mask = BigInt(0) var count = 0 for (d <- x.tail) { - if (! (d == '_' || d.isWhitespace)) { + if (!(d == '_' || d.isWhitespace)) { require("01?".contains(d), "Literal: " + x + " contains illegal character: " + d) mask = (mask << 1) + (if (d == '?') 0 else 1) bits = (bits << 1) + (if (d == '1') 1 else 0) @@ -105,15 +104,14 @@ object BitPat { import scala.language.experimental.macros - final def === (that: BitPat): Bool = macro SourceInfoTransform.thatArg - final def =/= (that: BitPat): Bool = macro SourceInfoTransform.thatArg + final def ===(that: BitPat): Bool = macro SourceInfoTransform.thatArg + final def =/=(that: BitPat): Bool = macro SourceInfoTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_=== (that: BitPat) - (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = that === x + def do_===(that: BitPat)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = that === x + /** @group SourceInfoTransformMacro */ - def do_=/= (that: BitPat) - (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = that =/= x + def do_=/=(that: BitPat)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = that =/= x } } @@ -148,6 +146,7 @@ package experimental { /** A Set of [[BitPat]] represents a set of bit vector with mask. */ sealed trait BitSet { outer => + /** all [[BitPat]] elements in [[terms]] make up this [[BitSet]]. * all [[terms]] should be have the same width. */ @@ -229,7 +228,6 @@ package experimental { } - /** Bit patterns are literals with masks, used to represent values with don't * care bits. Equality comparisons will ignore don't care bits. * @@ -239,7 +237,9 @@ package experimental { * "b10001".U === BitPat("b101??") // evaluates to false.B * }}} */ -sealed class BitPat(val value: BigInt, val mask: BigInt, val width: Int) extends util.experimental.BitSet with SourceInfoDoc { +sealed class BitPat(val value: BigInt, val mask: BigInt, val width: Int) + extends util.experimental.BitSet + with SourceInfoDoc { import chisel3.util.experimental.BitSet def terms = Set(this) @@ -247,11 +247,11 @@ sealed class BitPat(val value: BigInt, val mask: BigInt, val width: Int) extends * Get specified width of said BitPat */ override def getWidth: Int = width - def apply(x: Int): BitPat = macro SourceInfoTransform.xArg - def apply(x: Int, y: Int): BitPat = macro SourceInfoTransform.xyArg - def === (that: UInt): Bool = macro SourceInfoTransform.thatArg - def =/= (that: UInt): Bool = macro SourceInfoTransform.thatArg - def ## (that: BitPat): BitPat = macro SourceInfoTransform.thatArg + def apply(x: Int): BitPat = macro SourceInfoTransform.xArg + def apply(x: Int, y: Int): BitPat = macro SourceInfoTransform.xyArg + def ===(that: UInt): Bool = macro SourceInfoTransform.thatArg + def =/=(that: UInt): Bool = macro SourceInfoTransform.thatArg + def ##(that: BitPat): BitPat = macro SourceInfoTransform.thatArg /** @group SourceInfoTransformMacro */ def do_apply(x: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): BitPat = { @@ -266,15 +266,15 @@ sealed class BitPat(val value: BigInt, val mask: BigInt, val width: Int) extends } /** @group SourceInfoTransformMacro */ - def do_=== (that: UInt) - (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = { + def do_===(that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = { value.asUInt === (that & mask.asUInt) } + /** @group SourceInfoTransformMacro */ - def do_=/= (that: UInt) - (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = { + def do_=/=(that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = { !(this === that) } + /** @group SourceInfoTransformMacro */ def do_##(that: BitPat)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): BitPat = { new BitPat((value << that.getWidth) + that.value, (mask << that.getWidth) + that.mask, this.width + that.getWidth) diff --git a/src/main/scala/chisel3/util/Bitwise.scala b/src/main/scala/chisel3/util/Bitwise.scala index ddf7546a..0d8318bf 100644 --- a/src/main/scala/chisel3/util/Bitwise.scala +++ b/src/main/scala/chisel3/util/Bitwise.scala @@ -19,6 +19,7 @@ import chisel3._ * }}} */ object FillInterleaved { + /** Creates n repetitions of each bit of x in order. * * Output data-equivalent to in(size(in)-1) (n times) ## ... ## in(1) (n times) ## in(0) (n times) @@ -58,6 +59,7 @@ object PopCount { * }}} */ object Fill { + /** Create n repetitions of x using a tree fanout topology. * * Output data-equivalent to x ## x ## ... ## x (n repetitions). @@ -66,8 +68,8 @@ object Fill { def apply(n: Int, x: UInt): UInt = { n match { case _ if n < 0 => throw new IllegalArgumentException(s"n (=$n) must be nonnegative integer.") - case 0 => UInt(0.W) - case 1 => x + case 0 => UInt(0.W) + case 1 => x case _ if x.isWidthKnown && x.getWidth == 1 => Mux(x.asBool, ((BigInt(1) << n) - 1).asUInt(n.W), 0.U(n.W)) case _ => @@ -75,7 +77,7 @@ object Fill { val p2 = Array.ofDim[UInt](nBits) p2(0) = x for (i <- 1 until p2.length) - p2(i) = Cat(p2(i-1), p2(i-1)) + p2(i) = Cat(p2(i - 1), p2(i - 1)) Cat((0 until nBits).filter(i => (n & (1 << i)) != 0).map(p2(_))) } } @@ -91,22 +93,22 @@ object Fill { */ object Reverse { private def doit(in: UInt, length: Int): UInt = length match { - case _ if length < 0 => throw new IllegalArgumentException(s"length (=$length) must be nonnegative integer.") - case _ if length <= 1 => in + case _ if length < 0 => throw new IllegalArgumentException(s"length (=$length) must be nonnegative integer.") + case _ if length <= 1 => in case _ if isPow2(length) && length >= 8 && length <= 64 => // This esoterica improves simulation performance var res = in var shift = length >> 1 var mask = ((BigInt(1) << length) - 1).asUInt(length.W) do { - mask = mask ^ (mask(length-shift-1,0) << shift) - res = ((res >> shift) & mask) | ((res(length-shift-1,0) << shift) & ~mask) + mask = mask ^ (mask(length - shift - 1, 0) << shift) + res = ((res >> shift) & mask) | ((res(length - shift - 1, 0) << shift) & ~mask) shift = shift >> 1 } while (shift > 0) res case _ => - val half = (1 << log2Ceil(length))/2 - Cat(doit(in(half-1,0), half), doit(in(length-1,half), length-half)) + val half = (1 << log2Ceil(length)) / 2 + Cat(doit(in(half - 1, 0), half), doit(in(length - 1, half), length - half)) } def apply(in: UInt): UInt = doit(in, in.getWidth) diff --git a/src/main/scala/chisel3/util/BlackBoxUtils.scala b/src/main/scala/chisel3/util/BlackBoxUtils.scala index 443d7f3e..7c4400f8 100644 --- a/src/main/scala/chisel3/util/BlackBoxUtils.scala +++ b/src/main/scala/chisel3/util/BlackBoxUtils.scala @@ -4,14 +4,20 @@ package chisel3.util import chisel3._ import chisel3.experimental.{ChiselAnnotation, RunFirrtlTransform} -import firrtl.transforms.{BlackBoxPathAnno, BlackBoxResourceAnno, BlackBoxInlineAnno, BlackBoxSourceHelper, - BlackBoxNotFoundException} +import firrtl.transforms.{ + BlackBoxInlineAnno, + BlackBoxNotFoundException, + BlackBoxPathAnno, + BlackBoxResourceAnno, + BlackBoxSourceHelper +} import firrtl.annotations.ModuleName import logger.LazyLogging private[util] object BlackBoxHelpers { implicit class BlackBoxInlineAnnoHelpers(anno: BlackBoxInlineAnno.type) extends LazyLogging { + /** Generate a BlackBoxInlineAnno from a Java Resource and a module name. */ def fromResource(resourceName: String, moduleName: ModuleName) = try { val blackBoxFile = os.resource / os.RelPath(resourceName.dropWhile(_ == '/')) diff --git a/src/main/scala/chisel3/util/Cat.scala b/src/main/scala/chisel3/util/Cat.scala index 3369eb18..c5adce56 100644 --- a/src/main/scala/chisel3/util/Cat.scala +++ b/src/main/scala/chisel3/util/Cat.scala @@ -15,6 +15,7 @@ import chisel3._ * }}} */ object Cat { + /** Concatenates the argument data elements, in argument order, together. The first argument * forms the most significant bits, while the last argument forms the least significant bits. */ diff --git a/src/main/scala/chisel3/util/CircuitMath.scala b/src/main/scala/chisel3/util/CircuitMath.scala index 58961630..df60f059 100644 --- a/src/main/scala/chisel3/util/CircuitMath.scala +++ b/src/main/scala/chisel3/util/CircuitMath.scala @@ -6,7 +6,7 @@ package chisel3.util import chisel3._ -import chisel3.internal.naming.chiselName // can't use chisel3_ version because of compile order +import chisel3.internal.naming.chiselName // can't use chisel3_ version because of compile order /** Returns the base-2 integer logarithm of an UInt. * @@ -17,9 +17,9 @@ import chisel3.internal.naming.chiselName // can't use chisel3_ version because * Log2(13.U) // evaluates to 3.U (truncation) * Log2(myUIntWire) * }}} - * */ object Log2 { + /** Returns the base-2 integer logarithm of the least-significant `width` bits of an UInt. */ @chiselName @@ -29,11 +29,11 @@ object Log2 { } else if (width == 2) { x(1) } else if (width <= divideAndConquerThreshold) { - Mux(x(width-1), (width-1).asUInt, apply(x, width-1)) + Mux(x(width - 1), (width - 1).asUInt, apply(x, width - 1)) } else { val mid = 1 << (log2Ceil(width) - 1) - val hi = x(width-1, mid) - val lo = x(mid-1, 0) + val hi = x(width - 1, mid) + val lo = x(mid - 1, 0) val useHi = hi.orR Cat(useHi, Mux(useHi, Log2(hi, width - mid), Log2(lo, mid))) } diff --git a/src/main/scala/chisel3/util/Conditional.scala b/src/main/scala/chisel3/util/Conditional.scala index 1ac94bfe..754112eb 100644 --- a/src/main/scala/chisel3/util/Conditional.scala +++ b/src/main/scala/chisel3/util/Conditional.scala @@ -17,7 +17,13 @@ import chisel3.internal.sourceinfo.SourceInfo * @note DO NOT USE. This API is subject to change without warning. */ class SwitchContext[T <: Element](cond: T, whenContext: Option[WhenContext], lits: Set[BigInt]) { - def is(v: Iterable[T])(block: => Any)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SwitchContext[T] = { + def is( + v: Iterable[T] + )(block: => Any + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): SwitchContext[T] = { if (!v.isEmpty) { val newLits = v.map { w => require(w.litOption.isDefined, "is condition must be literal") @@ -26,17 +32,25 @@ class SwitchContext[T <: Element](cond: T, whenContext: Option[WhenContext], lit value } // def instead of val so that logic ends up in legal place - def p = v.map(_.asUInt === cond.asUInt).reduce(_||_) + def p = v.map(_.asUInt === cond.asUInt).reduce(_ || _) whenContext match { case Some(w) => new SwitchContext(cond, Some(w.elsewhen(p)(block)), lits ++ newLits) - case None => new SwitchContext(cond, Some(when(p)(block)), lits ++ newLits) + case None => new SwitchContext(cond, Some(when(p)(block)), lits ++ newLits) } } else { this } } - def is(v: T)(block: => Any)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SwitchContext[T] = is(Seq(v))(block) - def is(v: T, vr: T*)(block: => Any)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SwitchContext[T] = is(v :: vr.toList)(block) + def is(v: T)(block: => Any)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SwitchContext[T] = + is(Seq(v))(block) + def is( + v: T, + vr: T* + )(block: => Any + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): SwitchContext[T] = is(v :: vr.toList)(block) } /** Use to specify cases in a [[switch]] block, equivalent to a [[when$ when]] block comparing to @@ -84,15 +98,17 @@ object is { */ object switch { def apply[T <: Element](cond: T)(x: => Any): Unit = macro impl - def impl(c: Context)(cond: c.Tree)(x: c.Tree): c.Tree = { import c.universe._ + def impl(c: Context)(cond: c.Tree)(x: c.Tree): c.Tree = { + import c.universe._ val q"..$body" = x val res = body.foldLeft(q"""new chisel3.util.SwitchContext($cond, None, Set.empty)""") { - case (acc, tree) => tree match { - // TODO: remove when Chisel compatibility package is removed - case q"Chisel.`package`.is.apply( ..$params )( ..$body )" => q"$acc.is( ..$params )( ..$body )" - case q"chisel3.util.is.apply( ..$params )( ..$body )" => q"$acc.is( ..$params )( ..$body )" - case b => throw new Exception(s"Cannot include blocks that do not begin with is() in switch.") - } + case (acc, tree) => + tree match { + // TODO: remove when Chisel compatibility package is removed + case q"Chisel.`package`.is.apply( ..$params )( ..$body )" => q"$acc.is( ..$params )( ..$body )" + case q"chisel3.util.is.apply( ..$params )( ..$body )" => q"$acc.is( ..$params )( ..$body )" + case b => throw new Exception(s"Cannot include blocks that do not begin with is() in switch.") + } } q"""{ $res }""" } diff --git a/src/main/scala/chisel3/util/Counter.scala b/src/main/scala/chisel3/util/Counter.scala index 5910c703..ef1eff9f 100644 --- a/src/main/scala/chisel3/util/Counter.scala +++ b/src/main/scala/chisel3/util/Counter.scala @@ -3,7 +3,7 @@ package chisel3.util import chisel3._ -import chisel3.internal.naming.chiselName // can't use chisel3_ version because of compile order +import chisel3.internal.naming.chiselName // can't use chisel3_ version because of compile order /** Used to generate an inline (logic directly in the containing Module, no internal Module is created) * hardware counter. @@ -42,11 +42,13 @@ class Counter private (r: Range, oldN: Option[Int] = None) { */ def n: Int = oldN match { case Some(x) => x - case None => + case None => // Reasonable for typical ranges - require(r.start == 0 && r.step == 1, + require( + r.start == 0 && r.step == 1, s"Counter.n only defined on ranges starting at 0 with step == 1, got $r. " + - "Use underlying range.") + "Use underlying range." + ) r.last + 1 } @@ -98,14 +100,14 @@ class Counter private (r: Range, oldN: Option[Int] = None) { } } -object Counter -{ +object Counter { + /** Instantiate a [[Counter! counter]] with the specified number of counts. */ def apply(n: Int): Counter = new Counter(n) /** Instantiate a [[Counter! counter]] with the specified number of counts and a gate. - * + * * @param cond condition that controls whether the counter increments this cycle * @param n number of counts before the counter resets * @return tuple of the counter value and whether the counter will wrap (the value is at @@ -115,7 +117,7 @@ object Counter def apply(cond: Bool, n: Int): (UInt, Bool) = { val c = new Counter(n) val wrap = WireInit(false.B) - when (cond) { wrap := c.inc() } + when(cond) { wrap := c.inc() } (c.value, wrap) } diff --git a/src/main/scala/chisel3/util/Decoupled.scala b/src/main/scala/chisel3/util/Decoupled.scala index 4b8b3eeb..5c71a4ea 100644 --- a/src/main/scala/chisel3/util/Decoupled.scala +++ b/src/main/scala/chisel3/util/Decoupled.scala @@ -6,8 +6,8 @@ package chisel3.util import chisel3._ -import chisel3.experimental.{DataMirror, Direction, requireIsChiselType} -import chisel3.internal.naming._ // can't use chisel3_ version because of compile order +import chisel3.experimental.{requireIsChiselType, DataMirror, Direction} +import chisel3.internal.naming._ // can't use chisel3_ version because of compile order /** An I/O Bundle containing 'valid' and 'ready' signals that handshake * the transfer of data stored in the 'bits' subfield. @@ -18,40 +18,41 @@ import chisel3.internal.naming._ // can't use chisel3_ version because of compi * @param gen the type of data to be wrapped in Ready/Valid * @groupdesc Signals The actual hardware fields of the Bundle */ -abstract class ReadyValidIO[+T <: Data](gen: T) extends Bundle -{ +abstract class ReadyValidIO[+T <: Data](gen: T) extends Bundle { // Compatibility hack for rocket-chip private val genType = (DataMirror.internal.isSynthesizable(gen), chisel3.internal.Builder.currentModule) match { - case (true, Some(module: Module)) - if !module.compileOptions.declaredTypeMustBeUnbound => chiselTypeOf(gen) + case (true, Some(module: Module)) if !module.compileOptions.declaredTypeMustBeUnbound => chiselTypeOf(gen) case _ => gen } -/** Indicates that the consumer is ready to accept the data this cycle - * @group Signals - */ + /** Indicates that the consumer is ready to accept the data this cycle + * @group Signals + */ val ready = Input(Bool()) - -/** Indicates that the producer has put valid data in 'bits' - * @group Signals - */ + + /** Indicates that the producer has put valid data in 'bits' + * @group Signals + */ val valid = Output(Bool()) - -/** The data to be transferred when ready and valid are asserted at the same cycle - * @group Signals - */ - val bits = Output(genType) + + /** The data to be transferred when ready and valid are asserted at the same cycle + * @group Signals + */ + val bits = Output(genType) } object ReadyValidIO { - implicit class AddMethodsToReadyValid[T<:Data](target: ReadyValidIO[T]) { + implicit class AddMethodsToReadyValid[T <: Data](target: ReadyValidIO[T]) { /** Indicates if IO is both ready and valid - */ + */ def fire: Bool = target.ready && target.valid - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) def fire(dummy: Int = 0): Bool = fire /** Push dat onto the output bits of this interface to let the consumer know it has happened. @@ -99,8 +100,8 @@ object ReadyValidIO { class DecoupledIO[+T <: Data](gen: T) extends ReadyValidIO[T](gen) /** This factory adds a decoupled handshaking protocol to a data bundle. */ -object Decoupled -{ +object Decoupled { + /** Wraps some Data with a DecoupledIO interface. */ def apply[T <: Data](gen: T): DecoupledIO[T] = new DecoupledIO(gen) @@ -110,6 +111,7 @@ object Decoupled // Both of these methods return DecoupledIO parameterized by the most generic type: Data /** Returns a [[DecoupledIO]] inteface with no payload */ def apply(): DecoupledIO[Data] = apply(new EmptyBundle) + /** Returns a [[DecoupledIO]] inteface with no payload */ def empty: DecoupledIO[Data] = Decoupled() @@ -119,7 +121,10 @@ object Decoupled */ @chiselName def apply[T <: Data](irr: IrrevocableIO[T]): DecoupledIO[T] = { - require(DataMirror.directionOf(irr.bits) == Direction.Output, "Only safe to cast produced Irrevocable bits to Decoupled.") + require( + DataMirror.directionOf(irr.bits) == Direction.Output, + "Only safe to cast produced Irrevocable bits to Decoupled." + ) val d = Wire(new DecoupledIO(chiselTypeOf(irr.bits))) d.bits := irr.bits d.valid := irr.valid @@ -138,8 +143,7 @@ object Decoupled class IrrevocableIO[+T <: Data](gen: T) extends ReadyValidIO[T](gen) /** Factory adds an irrevocable handshaking protocol to a data bundle. */ -object Irrevocable -{ +object Irrevocable { def apply[T <: Data](gen: T): IrrevocableIO[T] = new IrrevocableIO(gen) /** Upconverts a DecoupledIO input to an IrrevocableIO, allowing an IrrevocableIO to be used @@ -148,7 +152,10 @@ object Irrevocable * @note unsafe (and will error) on the consumer (output) side of an DecoupledIO */ def apply[T <: Data](dec: DecoupledIO[T]): IrrevocableIO[T] = { - require(DataMirror.directionOf(dec.bits) == Direction.Input, "Only safe to cast consumed Decoupled bits to Irrevocable.") + require( + DataMirror.directionOf(dec.bits) == Direction.Input, + "Only safe to cast consumed Decoupled bits to Irrevocable." + ) val i = Wire(new IrrevocableIO(chiselTypeOf(dec.bits))) dec.bits := i.bits dec.valid := i.valid @@ -161,13 +168,14 @@ object Irrevocable * @param gen The type of data to enqueue */ object EnqIO { - def apply[T<:Data](gen: T): DecoupledIO[T] = Decoupled(gen) + def apply[T <: Data](gen: T): DecoupledIO[T] = Decoupled(gen) } + /** Consumer - drives (outputs) ready, inputs valid and bits. * @param gen The type of data to dequeue */ object DeqIO { - def apply[T<:Data](gen: T): DecoupledIO[T] = Flipped(Decoupled(gen)) + def apply[T <: Data](gen: T): DecoupledIO[T] = Flipped(Decoupled(gen)) } /** An I/O Bundle for Queues @@ -176,28 +184,34 @@ object DeqIO { * @param hasFlush A boolean for whether the generated Queue is flushable * @groupdesc Signals The hardware fields of the Bundle */ -class QueueIO[T <: Data](private val gen: T, val entries: Int, val hasFlush: Boolean = false) extends Bundle -{ // See github.com/freechipsproject/chisel3/issues/765 for why gen is a private val and proposed replacement APIs. +class QueueIO[T <: Data]( + private val gen: T, + val entries: Int, + val hasFlush: Boolean = false) + extends Bundle { // See github.com/freechipsproject/chisel3/issues/765 for why gen is a private val and proposed replacement APIs. /* These may look inverted, because the names (enq/deq) are from the perspective of the client, * but internally, the queue implementation itself sits on the other side * of the interface so uses the flipped instance. */ - /** I/O to enqueue data (client is producer, and Queue object is consumer), is [[Chisel.DecoupledIO]] flipped. + /** I/O to enqueue data (client is producer, and Queue object is consumer), is [[Chisel.DecoupledIO]] flipped. * @group Signals */ val enq = Flipped(EnqIO(gen)) + /** I/O to dequeue data (client is consumer and Queue object is producer), is [[Chisel.DecoupledIO]] * @group Signals */ val deq = Flipped(DeqIO(gen)) - /** The current amount of data in the queue + + /** The current amount of data in the queue * @group Signals */ val count = Output(UInt(log2Ceil(entries + 1).W)) + /** When asserted, reset the enqueue and dequeue pointers, effectively flushing the queue (Optional IO for a flushable Queue) * @group Signals - */ + */ val flush = if (hasFlush) Some(Input(Bool())) else None } @@ -218,13 +232,15 @@ class QueueIO[T <: Data](private val gen: T, val entries: Int, val hasFlush: Boo * }}} */ @chiselName -class Queue[T <: Data](val gen: T, - val entries: Int, - val pipe: Boolean = false, - val flow: Boolean = false, - val useSyncReadMem: Boolean = false, - val hasFlush: Boolean = false) - (implicit compileOptions: chisel3.CompileOptions) +class Queue[T <: Data]( + val gen: T, + val entries: Int, + val pipe: Boolean = false, + val flow: Boolean = false, + val useSyncReadMem: Boolean = false, + val hasFlush: Boolean = false +)( + implicit compileOptions: chisel3.CompileOptions) extends Module() { require(entries > -1, "Queue must have non-negative number of entries") require(entries != 0, "Use companion object Queue.apply for zero entries") @@ -253,21 +269,21 @@ class Queue[T <: Data](val gen: T, // when flush is high, empty the queue // Semantically, any enqueues happen before the flush. - when (do_enq) { + when(do_enq) { ram(enq_ptr.value) := io.enq.bits enq_ptr.inc() } - when (do_deq) { + when(do_deq) { deq_ptr.inc() } - when (do_enq =/= do_deq) { + when(do_enq =/= do_deq) { maybe_full := do_enq } when(flush) { enq_ptr.reset() deq_ptr.reset() maybe_full := false.B - } + } io.deq.valid := !empty io.enq.ready := !full @@ -276,22 +292,21 @@ class Queue[T <: Data](val gen: T, val deq_ptr_next = Mux(deq_ptr.value === (entries.U - 1.U), 0.U, deq_ptr.value + 1.U) val r_addr = WireDefault(Mux(do_deq, deq_ptr_next, deq_ptr.value)) io.deq.bits := ram.read(r_addr) - } - else { + } else { io.deq.bits := ram(deq_ptr.value) } if (flow) { - when (io.enq.valid) { io.deq.valid := true.B } - when (empty) { + when(io.enq.valid) { io.deq.valid := true.B } + when(empty) { io.deq.bits := io.enq.bits do_deq := false.B - when (io.deq.ready) { do_enq := false.B } + when(io.deq.ready) { do_enq := false.B } } } if (pipe) { - when (io.deq.ready) { io.enq.ready := true.B } + when(io.deq.ready) { io.enq.ready := true.B } } val ptr_diff = enq_ptr.value - deq_ptr.value @@ -299,17 +314,17 @@ class Queue[T <: Data](val gen: T, if (isPow2(entries)) { io.count := Mux(maybe_full && ptr_match, entries.U, 0.U) | ptr_diff } else { - io.count := Mux(ptr_match, - Mux(maybe_full, - entries.asUInt, 0.U), - Mux(deq_ptr.value > enq_ptr.value, - entries.asUInt + ptr_diff, ptr_diff)) + io.count := Mux( + ptr_match, + Mux(maybe_full, entries.asUInt, 0.U), + Mux(deq_ptr.value > enq_ptr.value, entries.asUInt + ptr_diff, ptr_diff) + ) } } /** Factory for a generic hardware queue. */ -object Queue -{ +object Queue { + /** Create a [[Queue]] and supply a [[DecoupledIO]] containing the product. * * @param enq input (enqueue) interface to the queue, also determines type of queue elements. @@ -329,12 +344,13 @@ object Queue */ @chiselName def apply[T <: Data]( - enq: ReadyValidIO[T], - entries: Int = 2, - pipe: Boolean = false, - flow: Boolean = false, - useSyncReadMem: Boolean = false, - flush: Option[Bool] = None): DecoupledIO[T] = { + enq: ReadyValidIO[T], + entries: Int = 2, + pipe: Boolean = false, + flow: Boolean = false, + useSyncReadMem: Boolean = false, + flush: Option[Bool] = None + ): DecoupledIO[T] = { if (entries == 0) { val deq = Wire(new DecoupledIO(chiselTypeOf(enq.bits))) deq.valid := enq.valid @@ -373,12 +389,13 @@ object Queue */ @chiselName def irrevocable[T <: Data]( - enq: ReadyValidIO[T], - entries: Int = 2, - pipe: Boolean = false, - flow: Boolean = false, - useSyncReadMem: Boolean = false, - flush: Option[Bool] = None): IrrevocableIO[T] = { + enq: ReadyValidIO[T], + entries: Int = 2, + pipe: Boolean = false, + flow: Boolean = false, + useSyncReadMem: Boolean = false, + flush: Option[Bool] = None + ): IrrevocableIO[T] = { val deq = apply(enq, entries, pipe, flow, useSyncReadMem, flush) require(entries > 0, "Zero-entry queues don't guarantee Irrevocability") val irr = Wire(new IrrevocableIO(chiselTypeOf(deq.bits))) diff --git a/src/main/scala/chisel3/util/Enum.scala b/src/main/scala/chisel3/util/Enum.scala index 4501a2de..059506d9 100644 --- a/src/main/scala/chisel3/util/Enum.scala +++ b/src/main/scala/chisel3/util/Enum.scala @@ -26,9 +26,10 @@ import chisel3._ * }}} */ trait Enum { + /** Returns a sequence of Bits subtypes with values from 0 until n. Helper method. */ protected def createValues(n: Int): Seq[UInt] = - (0 until n).map(_.U((1 max log2Ceil(n)).W)) + (0 until n).map(_.U((1.max(log2Ceil(n))).W)) /** Returns n unique UInt values * diff --git a/src/main/scala/chisel3/util/ExtModuleUtils.scala b/src/main/scala/chisel3/util/ExtModuleUtils.scala index 62f384bc..5c9c02ba 100644 --- a/src/main/scala/chisel3/util/ExtModuleUtils.scala +++ b/src/main/scala/chisel3/util/ExtModuleUtils.scala @@ -3,8 +3,13 @@ package chisel3.util import chisel3.experimental.{ChiselAnnotation, ExtModule, RunFirrtlTransform} -import firrtl.transforms.{BlackBoxPathAnno, BlackBoxResourceAnno, BlackBoxInlineAnno, BlackBoxSourceHelper, - BlackBoxNotFoundException} +import firrtl.transforms.{ + BlackBoxInlineAnno, + BlackBoxNotFoundException, + BlackBoxPathAnno, + BlackBoxResourceAnno, + BlackBoxSourceHelper +} import BlackBoxHelpers._ diff --git a/src/main/scala/chisel3/util/ImplicitConversions.scala b/src/main/scala/chisel3/util/ImplicitConversions.scala index 792280ac..99d567ad 100644 --- a/src/main/scala/chisel3/util/ImplicitConversions.scala +++ b/src/main/scala/chisel3/util/ImplicitConversions.scala @@ -12,6 +12,6 @@ import scala.language.implicitConversions object ImplicitConversions { // The explicit fromIntToLiteral resolves an ambiguous conversion between fromIntToLiteral and // UInt.asUInt. - implicit def intToUInt(x: Int): UInt = chisel3.fromIntToLiteral(x).asUInt + implicit def intToUInt(x: Int): UInt = chisel3.fromIntToLiteral(x).asUInt implicit def booleanToBool(x: Boolean): Bool = x.B } diff --git a/src/main/scala/chisel3/util/Lookup.scala b/src/main/scala/chisel3/util/Lookup.scala index e0ed694f..f538c4d1 100644 --- a/src/main/scala/chisel3/util/Lookup.scala +++ b/src/main/scala/chisel3/util/Lookup.scala @@ -29,8 +29,9 @@ import chisel3._ object ListLookup { def apply[T <: Data](addr: UInt, default: List[T], mapping: Array[(BitPat, List[T])]): List[T] = { val map = mapping.map(m => (m._1 === addr, m._2)) - default.zipWithIndex map { case (d, i) => - map.foldRight(d)((m, n) => Mux(m._1, m._2(i), n)) + default.zipWithIndex.map { + case (d, i) => + map.foldRight(d)((m, n) => Mux(m._1, m._2(i), n)) } } } diff --git a/src/main/scala/chisel3/util/Math.scala b/src/main/scala/chisel3/util/Math.scala index 2a833e80..6eab9241 100644 --- a/src/main/scala/chisel3/util/Math.scala +++ b/src/main/scala/chisel3/util/Math.scala @@ -47,7 +47,7 @@ object log2Up { object log2Ceil { def apply(in: BigInt): Int = { require(in > 0) - (in-1).bitLength + (in - 1).bitLength } def apply(in: Int): Int = apply(BigInt(in)) } @@ -82,7 +82,7 @@ object log2Down { */ object log2Floor { def apply(in: BigInt): Int = log2Ceil(in) - (if (isPow2(in)) 0 else 1) - def apply(in: Int): Int = apply(BigInt(in)) + def apply(in: Int): Int = apply(BigInt(in)) } /** Returns whether a Scala integer is a power of two. @@ -95,12 +95,12 @@ object log2Floor { * }}} */ object isPow2 { - def apply(in: BigInt): Boolean = in > 0 && ((in & (in-1)) == 0) - def apply(in: Int): Boolean = apply(BigInt(in)) + def apply(in: BigInt): Boolean = in > 0 && ((in & (in - 1)) == 0) + def apply(in: Int): Boolean = apply(BigInt(in)) } - object unsignedBitLength { + /** Return the number of bits required to encode a specific value, assuming no sign bit is required. * * Basically, `n.bitLength`. NOTE: This will return 0 for a value of 0. @@ -115,6 +115,7 @@ object unsignedBitLength { } object signedBitLength { + /** Return the number of bits required to encode a specific value, assuming a sign bit is required. * * Basically, 0 for 0, 1 for -1, and `n.bitLength` + 1 for everything else. @@ -124,9 +125,9 @@ object signedBitLength { */ def apply(in: BigInt): Int = { in.toInt match { - case 0 => 0 + case 0 => 0 case -1 => 1 - case _ => in.bitLength + 1 + case _ => in.bitLength + 1 } } diff --git a/src/main/scala/chisel3/util/MixedVec.scala b/src/main/scala/chisel3/util/MixedVec.scala index 14d6be38..5f8c9da8 100644 --- a/src/main/scala/chisel3/util/MixedVec.scala +++ b/src/main/scala/chisel3/util/MixedVec.scala @@ -19,6 +19,7 @@ import scala.collection.immutable.ListMap * }}} */ object MixedVecInit { + /** * Create a MixedVec wire from a Seq of values. */ @@ -45,6 +46,7 @@ object MixedVecInit { * @return MixedVec with the given types. */ object MixedVec { + /** * Create a MixedVec type from a Seq of Chisel types. */ @@ -111,7 +113,7 @@ final class MixedVec[T <: Data](private val eltsIn: Seq[T]) extends Record with */ def :=(that: Seq[T]): Unit = { require(this.length == that.length) - for ((a, b) <- this zip that) + for ((a, b) <- this.zip(that)) a := b } diff --git a/src/main/scala/chisel3/util/Mux.scala b/src/main/scala/chisel3/util/Mux.scala index 946de461..e84b86a4 100644 --- a/src/main/scala/chisel3/util/Mux.scala +++ b/src/main/scala/chisel3/util/Mux.scala @@ -23,8 +23,8 @@ import chisel3._ */ object Mux1H { def apply[T <: Data](sel: Seq[Bool], in: Seq[T]): T = - apply(sel zip in) - def apply[T <: Data](in: Iterable[(Bool, T)]): T = SeqUtils.oneHotMux(in) + apply(sel.zip(in)) + def apply[T <: Data](in: Iterable[(Bool, T)]): T = SeqUtils.oneHotMux(in) def apply[T <: Data](sel: UInt, in: Seq[T]): T = apply((0 until in.size).map(sel(_)), in) def apply(sel: UInt, in: UInt): Bool = (sel & in).orR @@ -44,8 +44,8 @@ object Mux1H { * Returns the output of the Mux tree. */ object PriorityMux { - def apply[T <: Data](in: Seq[(Bool, T)]): T = SeqUtils.priorityMux(in) - def apply[T <: Data](sel: Seq[Bool], in: Seq[T]): T = apply(sel zip in) + def apply[T <: Data](in: Seq[(Bool, T)]): T = SeqUtils.priorityMux(in) + def apply[T <: Data](sel: Seq[Bool], in: Seq[T]): T = apply(sel.zip(in)) def apply[T <: Data](sel: Bits, in: Seq[T]): T = apply((0 until in.size).map(sel(_)), in) } @@ -57,12 +57,13 @@ object PriorityMux { * }}} */ object MuxLookup { + /** @param key a key to search for * @param default a default value if nothing is found * @param mapping a sequence to search of keys and values * @return the value found or the default if not */ - def apply[S <: UInt, T <: Data] (key: S, default: T, mapping: Seq[(S, T)]): T = { + def apply[S <: UInt, T <: Data](key: S, default: T, mapping: Seq[(S, T)]): T = { /* If the mapping is defined for all possible values of the key, then don't use the default value */ val (defaultx, mappingx) = key.widthOption match { case Some(width) => @@ -77,7 +78,7 @@ object MuxLookup { case None => (default, mapping) } - mappingx.foldLeft(defaultx){ case (d, (k, v)) => Mux(k === key, v, d) } + mappingx.foldLeft(defaultx) { case (d, (k, v)) => Mux(k === key, v, d) } } } @@ -89,12 +90,14 @@ object MuxLookup { * }}} */ object MuxCase { + /** @param default the default value if none are enabled * @param mapping a set of data values with associated enables - * @return the first value in mapping that is enabled */ - def apply[T <: Data] (default: T, mapping: Seq[(Bool, T)]): T = { + * @return the first value in mapping that is enabled + */ + def apply[T <: Data](default: T, mapping: Seq[(Bool, T)]): T = { var res = default - for ((t, v) <- mapping.reverse){ + for ((t, v) <- mapping.reverse) { res = Mux(t, v, res) } res diff --git a/src/main/scala/chisel3/util/OneHot.scala b/src/main/scala/chisel3/util/OneHot.scala index 03f470c7..23b350e5 100644 --- a/src/main/scala/chisel3/util/OneHot.scala +++ b/src/main/scala/chisel3/util/OneHot.scala @@ -20,15 +20,15 @@ import chisel3._ object OHToUInt { def apply(in: Seq[Bool]): UInt = apply(Cat(in.reverse), in.size) def apply(in: Vec[Bool]): UInt = apply(in.asUInt, in.size) - def apply(in: Bits): UInt = apply(in, in.getWidth) + def apply(in: Bits): UInt = apply(in, in.getWidth) def apply(in: Bits, width: Int): UInt = { if (width <= 2) { Log2(in, width) } else { - val mid = 1 << (log2Ceil(width)-1) - val hi = in(width-1, mid) - val lo = in(mid-1, 0) + val mid = 1 << (log2Ceil(width) - 1) + val hi = in(width - 1, mid) + val lo = in(mid - 1, 0) Cat(hi.orR, apply(hi | lo, mid)) } } @@ -44,7 +44,7 @@ object OHToUInt { */ object PriorityEncoder { def apply(in: Seq[Bool]): UInt = PriorityMux(in, (0 until in.size).map(_.asUInt)) - def apply(in: Bits): UInt = apply(in.asBools) + def apply(in: Bits): UInt = apply(in.asBools) } /** Returns the one hot encoding of the input UInt. @@ -52,7 +52,6 @@ object PriorityEncoder { * @example {{{ * UIntToOH(2.U) // results in "b0100".U * }}} - * */ object UIntToOH { def apply(in: UInt): UInt = 1.U << in diff --git a/src/main/scala/chisel3/util/Reg.scala b/src/main/scala/chisel3/util/Reg.scala index e2b5d172..ddb74dd6 100644 --- a/src/main/scala/chisel3/util/Reg.scala +++ b/src/main/scala/chisel3/util/Reg.scala @@ -5,6 +5,7 @@ package chisel3.util import chisel3._ object RegEnable { + /** Returns a register with the specified next, update enable gate, and no reset initialization. * * @example {{{ @@ -13,7 +14,7 @@ object RegEnable { */ def apply[T <: Data](next: T, enable: Bool): T = { val r = Reg(chiselTypeOf(next)) - when (enable) { r := next } + when(enable) { r := next } r } @@ -25,13 +26,13 @@ object RegEnable { */ def apply[T <: Data](next: T, init: T, enable: Bool): T = { val r = RegInit(init) - when (enable) { r := next } + when(enable) { r := next } r } } -object ShiftRegister -{ +object ShiftRegister { + /** Returns the n-cycle delayed version of the input signal. * * @param in input to delay @@ -55,18 +56,17 @@ object ShiftRegister * val regDelayTwoReset = ShiftRegister(nextVal, 2, 0.U, ena) * }}} */ - def apply[T <: Data](in: T, n: Int, resetData: T, en: Bool): T = ShiftRegisters(in, n, resetData, en).lastOption.getOrElse(in) + def apply[T <: Data](in: T, n: Int, resetData: T, en: Bool): T = + ShiftRegisters(in, n, resetData, en).lastOption.getOrElse(in) } +object ShiftRegisters { -object ShiftRegisters -{ /** Returns a sequence of delayed input signal registers from 1 to n. * * @param in input to delay * @param n number of cycles to delay * @param en enable the shift - * */ def apply[T <: Data](in: T, n: Int, en: Bool = true.B): Seq[T] = Seq.iterate(in, n + 1)(util.RegEnable(_, en)).drop(1) @@ -77,7 +77,6 @@ object ShiftRegisters * @param n number of cycles to delay * @param resetData reset value for each register in the shift * @param en enable the shift - * */ def apply[T <: Data](in: T, n: Int, resetData: T, en: Bool): Seq[T] = Seq.iterate(in, n + 1)(util.RegEnable(_, resetData, en)).drop(1) diff --git a/src/main/scala/chisel3/util/TransitName.scala b/src/main/scala/chisel3/util/TransitName.scala index 97c13696..cc8f2456 100644 --- a/src/main/scala/chisel3/util/TransitName.scala +++ b/src/main/scala/chisel3/util/TransitName.scala @@ -42,24 +42,23 @@ object TransitName { * @param to the thing that will receive the "good" name * @return the `from` parameter */ - def apply[T<:HasId](from: T, to: HasId): T = { + def apply[T <: HasId](from: T, to: HasId): T = { // To transit a name, we need to hook on both the suggestName and autoSeed mechanisms - from.addSuggestPostnameHook((given_name: String) => {to.suggestName(given_name)}) - from.addAutoPostnameHook((given_name: String) => {to.autoSeed(given_name)}) + from.addSuggestPostnameHook((given_name: String) => { to.suggestName(given_name) }) + from.addAutoPostnameHook((given_name: String) => { to.autoSeed(given_name) }) from } - /** Transit a name from one type to another ''and add a suffix'' * @param suffix the suffix to append * @param from the thing with a "good" name * @param to the thing that will receive the "good" name * @return the `from` parameter */ - def withSuffix[T<:HasId](suffix: String)(from: T, to: HasId): T = { + def withSuffix[T <: HasId](suffix: String)(from: T, to: HasId): T = { // To transit a name, we need to hook on both the suggestName and autoSeed mechanisms - from.addSuggestPostnameHook((given_name: String) => {to.suggestName(given_name + suffix)}) - from.addAutoPostnameHook((given_name: String) => {to.autoSeed(given_name + suffix)}) + from.addSuggestPostnameHook((given_name: String) => { to.suggestName(given_name + suffix) }) + from.addAutoPostnameHook((given_name: String) => { to.autoSeed(given_name + suffix) }) from } diff --git a/src/main/scala/chisel3/util/Valid.scala b/src/main/scala/chisel3/util/Valid.scala index 5d80502a..eeb2ab68 100644 --- a/src/main/scala/chisel3/util/Valid.scala +++ b/src/main/scala/chisel3/util/Valid.scala @@ -20,7 +20,8 @@ import chisel3._ * @groupdesc Signals The actual hardware fields of the Bundle */ class Valid[+T <: Data](gen: T) extends Bundle { - /** A bit that will be asserted when `bits` is valid + + /** A bit that will be asserted when `bits` is valid * @group Signals */ val valid = Output(Bool()) @@ -28,14 +29,17 @@ class Valid[+T <: Data](gen: T) extends Bundle { /** The data to be transferred, qualified by `valid` * @group Signals */ - val bits = Output(gen) + val bits = Output(gen) /** True when `valid` is asserted * @return a Chisel [[Bool]] true if `valid` is asserted */ def fire: Bool = valid - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) def fire(dummy: Int = 0): Bool = valid } @@ -122,7 +126,7 @@ object Pipe { } else { val v = RegNext(enqValid, false.B) val b = RegEnable(enqBits, enqValid) - val out = apply(v, b, latency-1)(compileOptions) + val out = apply(v, b, latency - 1)(compileOptions) TransitName.withSuffix("Pipe_valid")(out, v) TransitName.withSuffix("Pipe_bits")(out, b) @@ -182,12 +186,12 @@ class Pipe[T <: Data](val gen: T, val latency: Int = 1)(implicit compileOptions: */ class PipeIO extends Bundle { - /** [[Valid]] input + /** [[Valid]] input * @group Signals */ val enq = Input(Valid(gen)) - /** [[Valid]] output. Data will appear here `latency` cycles after being valid at `enq`. + /** [[Valid]] output. Data will appear here `latency` cycles after being valid at `enq`. * @group Signals */ val deq = Output(Valid(gen)) diff --git a/src/main/scala/chisel3/util/experimental/BoringUtils.scala b/src/main/scala/chisel3/util/experimental/BoringUtils.scala index f2a3e757..254f83a4 100644 --- a/src/main/scala/chisel3/util/experimental/BoringUtils.scala +++ b/src/main/scala/chisel3/util/experimental/BoringUtils.scala @@ -3,11 +3,11 @@ package chisel3.util.experimental import chisel3._ -import chisel3.experimental.{ChiselAnnotation, RunFirrtlTransform, annotate} +import chisel3.experimental.{annotate, ChiselAnnotation, RunFirrtlTransform} import chisel3.internal.{InstanceId, NamedComponent, Namespace} import firrtl.transforms.{DontTouchAnnotation, NoDedupAnnotation} -import firrtl.passes.wiring.{WiringTransform, SourceAnnotation, SinkAnnotation} -import firrtl.annotations.{ModuleName, ComponentName} +import firrtl.passes.wiring.{SinkAnnotation, SourceAnnotation, WiringTransform} +import firrtl.annotations.{ComponentName, ModuleName} import scala.concurrent.SyncVar @@ -122,20 +122,25 @@ object BoringUtils { * @note if a uniqueName is not specified, the returned name may differ from the user-provided name */ def addSource( - component: NamedComponent, - name: String, + component: NamedComponent, + name: String, disableDedup: Boolean = false, - uniqueName: Boolean = false): String = { + uniqueName: Boolean = false + ): String = { - val id = if (uniqueName) { newName(name) } else { name } + val id = if (uniqueName) { newName(name) } + else { name } val maybeDedup = if (disableDedup) { Seq(new ChiselAnnotation { def toFirrtl = NoDedupAnnotation(component.toNamed.module) }) } - else { Seq[ChiselAnnotation]() } + else { Seq[ChiselAnnotation]() } val annotations = - Seq(new ChiselAnnotation with RunFirrtlTransform { - def toFirrtl = SourceAnnotation(component.toNamed, id) - def transformClass = classOf[WiringTransform] }, - new ChiselAnnotation { def toFirrtl = DontTouchAnnotation(component.toNamed) } ) ++ maybeDedup + Seq( + new ChiselAnnotation with RunFirrtlTransform { + def toFirrtl = SourceAnnotation(component.toNamed, id) + def transformClass = classOf[WiringTransform] + }, + new ChiselAnnotation { def toFirrtl = DontTouchAnnotation(component.toNamed) } + ) ++ maybeDedup annotations.foreach(annotate(_)) id @@ -150,25 +155,28 @@ object BoringUtils { * @throws BoringUtilsException if name is expected to exist and it doesn't */ def addSink( - component: InstanceId, - name: String, + component: InstanceId, + name: String, disableDedup: Boolean = false, - forceExists: Boolean = false): Unit = { + forceExists: Boolean = false + ): Unit = { if (forceExists && !checkName(name)) { - throw new BoringUtilsException(s"Sink ID '$name' not found in BoringUtils ID namespace") } + throw new BoringUtilsException(s"Sink ID '$name' not found in BoringUtils ID namespace") + } def moduleName = component.toNamed match { - case c: ModuleName => c + case c: ModuleName => c case c: ComponentName => c.module case _ => throw new ChiselException("Can only add a Module or Component sink", null) } val maybeDedup = if (disableDedup) { Seq(new ChiselAnnotation { def toFirrtl = NoDedupAnnotation(moduleName) }) } - else { Seq[ChiselAnnotation]() } + else { Seq[ChiselAnnotation]() } val annotations = Seq(new ChiselAnnotation with RunFirrtlTransform { - def toFirrtl = SinkAnnotation(component.toNamed, name) - def transformClass = classOf[WiringTransform] }) ++ maybeDedup + def toFirrtl = SinkAnnotation(component.toNamed, name) + def transformClass = classOf[WiringTransform] + }) ++ maybeDedup annotations.foreach(annotate(_)) } @@ -181,11 +189,12 @@ object BoringUtils { * component */ def bore(source: Data, sinks: Seq[Data]): String = { - val boringName = try { - source.instanceName - } catch { - case _: Exception => "bore" - } + val boringName = + try { + source.instanceName + } catch { + case _: Exception => "bore" + } val genName = addSource(source, boringName, true, true) sinks.foreach(addSink(_, genName, true, true)) genName diff --git a/src/main/scala/chisel3/util/experimental/ForceNames.scala b/src/main/scala/chisel3/util/experimental/ForceNames.scala index bac69ed4..53ee2bd2 100644 --- a/src/main/scala/chisel3/util/experimental/ForceNames.scala +++ b/src/main/scala/chisel3/util/experimental/ForceNames.scala @@ -2,7 +2,7 @@ package chisel3.util.experimental -import chisel3.experimental.{ChiselAnnotation, RunFirrtlTransform, annotate} +import chisel3.experimental.{annotate, ChiselAnnotation, RunFirrtlTransform} import firrtl.Mappers._ import firrtl._ import firrtl.annotations._ @@ -49,7 +49,7 @@ object forceName { * @param instance Instance to name */ def apply(instance: chisel3.experimental.BaseModule, name: String): Unit = { - annotate(new ChiselAnnotation with RunFirrtlTransform { + annotate(new ChiselAnnotation with RunFirrtlTransform { def toFirrtl = { val t = instance.toAbsoluteTarget ForceNameAnnotation(t, name) @@ -64,7 +64,7 @@ object forceName { * @param instance Signal to name */ def apply(instance: chisel3.experimental.BaseModule): Unit = { - annotate(new ChiselAnnotation with RunFirrtlTransform { + annotate(new ChiselAnnotation with RunFirrtlTransform { def toFirrtl = { val t = instance.toAbsoluteTarget ForceNameAnnotation(t, instance.instanceName) @@ -80,8 +80,7 @@ object forceName { * @param target signal/instance to force the name * @param name name to force it to be */ -case class ForceNameAnnotation(target: IsMember, name: String) - extends SingleTargetAnnotation[IsMember] { +case class ForceNameAnnotation(target: IsMember, name: String) extends SingleTargetAnnotation[IsMember] { def duplicate(n: IsMember): ForceNameAnnotation = this.copy(target = n, name) // Errors if renaming to multiple targets @@ -105,6 +104,7 @@ case class ForceNameAnnotation(target: IsMember, name: String) * Could (should?) be moved to FIRRTL. */ private object ForceNamesTransform { + /** Returns the [[IsModule]] which is referred to, or if a [[ReferenceTarget]], the enclosing [[IsModule]] * * @param a signal/instance/module @@ -123,10 +123,12 @@ private object ForceNamesTransform { */ def allInstancePaths(graph: InstanceKeyGraph): IsModule => List[List[(Instance, OfModule)]] = { val lookup: String => List[List[(Instance, OfModule)]] = - str => graph.findInstancesInHierarchy(str) - .view - .map(_.map(_.toTokens).toList) - .toList + str => + graph + .findInstancesInHierarchy(str) + .view + .map(_.map(_.toTokens).toList) + .toList allInstancePaths(lookup) _ } @@ -136,8 +138,10 @@ private object ForceNamesTransform { * @param target target to get all instance paths to * @return */ - def allInstancePaths(lookup: String => List[List[(Instance, OfModule)]]) - (target: IsModule): List[List[(Instance, OfModule)]] = { + def allInstancePaths( + lookup: String => List[List[(Instance, OfModule)]] + )(target: IsModule + ): List[List[(Instance, OfModule)]] = { target match { case ModuleTarget(circuit, module) => if (circuit == module) List(List((Instance(module), OfModule(module)))) @@ -149,16 +153,13 @@ private object ForceNamesTransform { } } - /** Builds the map of module name to map of old signal/instance name to new signal/instance name * * @param state CircuitState to operate on * @param igraph built instance key graph from state's circuit * @return */ - def buildForceNameMap(state: CircuitState, - igraph: => InstanceKeyGraph - ): Option[Map[String, Map[String, String]]] = { + def buildForceNameMap(state: CircuitState, igraph: => InstanceKeyGraph): Option[Map[String, Map[String, String]]] = { val forceNames = state.annotations.collect { case f: ForceNameAnnotation => f } val badNames = mutable.HashSet[ForceNameAnnotation]() val allNameMaps = forceNames.groupBy { case f => referringIsModule(f.target) }.mapValues { value => @@ -207,9 +208,9 @@ private object ForceNamesTransform { * - Use to avoid prefixing behavior on specific instances whose enclosing modules are inlined */ class ForceNamesTransform extends Transform with DependencyAPIMigration { - override def optionalPrerequisites: Seq[TransformDependency] = Seq(Dependency[InlineInstances]) + override def optionalPrerequisites: Seq[TransformDependency] = Seq(Dependency[InlineInstances]) override def optionalPrerequisiteOf: Seq[TransformDependency] = Forms.LowEmitters - override def prerequisites: Seq[TransformDependency] = Seq(Dependency(LowerTypes)) + override def prerequisites: Seq[TransformDependency] = Seq(Dependency(LowerTypes)) override def invalidates(a: Transform): Boolean = firrtl.passes.InferTypes == a import ForceNamesTransform._ @@ -226,22 +227,23 @@ class ForceNamesTransform extends Transform with DependencyAPIMigration { */ private def forceNamesInModule( modToNames: Map[String, Map[String, String]], - renameMap: RenameMap, - ct: CircuitTarget, - igraph: InstanceKeyGraph - )(mod: DefModule): DefModule = { + renameMap: RenameMap, + ct: CircuitTarget, + igraph: InstanceKeyGraph + )(mod: DefModule + ): DefModule = { val mt = ct.module(mod.name) val instToOfModule = mutable.HashMap[String, String]() val names = modToNames.getOrElse(mod.name, Map.empty[String, String]) // Need to find WRef referring to mems for prefixing def onExpr(expr: Expression): Expression = expr match { - case ref @ Reference(n, _,_,_) if names.contains(n) => + case ref @ Reference(n, _, _, _) if names.contains(n) => ref.copy(name = names(n)) - case sub @ SubField(WRef(i, _, _, _), p,_,_) if instToOfModule.contains(i) => + case sub @ SubField(WRef(i, _, _, _), p, _, _) if instToOfModule.contains(i) => val newsub = modToNames.get(instToOfModule(i)) match { case Some(map) if map.contains(p) => sub.copy(name = map(p)) - case _ => sub + case _ => sub } newsub.map(onExpr) case other => other.map(onExpr) @@ -269,17 +271,19 @@ class ForceNamesTransform extends Transform with DependencyAPIMigration { } else port } - val childInstanceHasRename = igraph.getChildInstanceMap(OfModule(mod.name)).exists { - o => modToNames.contains(o._2.value) + val childInstanceHasRename = igraph.getChildInstanceMap(OfModule(mod.name)).exists { o => + modToNames.contains(o._2.value) } - if(childInstanceHasRename || modToNames.contains(mod.name)) { + if (childInstanceHasRename || modToNames.contains(mod.name)) { val ns = Namespace(mod) val conflicts = names.values.collect { case k if ns.contains(k) => k } - if(conflicts.isEmpty) { + if (conflicts.isEmpty) { mod.map(onPort).map(onStmt) } else { - throw new FirrtlUserException(s"Cannot force the following names in module ${mod.name} because they conflict: ${conflicts.mkString(",")}") + throw new FirrtlUserException( + s"Cannot force the following names in module ${mod.name} because they conflict: ${conflicts.mkString(",")}" + ) } } else mod } diff --git a/src/main/scala/chisel3/util/experimental/Inline.scala b/src/main/scala/chisel3/util/experimental/Inline.scala index 1d5fcb89..fd5c6aa5 100644 --- a/src/main/scala/chisel3/util/experimental/Inline.scala +++ b/src/main/scala/chisel3/util/experimental/Inline.scala @@ -6,7 +6,7 @@ import chisel3._ import chisel3.experimental.{BaseModule, ChiselAnnotation, RunFirrtlTransform} import firrtl.Transform import firrtl.passes.{InlineAnnotation, InlineInstances} -import firrtl.transforms.{NoDedupAnnotation, FlattenAnnotation, Flatten} +import firrtl.transforms.{Flatten, FlattenAnnotation, NoDedupAnnotation} import firrtl.annotations.Annotation /** Inlines an instance of a module @@ -40,11 +40,15 @@ import firrtl.annotations.Annotation * }}} */ trait InlineInstance { self: BaseModule => - Seq(new ChiselAnnotation with RunFirrtlTransform { - def toFirrtl: Annotation = InlineAnnotation(self.toNamed) - def transformClass: Class[_ <: Transform] = classOf[InlineInstances] }, - new ChiselAnnotation { - def toFirrtl: Annotation = NoDedupAnnotation(self.toNamed) }) + Seq( + new ChiselAnnotation with RunFirrtlTransform { + def toFirrtl: Annotation = InlineAnnotation(self.toNamed) + def transformClass: Class[_ <: Transform] = classOf[InlineInstances] + }, + new ChiselAnnotation { + def toFirrtl: Annotation = NoDedupAnnotation(self.toNamed) + } + ) .map(chisel3.experimental.annotate(_)) } @@ -75,10 +79,14 @@ trait InlineInstance { self: BaseModule => * }}} */ trait FlattenInstance { self: BaseModule => - Seq(new ChiselAnnotation with RunFirrtlTransform { - def toFirrtl: Annotation = FlattenAnnotation(self.toNamed) - def transformClass: Class[_ <: Transform] = classOf[Flatten] }, - new ChiselAnnotation { - def toFirrtl: Annotation = NoDedupAnnotation(self.toNamed) }) - .map(chisel3.experimental.annotate(_)) + Seq( + new ChiselAnnotation with RunFirrtlTransform { + def toFirrtl: Annotation = FlattenAnnotation(self.toNamed) + def transformClass: Class[_ <: Transform] = classOf[Flatten] + }, + new ChiselAnnotation { + def toFirrtl: Annotation = NoDedupAnnotation(self.toNamed) + } + ) + .map(chisel3.experimental.annotate(_)) } diff --git a/src/main/scala/chisel3/util/experimental/LoadMemoryTransform.scala b/src/main/scala/chisel3/util/experimental/LoadMemoryTransform.scala index 93981485..bd46abe9 100644 --- a/src/main/scala/chisel3/util/experimental/LoadMemoryTransform.scala +++ b/src/main/scala/chisel3/util/experimental/LoadMemoryTransform.scala @@ -3,7 +3,7 @@ package chisel3.util.experimental import chisel3._ -import chisel3.experimental.{RunFirrtlTransform, annotate, ChiselAnnotation} +import chisel3.experimental.{annotate, ChiselAnnotation, RunFirrtlTransform} import firrtl.annotations._ import firrtl.ir.{Module => _, _} import firrtl.transforms.BlackBoxInlineAnno @@ -21,11 +21,11 @@ import scala.collection.mutable case class ChiselLoadMemoryAnnotation[T <: Data]( target: MemBase[T], fileName: String, - hexOrBinary: MemoryLoadFileType.FileType = MemoryLoadFileType.Hex -) - extends ChiselAnnotation with RunFirrtlTransform { + hexOrBinary: MemoryLoadFileType.FileType = MemoryLoadFileType.Hex) + extends ChiselAnnotation + with RunFirrtlTransform { - if(fileName.isEmpty) { + if (fileName.isEmpty) { throw new Exception( s"""LoadMemory from file annotations file empty file name""" ) @@ -39,7 +39,6 @@ case class ChiselLoadMemoryAnnotation[T <: Data]( } } - /** [[loadMemoryFromFile]] is an annotation generator that helps with loading a memory from a text file as a bind module. This relies on * Verilator and Verilog's `\$readmemh` or `\$readmemb`. The [[https://github.com/freechipsproject/treadle Treadle * backend]] can also recognize this annotation and load memory at run-time. @@ -101,22 +100,20 @@ case class ChiselLoadMemoryAnnotation[T <: Data]( */ object loadMemoryFromFile { - /** Annotate a memory such that it can be initialized using a file * @param memory the memory * @param filename the file used for initialization * @param hexOrBinary whether the file uses a hex or binary number representation */ def apply[T <: Data]( - memory: MemBase[T], - fileName: String, + memory: MemBase[T], + fileName: String, hexOrBinary: MemoryLoadFileType.FileType = MemoryLoadFileType.Hex ): Unit = { annotate(ChiselLoadMemoryAnnotation(memory, fileName, hexOrBinary)) } } - /** [[loadMemoryFromFileInline]] is an annotation generator that helps with loading a memory from a text file inlined in * the Verilog module. This relies on Verilator and Verilog's `\$readmemh` or `\$readmemb`. * The [[https://github.com/freechipsproject/treadle Treadlebackend]] can also recognize this annotation and load memory at run-time. @@ -179,15 +176,14 @@ object loadMemoryFromFile { */ object loadMemoryFromFileInline { - /** Annotate a memory such that it can be initialized inline using a file * @param memory the memory * @param fileName the file used for initialization * @param hexOrBinary whether the file uses a hex or binary number representation */ def apply[T <: Data]( - memory: MemBase[T], - fileName: String, + memory: MemBase[T], + fileName: String, hexOrBinary: MemoryLoadFileType.FileType = MemoryLoadFileType.Hex ): Unit = { annotate(new ChiselAnnotation { @@ -204,14 +200,14 @@ object loadMemoryFromFileInline { * not need this transform to do that. */ class LoadMemoryTransform extends Transform { - def inputForm: CircuitForm = LowForm + def inputForm: CircuitForm = LowForm def outputForm: CircuitForm = LowForm private var memoryCounter: Int = -1 private val bindModules: mutable.ArrayBuffer[BlackBoxInlineAnno] = new mutable.ArrayBuffer() - private val verilogEmitter: VerilogEmitter = new VerilogEmitter + private val verilogEmitter: VerilogEmitter = new VerilogEmitter /** run the pass * @param circuit the circuit @@ -219,19 +215,19 @@ class LoadMemoryTransform extends Transform { * @return */ def run(circuit: Circuit, annotations: AnnotationSeq): Circuit = { - val groups = annotations - .collect{ case m: LoadMemoryAnnotation => m } + val groups = annotations.collect { case m: LoadMemoryAnnotation => m } .groupBy(_.target.serialize) - val memoryAnnotations = groups.map { case (key, annos) => + val memoryAnnotations = groups.map { + case (key, annos) => if (annos.size > 1) { throw new Exception( s"Multiple (${annos.size} found for memory $key one LoadMemoryAnnotation is allowed per memory" ) } key -> annos.head - } + } - val modulesByName = circuit.modules.collect { case module: firrtl.ir.Module => module.name -> module }.toMap + val modulesByName = circuit.modules.collect { case module: firrtl.ir.Module => module.name -> module }.toMap /* Walk the module and for memories that are annotated with [[LoadMemoryAnnotation]]s generate the bindable modules for * Verilog emission. @@ -251,32 +247,34 @@ class LoadMemoryTransform extends Transform { val writer = new java.io.StringWriter val readmem = hexOrBinary match { case MemoryLoadFileType.Binary => "$readmemb" - case MemoryLoadFileType.Hex => "$readmemh" + case MemoryLoadFileType.Hex => "$readmemh" } modulesByName.get(moduleName.name).foreach { module => - val renderer = verilogEmitter.getRenderer(module, modulesByName)(writer) - val loadFileName = lma.getFileName - - memoryCounter += 1 - val bindsToName = s"BindsTo_${memoryCounter}_${moduleName.name}" - renderer.emitVerilogBind(bindsToName, - s""" - |initial begin - | $readmem("$loadFileName", ${myModule.name}.$componentName); - |end - """.stripMargin) - val inLineText = writer.toString + "\n" + - s"""bind ${myModule.name} $bindsToName ${bindsToName}_Inst(.*);""" - - val blackBoxInline = BlackBoxInlineAnno( - moduleName, - moduleName.serialize + "." + componentName + ".v", - inLineText - ) - - bindModules += blackBoxInline - } + val renderer = verilogEmitter.getRenderer(module, modulesByName)(writer) + val loadFileName = lma.getFileName + + memoryCounter += 1 + val bindsToName = s"BindsTo_${memoryCounter}_${moduleName.name}" + renderer.emitVerilogBind( + bindsToName, + s""" + |initial begin + | $readmem("$loadFileName", ${myModule.name}.$componentName); + |end + """.stripMargin + ) + val inLineText = writer.toString + "\n" + + s"""bind ${myModule.name} $bindsToName ${bindsToName}_Inst(.*);""" + + val blackBoxInline = BlackBoxInlineAnno( + moduleName, + moduleName.serialize + "." + componentName + ".v", + inLineText + ) + + bindModules += blackBoxInline + } case _ => } @@ -284,8 +282,8 @@ class LoadMemoryTransform extends Transform { def processStatements(statement: Statement): Statement = { statement match { - case m: DefMemory => processMemory(m.name) - case s => s map processStatements + case m: DefMemory => processMemory(m.name) + case s => s.map(processStatements) } statement } @@ -299,7 +297,7 @@ class LoadMemoryTransform extends Transform { myModule } - circuit map processModule + circuit.map(processModule) } def execute(state: CircuitState): CircuitState = { @@ -309,11 +307,10 @@ class LoadMemoryTransform extends Transform { case _ => false } - if(isVerilog) { + if (isVerilog) { run(state.circuit, state.annotations) state.copy(annotations = state.annotations ++ bindModules) - } - else { + } else { state } } diff --git a/src/main/scala/chisel3/util/experimental/decode/EspressoMinimizer.scala b/src/main/scala/chisel3/util/experimental/decode/EspressoMinimizer.scala index 4dcea99e..de2f207b 100644 --- a/src/main/scala/chisel3/util/experimental/decode/EspressoMinimizer.scala +++ b/src/main/scala/chisel3/util/experimental/decode/EspressoMinimizer.scala @@ -19,7 +19,7 @@ case object EspressoNotFoundException extends Exception */ object EspressoMinimizer extends Minimizer with LazyLogging { def minimize(table: TruthTable): TruthTable = - TruthTable.merge(TruthTable.split(table).map{case (table, indexes) => (espresso(table), indexes)}) + TruthTable.merge(TruthTable.split(table).map { case (table, indexes) => (espresso(table), indexes) }) private def espresso(table: TruthTable): TruthTable = { def writeTable(table: TruthTable): String = { @@ -34,10 +34,9 @@ object EspressoMinimizer extends Minimizer with LazyLogging { } val tableType: String = defaultType match { case '?' => "fr" - case _ => "fd" + case _ => "fd" } - val rawTable = table - .toString + val rawTable = table.toString .split("\n") .filter(_.contains("->")) .mkString("\n") @@ -69,11 +68,13 @@ object EspressoMinimizer extends Minimizer with LazyLogging { logger.trace(s"""espresso input table: |$input |""".stripMargin) - val output = try { - os.proc("espresso").call(stdin = input).out.chunks.mkString - } catch { - case e: java.io.IOException if e.getMessage.contains("error=2, No such file or directory") => throw EspressoNotFoundException - } + val output = + try { + os.proc("espresso").call(stdin = input).out.chunks.mkString + } catch { + case e: java.io.IOException if e.getMessage.contains("error=2, No such file or directory") => + throw EspressoNotFoundException + } logger.trace(s"""espresso output table: |$output |""".stripMargin) diff --git a/src/main/scala/chisel3/util/experimental/decode/Minimizer.scala b/src/main/scala/chisel3/util/experimental/decode/Minimizer.scala index 86847710..c4065ac9 100644 --- a/src/main/scala/chisel3/util/experimental/decode/Minimizer.scala +++ b/src/main/scala/chisel3/util/experimental/decode/Minimizer.scala @@ -3,6 +3,7 @@ package chisel3.util.experimental.decode abstract class Minimizer { + /** Minimize a multi-input multi-output logic function given by the truth table `table`, with function output values * on unspecified inputs treated as `default`, and return a minimized PLA-like representation of the function. * @@ -26,4 +27,4 @@ abstract class Minimizer { * }}} */ def minimize(table: TruthTable): TruthTable -}
\ No newline at end of file +} diff --git a/src/main/scala/chisel3/util/experimental/decode/QMCMinimizer.scala b/src/main/scala/chisel3/util/experimental/decode/QMCMinimizer.scala index 59120221..a3481869 100644 --- a/src/main/scala/chisel3/util/experimental/decode/QMCMinimizer.scala +++ b/src/main/scala/chisel3/util/experimental/decode/QMCMinimizer.scala @@ -125,12 +125,15 @@ object QMCMinimizer extends Minimizer { * b: nonessential prime implicants * c: implicants that are not cover by any of the essential prime implicants */ - private def getEssentialPrimeImplicants(primes: Seq[Implicant], minterms: Seq[Implicant]): (Seq[Implicant], Seq[Implicant], Seq[Implicant]) = { + private def getEssentialPrimeImplicants( + primes: Seq[Implicant], + minterms: Seq[Implicant] + ): (Seq[Implicant], Seq[Implicant], Seq[Implicant]) = { // primeCovers(i): implicants that `prime(i)` covers val primeCovers = primes.map(p => minterms.filter(p.covers)) // eliminate prime implicants that can be covered by other prime implicants - for (((icover, pi), i) <- (primeCovers zip primes).zipWithIndex) { - for (((jcover, pj), _) <- (primeCovers zip primes).zipWithIndex.drop(i + 1)) { + for (((icover, pi), i) <- (primeCovers.zip(primes)).zipWithIndex) { + for (((jcover, pj), _) <- (primeCovers.zip(primes)).zipWithIndex.drop(i + 1)) { // we prefer prime implicants with wider implicants coverage if (icover.size > jcover.size && jcover.forall(pi.covers)) { // calculate essential prime implicants with `pj` eliminated from prime implicants table @@ -165,6 +168,7 @@ object QMCMinimizer extends Minimizer { * @return Selected nonessential prime implicants */ private def getCover(implicants: Seq[Implicant], minterms: Seq[Implicant]): Seq[Implicant] = { + /** Calculate the implementation cost (using comparators) of a list of implicants, more don't cares is cheaper * * @param cover Implicant list @@ -193,7 +197,8 @@ object QMCMinimizer extends Minimizer { * @return `a` < `b` */ @tailrec - def listLess(a: Seq[Implicant], b: Seq[Implicant]): Boolean = b.nonEmpty && (a.isEmpty || a.head < b.head || a.head == b.head && listLess(a.tail, b.tail)) + def listLess(a: Seq[Implicant], b: Seq[Implicant]): Boolean = + b.nonEmpty && (a.isEmpty || a.head < b.head || a.head == b.head && listLess(a.tail, b.tail)) ca < cb || ca == cb && listLess(a.sortWith(_ < _), b.sortWith(_ < _)) } @@ -216,8 +221,14 @@ object QMCMinimizer extends Minimizer { // extract decode table to inputs and outputs val (inputs, outputs) = table.table.unzip - require(outputs.map(_.getWidth == table.default.getWidth).reduce(_ && _), "All output BitPats and default BitPat must have the same length") - require(if (inputs.toSeq.length > 1) inputs.tail.map(_.width == inputs.head.width).reduce(_ && _) else true, "All input BitPats must have the same length") + require( + outputs.map(_.getWidth == table.default.getWidth).reduce(_ && _), + "All output BitPats and default BitPat must have the same length" + ) + require( + if (inputs.toSeq.length > 1) inputs.tail.map(_.width == inputs.head.width).reduce(_ && _) else true, + "All input BitPats must have the same length" + ) // make sure no two inputs specified in the truth table intersect for (t <- inputs.tails; if t.nonEmpty) @@ -234,9 +245,11 @@ object QMCMinimizer extends Minimizer { val outputBp = BitPat("b" + "?" * (m - i - 1) + "1" + "?" * i) // Minterms, implicants that makes the output to be 1 - val mint: Seq[Implicant] = table.table.filter { case (_, t) => t.mask.testBit(i) && t.value.testBit(i) }.map(_._1).map(toImplicant) + val mint: Seq[Implicant] = + table.table.filter { case (_, t) => t.mask.testBit(i) && t.value.testBit(i) }.map(_._1).map(toImplicant) // Maxterms, implicants that makes the output to be 0 - val maxt: Seq[Implicant] = table.table.filter { case (_, t) => t.mask.testBit(i) && !t.value.testBit(i) }.map(_._1).map(toImplicant) + val maxt: Seq[Implicant] = + table.table.filter { case (_, t) => t.mask.testBit(i) && !t.value.testBit(i) }.map(_._1).map(toImplicant) // Don't cares, implicants that can produce either 0 or 1 as output val dc: Seq[Implicant] = table.table.filter { case (_, t) => !t.mask.testBit(i) }.map(_._1).map(toImplicant) @@ -251,16 +264,14 @@ object QMCMinimizer extends Minimizer { implicants.foreach(_.isPrime = true) val cols = (0 to n).reverse.map(b => implicants.filter(b == _.bp.mask.bitCount)) - val mergeTable = cols.map( - c => (0 to n).map( - b => collection.mutable.Set(c.filter(b == _.bp.value.bitCount):_*) - ) - ) + val mergeTable = cols.map(c => (0 to n).map(b => collection.mutable.Set(c.filter(b == _.bp.value.bitCount): _*))) // O(n ^ 3) for (i <- 0 to n) { for (j <- 0 until n - i) { - mergeTable(i)(j).foreach(a => mergeTable(i + 1)(j) ++= mergeTable(i)(j + 1).filter(_ similar a).map(_ merge a)) + mergeTable(i)(j).foreach(a => + mergeTable(i + 1)(j) ++= mergeTable(i)(j + 1).filter(_.similar(a)).map(_.merge(a)) + ) } if (defaultToDc) { for (j <- 0 until n - i) { @@ -268,14 +279,14 @@ object QMCMinimizer extends Minimizer { if (a.bp.mask.testBit(i) && !a.bp.value.testBit(i)) { // this bit is `0` val t = new BitPat(a.bp.value.setBit(i), a.bp.mask, a.width) - if (!maxt.exists(_.intersects(t))) mergeTable(i + 1)(j) += t merge a + if (!maxt.exists(_.intersects(t))) mergeTable(i + 1)(j) += t.merge(a) } } for (a <- mergeTable(i)(j + 1).filter(_.isPrime)) { if (a.bp.mask.testBit(i) && a.bp.value.testBit(i)) { // this bit is `1` val t = new BitPat(a.bp.value.clearBit(i), a.bp.mask, a.width) - if (!maxt.exists(_.intersects(t))) mergeTable(i + 1)(j) += a merge t + if (!maxt.exists(_.intersects(t))) mergeTable(i + 1)(j) += a.merge(t) } } } @@ -288,20 +299,29 @@ object QMCMinimizer extends Minimizer { val (essentialPrimeImplicants, nonessentialPrimeImplicants, uncoveredImplicants) = getEssentialPrimeImplicants(primeImplicants, implicants) - (essentialPrimeImplicants ++ getCover(nonessentialPrimeImplicants, uncoveredImplicants)).map(a => (a.bp, outputBp)) + (essentialPrimeImplicants ++ getCover(nonessentialPrimeImplicants, uncoveredImplicants)).map(a => + (a.bp, outputBp) + ) }) - minimized.tail.foldLeft(table.copy(table = Seq(minimized.head))) { case (tb, t) => - if (tb.table.exists(x => x._1 == t._1)) { - tb.copy(table = tb.table.map { case (k, v) => - if (k == t._1) { - def ones(bitPat: BitPat) = bitPat.rawString.zipWithIndex.collect{case ('1', x) => x} - (k, BitPat("b" + (0 until v.getWidth).map(i => if ((ones(v) ++ ones(t._2)).contains(i)) "1" else "?").mkString)) - } else (k, v) - }) - } else { - tb.copy(table = tb.table :+ t) - } + minimized.tail.foldLeft(table.copy(table = Seq(minimized.head))) { + case (tb, t) => + if (tb.table.exists(x => x._1 == t._1)) { + tb.copy(table = tb.table.map { + case (k, v) => + if (k == t._1) { + def ones(bitPat: BitPat) = bitPat.rawString.zipWithIndex.collect { case ('1', x) => x } + ( + k, + BitPat( + "b" + (0 until v.getWidth).map(i => if ((ones(v) ++ ones(t._2)).contains(i)) "1" else "?").mkString + ) + ) + } else (k, v) + }) + } else { + tb.copy(table = tb.table :+ t) + } } } -}
\ No newline at end of file +} diff --git a/src/main/scala/chisel3/util/experimental/decode/TruthTable.scala b/src/main/scala/chisel3/util/experimental/decode/TruthTable.scala index 322466f9..e742fd66 100644 --- a/src/main/scala/chisel3/util/experimental/decode/TruthTable.scala +++ b/src/main/scala/chisel3/util/experimental/decode/TruthTable.scala @@ -13,10 +13,11 @@ sealed class TruthTable private (val table: Seq[(BitPat, BitPat)], val default: def writeRow(map: (BitPat, BitPat)): String = s"${map._1.rawString}->${map._2.rawString}" - (table.map(writeRow) ++ Seq(s"${" "*(inputWidth + 2)}${default.rawString}")).mkString("\n") + (table.map(writeRow) ++ Seq(s"${" " * (inputWidth + 2)}${default.rawString}")).mkString("\n") } - def copy(table: Seq[(BitPat, BitPat)] = this.table, default: BitPat = this.default, sort: Boolean = this.sort) = TruthTable(table, default, sort) + def copy(table: Seq[(BitPat, BitPat)] = this.table, default: BitPat = this.default, sort: Boolean = this.sort) = + TruthTable(table, default, sort) override def equals(y: Any): Boolean = { y match { @@ -27,27 +28,36 @@ sealed class TruthTable private (val table: Seq[(BitPat, BitPat)], val default: } object TruthTable { + /** Convert a table and default output into a [[TruthTable]]. */ def apply(table: Iterable[(BitPat, BitPat)], default: BitPat, sort: Boolean = true): TruthTable = { require(table.map(_._1.getWidth).toSet.size == 1, "input width not equal.") require(table.map(_._2.getWidth).toSet.size == 1, "output width not equal.") val outputWidth = table.map(_._2.getWidth).head - val mergedTable = table.groupBy(_._1.toString).map { case (key, values) => - // merge same input inputs. - values.head._1 -> BitPat(s"b${ - Seq.tabulate(outputWidth) { i => - val outputSet = values.map(_._2) - .map(_.rawString) - .map(_ (i)) - .toSet - .filterNot(_ == '?') - require(outputSet.size != 2, s"TruthTable conflict in :\n${values.map { case (i, o) => s"${i.rawString}->${o.rawString}" }.mkString("\n")}") - outputSet.headOption.getOrElse('?') - }.mkString - }") - }.toSeq + val mergedTable = table + .groupBy(_._1.toString) + .map { + case (key, values) => + // merge same input inputs. + values.head._1 -> BitPat(s"b${Seq + .tabulate(outputWidth) { i => + val outputSet = values + .map(_._2) + .map(_.rawString) + .map(_(i)) + .toSet + .filterNot(_ == '?') + require( + outputSet.size != 2, + s"TruthTable conflict in :\n${values.map { case (i, o) => s"${i.rawString}->${o.rawString}" }.mkString("\n")}" + ) + outputSet.headOption.getOrElse('?') + } + .mkString}") + } + .toSeq import BitPat.bitPatOrder - new TruthTable(if(sort) mergedTable.sorted else mergedTable, default, sort) + new TruthTable(if (sort) mergedTable.sorted else mergedTable, default, sort) } /** Parse TruthTable from its string representation. */ @@ -77,10 +87,17 @@ object TruthTable { BitPat(s"b${bitPat.rawString.zipWithIndex.filter(b => indexes.contains(b._2)).map(_._1).mkString}") def tableFilter(indexes: Seq[Int]): Option[(TruthTable, Seq[Int])] = { - if(indexes.nonEmpty) Some((TruthTable( - table.table.map { case (in, out) => in -> bpFilter(out, indexes) }, - bpFilter(table.default, indexes) - ), indexes)) else None + if (indexes.nonEmpty) + Some( + ( + TruthTable( + table.table.map { case (in, out) => in -> bpFilter(out, indexes) }, + bpFilter(table.default, indexes) + ), + indexes + ) + ) + else None } def index(bitPat: BitPat, bpType: Char): Seq[Int] = @@ -99,7 +116,12 @@ object TruthTable { tables: Seq[(TruthTable, Seq[Int])] ): TruthTable = { def reIndex(bitPat: BitPat, table: TruthTable, indexes: Seq[Int]): Seq[(Char, Int)] = - table.table.map(a => a._1.toString -> a._2).collectFirst{ case (k, v) if k == bitPat.toString => v}.getOrElse(BitPat.dontCare(indexes.size)).rawString.zip(indexes) + table.table + .map(a => a._1.toString -> a._2) + .collectFirst { case (k, v) if k == bitPat.toString => v } + .getOrElse(BitPat.dontCare(indexes.size)) + .rawString + .zip(indexes) def bitPat(indexedChar: Seq[(Char, Int)]) = BitPat(s"b${indexedChar .sortBy(_._2) .map(_._1) diff --git a/src/main/scala/chisel3/util/experimental/decode/decoder.scala b/src/main/scala/chisel3/util/experimental/decode/decoder.scala index e0bf83b2..4feda672 100644 --- a/src/main/scala/chisel3/util/experimental/decode/decoder.scala +++ b/src/main/scala/chisel3/util/experimental/decode/decoder.scala @@ -3,13 +3,14 @@ package chisel3.util.experimental.decode import chisel3._ -import chisel3.experimental.{ChiselAnnotation, annotate} -import chisel3.util.{BitPat, pla} -import chisel3.util.experimental.{BitSet, getAnnotations} +import chisel3.experimental.{annotate, ChiselAnnotation} +import chisel3.util.{pla, BitPat} +import chisel3.util.experimental.{getAnnotations, BitSet} import firrtl.annotations.Annotation import logger.LazyLogging object decoder extends LazyLogging { + /** Use a specific [[Minimizer]] to generated decoded signals. * * @param minimizer specific [[Minimizer]], can be [[QMCMinimizer]] or [[EspressoMinimizer]]. @@ -71,7 +72,8 @@ object decoder extends LazyLogging { qmc(input, truthTable) } - try espresso(input, truthTable) catch { + try espresso(input, truthTable) + catch { case EspressoNotFoundException => logger.error(s"espresso is not found in your PATH:\n${sys.env("PATH").split(":").mkString("\n")}".stripMargin) qmcFallBack(input, truthTable) @@ -81,7 +83,6 @@ object decoder extends LazyLogging { } } - /** Generate a decoder circuit that matches the input to each bitSet. * * The resulting circuit functions like the following but is optimized with a logic minifier. @@ -104,9 +105,7 @@ object decoder extends LazyLogging { { bitSets.zipWithIndex.flatMap { case (bs, i) => - bs.terms.map(bp => - s"${bp.rawString}->${if (errorBit) "0"}${"0" * (bitSets.size - i - 1)}1${"0" * i}" - ) + bs.terms.map(bp => s"${bp.rawString}->${if (errorBit) "0"}${"0" * (bitSets.size - i - 1)}1${"0" * i}") } ++ Seq(s"${if (errorBit) "1"}${"?" * bitSets.size}") }.mkString("\n") ) diff --git a/src/main/scala/chisel3/util/experimental/getAnnotations.scala b/src/main/scala/chisel3/util/experimental/getAnnotations.scala index dc9b75ee..ac6e6bd1 100644 --- a/src/main/scala/chisel3/util/experimental/getAnnotations.scala +++ b/src/main/scala/chisel3/util/experimental/getAnnotations.scala @@ -4,6 +4,7 @@ import chisel3.internal.Builder import firrtl.AnnotationSeq object getAnnotations { + /** Returns the global Annotations */ def apply(): AnnotationSeq = Builder.annotationSeq } diff --git a/src/main/scala/chisel3/util/experimental/group.scala b/src/main/scala/chisel3/util/experimental/group.scala index e43115d0..202c95d8 100644 --- a/src/main/scala/chisel3/util/experimental/group.scala +++ b/src/main/scala/chisel3/util/experimental/group.scala @@ -3,7 +3,7 @@ package chisel3.util.experimental import chisel3._ -import chisel3.experimental.{ChiselAnnotation, RunFirrtlTransform, annotate} +import chisel3.experimental.{annotate, ChiselAnnotation, RunFirrtlTransform} import chisel3.internal.requireIsHardware import firrtl.Transform import firrtl.transforms.{GroupAnnotation, GroupComponents} @@ -46,12 +46,14 @@ object group { * @tparam T Parent type of input components */ def apply[T <: Data]( - components: Seq[T], - newModule: String, - newInstance: String, - outputSuffix: Option[String] = None, - inputSuffix: Option[String] = None - )(implicit compileOptions: CompileOptions): Unit = { + components: Seq[T], + newModule: String, + newInstance: String, + outputSuffix: Option[String] = None, + inputSuffix: Option[String] = None + )( + implicit compileOptions: CompileOptions + ): Unit = { if (compileOptions.checkSynthesizable) { components.foreach { data => requireIsHardware(data, s"Component ${data.toString} is marked to group, but is not bound.") @@ -64,4 +66,3 @@ object group { }) } } - diff --git a/src/main/scala/chisel3/util/pla.scala b/src/main/scala/chisel3/util/pla.scala index c57ca962..d4707d26 100644 --- a/src/main/scala/chisel3/util/pla.scala +++ b/src/main/scala/chisel3/util/pla.scala @@ -68,7 +68,8 @@ object pla { val inverterMask = invert.value & invert.mask if (inverterMask.bitCount != 0) - require(invert.getWidth == numberOfOutputs, + require( + invert.getWidth == numberOfOutputs, "non-zero inverter mask must have the same width as the output part of specified PLA table" ) @@ -99,28 +100,28 @@ object pla { // the OR matrix val orMatrixOutputs: UInt = Cat( - Seq - .tabulate(numberOfOutputs) { i => - val andMatrixLines = table - // OR matrix composed by input terms which makes this output bit a `1` - .filter { - case (_, or) => or.mask.testBit(i) && or.value.testBit(i) - }.map { - case (inputTerm, _) => - andMatrixOutputs(inputTerm.toString) - } - if (andMatrixLines.isEmpty) false.B - else Cat(andMatrixLines).orR() - } - .reverse - ) + Seq + .tabulate(numberOfOutputs) { i => + val andMatrixLines = table + // OR matrix composed by input terms which makes this output bit a `1` + .filter { + case (_, or) => or.mask.testBit(i) && or.value.testBit(i) + }.map { + case (inputTerm, _) => + andMatrixOutputs(inputTerm.toString) + } + if (andMatrixLines.isEmpty) false.B + else Cat(andMatrixLines).orR() + } + .reverse + ) // the INV matrix, useful for decoders val invMatrixOutputs: UInt = Cat( Seq .tabulate(numberOfOutputs) { i => if (inverterMask.testBit(i)) ~orMatrixOutputs(i) - else orMatrixOutputs(i) + else orMatrixOutputs(i) } .reverse ) diff --git a/src/main/scala/chisel3/util/random/FibonacciLFSR.scala b/src/main/scala/chisel3/util/random/FibonacciLFSR.scala index 32f5caa8..4da51a4e 100644 --- a/src/main/scala/chisel3/util/random/FibonacciLFSR.scala +++ b/src/main/scala/chisel3/util/random/FibonacciLFSR.scala @@ -40,14 +40,16 @@ import chisel3._ * $paramUpdateSeed */ class FibonacciLFSR( - width: Int, - taps: Set[Int], - seed: Option[BigInt] = Some(1), + width: Int, + taps: Set[Int], + seed: Option[BigInt] = Some(1), val reduction: LFSRReduce = XOR, - step: Int = 1, - updateSeed: Boolean = false) extends PRNG(width, seed, step, updateSeed) with LFSR { + step: Int = 1, + updateSeed: Boolean = false) + extends PRNG(width, seed, step, updateSeed) + with LFSR { - def delta(s: Seq[Bool]): Seq[Bool] = taps.map{ case i => s(i - 1) }.reduce(reduction) +: s.dropRight(1) + def delta(s: Seq[Bool]): Seq[Bool] = taps.map { case i => s(i - 1) }.reduce(reduction) +: s.dropRight(1) } @@ -87,11 +89,12 @@ object FibonacciLFSR { * $paramReduction */ def apply( - width: Int, - taps: Set[Int], + width: Int, + taps: Set[Int], increment: Bool = true.B, - seed: Option[BigInt] = Some(1), - reduction: LFSRReduce = XOR): UInt = PRNG(new FibonacciLFSR(width, taps, seed, reduction), increment) + seed: Option[BigInt] = Some(1), + reduction: LFSRReduce = XOR + ): UInt = PRNG(new FibonacciLFSR(width, taps, seed, reduction), increment) /** Return a pseudorandom [[UInt]] generated using a maximal period [[FibonacciLFSR]] * $paramWidth @@ -100,9 +103,10 @@ object FibonacciLFSR { * $paramReduction */ def maxPeriod( - width: Int, + width: Int, increment: Bool = true.B, - seed: Option[BigInt] = Some(1), - reduction: LFSRReduce = XOR): UInt = PRNG(new MaxPeriodFibonacciLFSR(width, seed, reduction), increment) + seed: Option[BigInt] = Some(1), + reduction: LFSRReduce = XOR + ): UInt = PRNG(new MaxPeriodFibonacciLFSR(width, seed, reduction), increment) } diff --git a/src/main/scala/chisel3/util/random/GaloisLFSR.scala b/src/main/scala/chisel3/util/random/GaloisLFSR.scala index 68346e82..f452cf75 100644 --- a/src/main/scala/chisel3/util/random/GaloisLFSR.scala +++ b/src/main/scala/chisel3/util/random/GaloisLFSR.scala @@ -38,21 +38,21 @@ import chisel3._ * $paramUpdateSeed */ class GaloisLFSR( - width: Int, - taps: Set[Int], - seed: Option[BigInt] = Some(1), + width: Int, + taps: Set[Int], + seed: Option[BigInt] = Some(1), val reduction: LFSRReduce = XOR, - step: Int = 1, - updateSeed: Boolean = false) extends PRNG(width, seed, step, updateSeed) with LFSR { + step: Int = 1, + updateSeed: Boolean = false) + extends PRNG(width, seed, step, updateSeed) + with LFSR { def delta(s: Seq[Bool]): Seq[Bool] = { val first = s.head - (s.tail :+ first) - .zipWithIndex - .map { - case (a, i) if taps(i + 1) && (i + 1 != s.size) => reduction(a, first) - case (a, _) => a - } + (s.tail :+ first).zipWithIndex.map { + case (a, i) if taps(i + 1) && (i + 1 != s.size) => reduction(a, first) + case (a, _) => a + } } } @@ -93,11 +93,12 @@ object GaloisLFSR { * $paramReduction */ def apply( - width: Int, - taps: Set[Int], + width: Int, + taps: Set[Int], increment: Bool = true.B, - seed: Option[BigInt] = Some(1), - reduction: LFSRReduce = XOR): UInt = PRNG(new GaloisLFSR(width, taps, seed, reduction), increment) + seed: Option[BigInt] = Some(1), + reduction: LFSRReduce = XOR + ): UInt = PRNG(new GaloisLFSR(width, taps, seed, reduction), increment) /** Return a pseudorandom [[UInt]] generated using a maximal period [[GaloisLFSR]] * $paramWidth @@ -106,9 +107,10 @@ object GaloisLFSR { * $paramReduction */ def maxPeriod( - width: Int, + width: Int, increment: Bool = true.B, - seed: Option[BigInt] = Some(1), - reduction: LFSRReduce = XOR): UInt = PRNG(new MaxPeriodGaloisLFSR(width, seed, reduction), increment) + seed: Option[BigInt] = Some(1), + reduction: LFSRReduce = XOR + ): UInt = PRNG(new MaxPeriodGaloisLFSR(width, seed, reduction), increment) } diff --git a/src/main/scala/chisel3/util/random/LFSR.scala b/src/main/scala/chisel3/util/random/LFSR.scala index 08b124f6..b26cfa5d 100644 --- a/src/main/scala/chisel3/util/random/LFSR.scala +++ b/src/main/scala/chisel3/util/random/LFSR.scala @@ -48,7 +48,8 @@ trait LFSR extends PRNG { def reduction: LFSRReduce override protected def resetValue: Vec[Bool] = seed match { - case Some(s) => reduction match { + case Some(s) => + reduction match { case XOR => require(s != 0, "Seed cannot be zero") case XNOR => require(s != BigInt(2).pow(width) - 1, "Seed cannot be all ones (max value)") } @@ -87,8 +88,9 @@ object LFSR { FibonacciLFSR.maxPeriod(width, increment, seed, XOR) /** Utility used to report an unknown tap width */ - private [random] def badWidth(width: Int): Nothing = throw new IllegalArgumentException( - s"No max period LFSR taps stored for requested width '$width'") + private[random] def badWidth(width: Int): Nothing = throw new IllegalArgumentException( + s"No max period LFSR taps stored for requested width '$width'" + ) /** A mapping of widths to a sequence of known LFSR taps that produce a maximal period LFSR. These work for either a * [[chisel3.util.random.FibonacciLFSR Fibonacci LFSR]] or a [[chisel3.util.random.GaloisLFSR Galois LFSR]]. Taps are @@ -104,796 +106,798 @@ object LFSR { /** First portion of known taps (a combined map hits the 64KB JVM method limit) */ private def tapsFirst = Map( - 2 -> Seq(Set(2, 1)), - 3 -> Seq(Set(3, 2)), - 4 -> Seq(Set(4, 3)), - 5 -> Seq(Set(5, 3), Set(5, 4, 3, 2)), - 6 -> Seq(Set(6, 5), Set(6, 5, 3, 2)), - 7 -> Seq(Set(7, 6), Set(7, 6, 5, 4)), - 8 -> Seq(Set(8, 6, 5, 4)), - 9 -> Seq(Set(9, 5), Set(9, 8, 6, 5)), - 10 -> Seq(Set(10, 7), Set(10, 9, 7, 6)), - 11 -> Seq(Set(11, 9), Set(11, 10, 9, 7)), - 12 -> Seq(Set(12, 11, 8, 6)), - 13 -> Seq(Set(13, 12, 10, 9)), - 14 -> Seq(Set(14, 13, 11, 9)), - 15 -> Seq(Set(15, 14), Set(15, 14, 13, 11)), - 16 -> Seq(Set(16, 14, 13, 11)), - 17 -> Seq(Set(17, 14), Set(17, 16, 15, 14)), - 18 -> Seq(Set(18, 11), Set(18, 17, 16, 13)), - 19 -> Seq(Set(19, 18, 17, 14)), - 20 -> Seq(Set(20, 17), Set(20, 19, 16, 14)), - 21 -> Seq(Set(21, 19), Set(21, 20, 19, 16)), - 22 -> Seq(Set(22, 21), Set(22, 19, 18, 17)), - 23 -> Seq(Set(23, 18), Set(23, 22, 20, 18)), - 24 -> Seq(Set(24, 23, 21, 20)), - 25 -> Seq(Set(25, 22), Set(25, 24, 23, 22)), - 26 -> Seq(Set(26, 25, 24, 20)), - 27 -> Seq(Set(27, 26, 25, 22)), - 28 -> Seq(Set(28, 25), Set(28, 27, 24, 22)), - 29 -> Seq(Set(29, 27), Set(29, 28, 27, 25)), - 30 -> Seq(Set(30, 29, 26, 24)), - 31 -> Seq(Set(31, 28), Set(31, 30, 29, 28)), - 32 -> Seq(Set(32, 30, 26, 25)), - 33 -> Seq(Set(33, 20), Set(33, 32, 29, 27)), - 34 -> Seq(Set(34, 31, 30, 26)), - 35 -> Seq(Set(35, 33), Set(35, 34, 28, 27)), - 36 -> Seq(Set(36, 25), Set(36, 35, 29, 28)), - 37 -> Seq(Set(37, 36, 33, 31)), - 38 -> Seq(Set(38, 37, 33, 32)), - 39 -> Seq(Set(39, 35), Set(39, 38, 35, 32)), - 40 -> Seq(Set(40, 37, 36, 35)), - 41 -> Seq(Set(41, 38), Set(41, 40, 39, 38)), - 42 -> Seq(Set(42, 40, 37, 35)), - 43 -> Seq(Set(43, 42, 38, 37)), - 44 -> Seq(Set(44, 42, 39, 38)), - 45 -> Seq(Set(45, 44, 42, 41)), - 46 -> Seq(Set(46, 40, 39, 38)), - 47 -> Seq(Set(47, 42), Set(47, 46, 43, 42)), - 48 -> Seq(Set(48, 44, 41, 39)), - 49 -> Seq(Set(49, 40), Set(49, 45, 44, 43)), - 50 -> Seq(Set(50, 48, 47, 46)), - 51 -> Seq(Set(51, 50, 48, 45)), - 52 -> Seq(Set(52, 49), Set(52, 51, 49, 46)), - 53 -> Seq(Set(53, 52, 51, 47)), - 54 -> Seq(Set(54, 51, 48, 46)), - 55 -> Seq(Set(55, 31), Set(55, 54, 53, 49)), - 56 -> Seq(Set(56, 54, 52, 49)), - 57 -> Seq(Set(57, 50), Set(57, 55, 54, 52)), - 58 -> Seq(Set(58, 39), Set(58, 57, 53, 52)), - 59 -> Seq(Set(59, 57, 55, 52)), - 60 -> Seq(Set(60, 59), Set(60, 58, 56, 55)), - 61 -> Seq(Set(61, 60, 59, 56)), - 62 -> Seq(Set(62, 59, 57, 56)), - 63 -> Seq(Set(63, 62), Set(63, 62, 59, 58)), - 64 -> Seq(Set(64, 63, 61, 60)), - 65 -> Seq(Set(65, 47), Set(65, 64, 62, 61)), - 66 -> Seq(Set(66, 60, 58, 57)), - 67 -> Seq(Set(67, 66, 65, 62)), - 68 -> Seq(Set(68, 59), Set(68, 67, 63, 61)), - 69 -> Seq(Set(69, 67, 64, 63)), - 70 -> Seq(Set(70, 69, 67, 65)), - 71 -> Seq(Set(71, 65), Set(71, 70, 68, 66)), - 72 -> Seq(Set(72, 69, 63, 62)), - 73 -> Seq(Set(73, 48), Set(73, 71, 70, 69)), - 74 -> Seq(Set(74, 71, 70, 67)), - 75 -> Seq(Set(75, 74, 72, 69)), - 76 -> Seq(Set(76, 74, 72, 71)), - 77 -> Seq(Set(77, 75, 72, 71)), - 78 -> Seq(Set(78, 77, 76, 71)), - 79 -> Seq(Set(79, 70), Set(79, 77, 76, 75)), - 80 -> Seq(Set(80, 78, 76, 71)), - 81 -> Seq(Set(81, 77), Set(81, 79, 78, 75)), - 82 -> Seq(Set(82, 78, 76, 73)), - 83 -> Seq(Set(83, 81, 79, 76)), - 84 -> Seq(Set(84, 71), Set(84, 83, 77, 75)), - 85 -> Seq(Set(85, 84, 83, 77)), - 86 -> Seq(Set(86, 84, 81, 80)), - 87 -> Seq(Set(87, 74), Set(87, 86, 82, 80)), - 88 -> Seq(Set(88, 80, 79, 77)), - 89 -> Seq(Set(89, 51), Set(89, 86, 84, 83)), - 90 -> Seq(Set(90, 88, 87, 85)), - 91 -> Seq(Set(91, 90, 86, 83)), - 92 -> Seq(Set(92, 90, 87, 86)), - 93 -> Seq(Set(93, 91), Set(93, 91, 90, 87)), - 94 -> Seq(Set(94, 73), Set(94, 93, 89, 88)), - 95 -> Seq(Set(95, 84), Set(95, 94, 90, 88)), - 96 -> Seq(Set(96, 90, 87, 86)), - 97 -> Seq(Set(97, 91), Set(97, 95, 93, 91)), - 98 -> Seq(Set(98, 87), Set(98, 97, 91, 90)), - 99 -> Seq(Set(99, 95, 94, 92)), - 100 -> Seq(Set(100, 63), Set(100, 98, 93, 92)), - 101 -> Seq(Set(101, 100, 95, 94)), - 102 -> Seq(Set(102, 99, 97, 96)), - 103 -> Seq(Set(103, 94), Set(103, 102, 99, 94)), - 104 -> Seq(Set(104, 103, 94, 93)), - 105 -> Seq(Set(105, 89), Set(105, 104, 99, 98)), - 106 -> Seq(Set(106, 91), Set(106, 105, 101, 100)), - 107 -> Seq(Set(107, 105, 99, 98)), - 108 -> Seq(Set(108, 77), Set(108, 103, 97, 96)), - 109 -> Seq(Set(109, 107, 105, 104)), - 110 -> Seq(Set(110, 109, 106, 104)), - 111 -> Seq(Set(111, 101), Set(111, 109, 107, 104)), - 112 -> Seq(Set(112, 108, 106, 101)), - 113 -> Seq(Set(113, 104), Set(113, 111, 110, 108)), - 114 -> Seq(Set(114, 113, 112, 103)), - 115 -> Seq(Set(115, 110, 108, 107)), - 116 -> Seq(Set(116, 114, 111, 110)), - 117 -> Seq(Set(117, 116, 115, 112)), - 118 -> Seq(Set(118, 85), Set(118, 116, 113, 112)), - 119 -> Seq(Set(119, 111), Set(119, 116, 111, 110)), - 120 -> Seq(Set(120, 118, 114, 111)), - 121 -> Seq(Set(121, 103), Set(121, 120, 116, 113)), - 122 -> Seq(Set(122, 121, 120, 116)), - 123 -> Seq(Set(123, 121), Set(123, 122, 119, 115)), - 124 -> Seq(Set(124, 87), Set(124, 119, 118, 117)), - 125 -> Seq(Set(125, 120, 119, 118)), - 126 -> Seq(Set(126, 124, 122, 119)), - 127 -> Seq(Set(127, 126), Set(127, 126, 124, 120)), - 128 -> Seq(Set(128, 127, 126, 121)), - 129 -> Seq(Set(129, 124), Set(129, 128, 125, 124)), - 130 -> Seq(Set(130, 127), Set(130, 129, 128, 125)), - 131 -> Seq(Set(131, 129, 128, 123)), - 132 -> Seq(Set(132, 103), Set(132, 130, 127, 123)), - 133 -> Seq(Set(133, 131, 125, 124)), - 134 -> Seq(Set(134, 77), Set(134, 133, 129, 127)), - 135 -> Seq(Set(135, 124), Set(135, 132, 131, 129)), - 136 -> Seq(Set(136, 134, 133, 128)), - 137 -> Seq(Set(137, 116), Set(137, 136, 133, 126)), - 138 -> Seq(Set(138, 137, 131, 130)), - 139 -> Seq(Set(139, 136, 134, 131)), - 140 -> Seq(Set(140, 111), Set(140, 139, 136, 132)), - 141 -> Seq(Set(141, 140, 135, 128)), - 142 -> Seq(Set(142, 121), Set(142, 141, 139, 132)), - 143 -> Seq(Set(143, 141, 140, 138)), - 144 -> Seq(Set(144, 142, 140, 137)), - 145 -> Seq(Set(145, 93), Set(145, 144, 140, 139)), - 146 -> Seq(Set(146, 144, 143, 141)), - 147 -> Seq(Set(147, 145, 143, 136)), - 148 -> Seq(Set(148, 121), Set(148, 145, 143, 141)), - 149 -> Seq(Set(149, 142, 140, 139)), - 150 -> Seq(Set(150, 97), Set(150, 148, 147, 142)), - 151 -> Seq(Set(151, 148), Set(151, 150, 149, 148)), - 152 -> Seq(Set(152, 150, 149, 146)), - 153 -> Seq(Set(153, 152), Set(153, 149, 148, 145)), - 154 -> Seq(Set(154, 153, 149, 145)), - 155 -> Seq(Set(155, 151, 150, 148)), - 156 -> Seq(Set(156, 153, 151, 147)), - 157 -> Seq(Set(157, 155, 152, 151)), - 158 -> Seq(Set(158, 153, 152, 150)), - 159 -> Seq(Set(159, 128), Set(159, 156, 153, 148)), - 160 -> Seq(Set(160, 158, 157, 155)), - 161 -> Seq(Set(161, 143), Set(161, 159, 158, 155)), - 162 -> Seq(Set(162, 158, 155, 154)), - 163 -> Seq(Set(163, 160, 157, 156)), - 164 -> Seq(Set(164, 159, 158, 152)), - 165 -> Seq(Set(165, 162, 157, 156)), - 166 -> Seq(Set(166, 164, 163, 156)), - 167 -> Seq(Set(167, 161), Set(167, 165, 163, 161)), - 168 -> Seq(Set(168, 162, 159, 152)), - 169 -> Seq(Set(169, 135), Set(169, 164, 163, 161)), - 170 -> Seq(Set(170, 147), Set(170, 169, 166, 161)), - 171 -> Seq(Set(171, 169, 166, 165)), - 172 -> Seq(Set(172, 165), Set(172, 169, 165, 161)), - 173 -> Seq(Set(173, 171, 168, 165)), - 174 -> Seq(Set(174, 161), Set(174, 169, 166, 165)), - 175 -> Seq(Set(175, 169), Set(175, 173, 171, 169)), - 176 -> Seq(Set(176, 167, 165, 164)), - 177 -> Seq(Set(177, 169), Set(177, 175, 174, 172)), - 178 -> Seq(Set(178, 91), Set(178, 176, 171, 170)), - 179 -> Seq(Set(179, 178, 177, 175)), - 180 -> Seq(Set(180, 173, 170, 168)), - 181 -> Seq(Set(181, 180, 175, 174)), - 182 -> Seq(Set(182, 181, 176, 174)), - 183 -> Seq(Set(183, 127), Set(183, 179, 176, 175)), - 184 -> Seq(Set(184, 177, 176, 175)), - 185 -> Seq(Set(185, 161), Set(185, 184, 182, 177)), - 186 -> Seq(Set(186, 180, 178, 177)), - 187 -> Seq(Set(187, 182, 181, 180)), - 188 -> Seq(Set(188, 186, 183, 182)), - 189 -> Seq(Set(189, 187, 184, 183)), - 190 -> Seq(Set(190, 188, 184, 177)), - 191 -> Seq(Set(191, 182), Set(191, 187, 185, 184)), - 192 -> Seq(Set(192, 190, 178, 177)), - 193 -> Seq(Set(193, 178), Set(193, 189, 186, 184)), - 194 -> Seq(Set(194, 107), Set(194, 192, 191, 190)), - 195 -> Seq(Set(195, 193, 192, 187)), - 196 -> Seq(Set(196, 194, 187, 185)), - 197 -> Seq(Set(197, 195, 193, 188)), - 198 -> Seq(Set(198, 133), Set(198, 193, 190, 183)), - 199 -> Seq(Set(199, 165), Set(199, 198, 195, 190)), - 200 -> Seq(Set(200, 198, 197, 195)), - 201 -> Seq(Set(201, 187), Set(201, 199, 198, 195)), - 202 -> Seq(Set(202, 147), Set(202, 198, 196, 195)), - 203 -> Seq(Set(203, 202, 196, 195)), - 204 -> Seq(Set(204, 201, 200, 194)), - 205 -> Seq(Set(205, 203, 200, 196)), - 206 -> Seq(Set(206, 201, 197, 196)), - 207 -> Seq(Set(207, 164), Set(207, 206, 201, 198)), - 208 -> Seq(Set(208, 207, 205, 199)), - 209 -> Seq(Set(209, 203), Set(209, 207, 206, 204)), - 210 -> Seq(Set(210, 207, 206, 198)), - 211 -> Seq(Set(211, 203, 201, 200)), - 212 -> Seq(Set(212, 107), Set(212, 209, 208, 205)), - 213 -> Seq(Set(213, 211, 208, 207)), - 214 -> Seq(Set(214, 213, 211, 209)), - 215 -> Seq(Set(215, 192), Set(215, 212, 210, 209)), - 216 -> Seq(Set(216, 215, 213, 209)), - 217 -> Seq(Set(217, 172), Set(217, 213, 212, 211)), - 218 -> Seq(Set(218, 207), Set(218, 217, 211, 210)), - 219 -> Seq(Set(219, 218, 215, 211)), - 220 -> Seq(Set(220, 211, 210, 208)), - 221 -> Seq(Set(221, 219, 215, 213)), - 222 -> Seq(Set(222, 220, 217, 214)), - 223 -> Seq(Set(223, 190), Set(223, 221, 219, 218)), - 224 -> Seq(Set(224, 222, 217, 212)), - 225 -> Seq(Set(225, 193), Set(225, 224, 220, 215)), - 226 -> Seq(Set(226, 223, 219, 216)), - 227 -> Seq(Set(227, 223, 218, 217)), - 228 -> Seq(Set(228, 226, 217, 216)), - 229 -> Seq(Set(229, 228, 225, 219)), - 230 -> Seq(Set(230, 224, 223, 222)), - 231 -> Seq(Set(231, 205), Set(231, 229, 227, 224)), - 232 -> Seq(Set(232, 228, 223, 221)), - 233 -> Seq(Set(233, 159), Set(233, 232, 229, 224)), - 234 -> Seq(Set(234, 203), Set(234, 232, 225, 223)), - 235 -> Seq(Set(235, 234, 229, 226)), - 236 -> Seq(Set(236, 231), Set(236, 229, 228, 226)), - 237 -> Seq(Set(237, 236, 233, 230)), - 238 -> Seq(Set(238, 237, 236, 233)), - 239 -> Seq(Set(239, 203), Set(239, 238, 232, 227)), - 240 -> Seq(Set(240, 237, 235, 232)), - 241 -> Seq(Set(241, 171), Set(241, 237, 233, 232)), - 242 -> Seq(Set(242, 241, 236, 231)), - 243 -> Seq(Set(243, 242, 238, 235)), - 244 -> Seq(Set(244, 243, 240, 235)), - 245 -> Seq(Set(245, 244, 241, 239)), - 246 -> Seq(Set(246, 245, 244, 235)), - 247 -> Seq(Set(247, 165), Set(247, 245, 243, 238)), - 248 -> Seq(Set(248, 238, 234, 233)), - 249 -> Seq(Set(249, 163), Set(249, 248, 245, 242)), - 250 -> Seq(Set(250, 147), Set(250, 247, 245, 240)), - 251 -> Seq(Set(251, 249, 247, 244)), - 252 -> Seq(Set(252, 185), Set(252, 251, 247, 241)), - 253 -> Seq(Set(253, 252, 247, 246)), - 254 -> Seq(Set(254, 253, 252, 247)), - 255 -> Seq(Set(255, 203), Set(255, 253, 252, 250)), - 256 -> Seq(Set(256, 254, 251, 246)), - 257 -> Seq(Set(257, 245), Set(257, 255, 251, 250)), - 258 -> Seq(Set(258, 175), Set(258, 254, 252, 249)), - 259 -> Seq(Set(259, 257, 253, 249)), - 260 -> Seq(Set(260, 253, 252, 250)), - 261 -> Seq(Set(261, 257, 255, 254)), - 262 -> Seq(Set(262, 258, 254, 253)), - 263 -> Seq(Set(263, 170), Set(263, 261, 258, 252)), - 264 -> Seq(Set(264, 263, 255, 254)), - 265 -> Seq(Set(265, 223), Set(265, 263, 262, 260)), - 266 -> Seq(Set(266, 219), Set(266, 265, 260, 259)), - 267 -> Seq(Set(267, 264, 261, 259)), - 268 -> Seq(Set(268, 243), Set(268, 267, 264, 258)), - 269 -> Seq(Set(269, 268, 263, 262)), - 270 -> Seq(Set(270, 217), Set(270, 267, 263, 260)), - 271 -> Seq(Set(271, 213), Set(271, 265, 264, 260)), - 272 -> Seq(Set(272, 270, 266, 263)), - 273 -> Seq(Set(273, 250), Set(273, 272, 271, 266)), - 274 -> Seq(Set(274, 207), Set(274, 272, 267, 265)), - 275 -> Seq(Set(275, 266, 265, 264)), - 276 -> Seq(Set(276, 275, 273, 270)), - 277 -> Seq(Set(277, 274, 271, 265)), - 278 -> Seq(Set(278, 273), Set(278, 277, 274, 273)), - 279 -> Seq(Set(279, 274), Set(279, 278, 275, 274)), - 280 -> Seq(Set(280, 278, 275, 271)), - 281 -> Seq(Set(281, 188), Set(281, 280, 277, 272)), - 282 -> Seq(Set(282, 247), Set(282, 278, 277, 272)), - 283 -> Seq(Set(283, 278, 276, 271)), - 284 -> Seq(Set(284, 165), Set(284, 279, 278, 276)), - 285 -> Seq(Set(285, 280, 278, 275)), - 286 -> Seq(Set(286, 217), Set(286, 285, 276, 271)), - 287 -> Seq(Set(287, 216), Set(287, 285, 282, 281)), - 288 -> Seq(Set(288, 287, 278, 277)), - 289 -> Seq(Set(289, 268), Set(289, 286, 285, 277)), - 290 -> Seq(Set(290, 288, 287, 285)), - 291 -> Seq(Set(291, 286, 280, 279)), - 292 -> Seq(Set(292, 195), Set(292, 291, 289, 285)), - 293 -> Seq(Set(293, 292, 287, 282)), - 294 -> Seq(Set(294, 233), Set(294, 292, 291, 285)), - 295 -> Seq(Set(295, 247), Set(295, 293, 291, 290)), - 296 -> Seq(Set(296, 292, 287, 285)), - 297 -> Seq(Set(297, 292), Set(297, 296, 293, 292)), - 298 -> Seq(Set(298, 294, 290, 287)), - 299 -> Seq(Set(299, 295, 293, 288)), - 300 -> Seq(Set(300, 293), Set(300, 290, 288, 287)), - 301 -> Seq(Set(301, 299, 296, 292)), - 302 -> Seq(Set(302, 261), Set(302, 297, 293, 290)), - 303 -> Seq(Set(303, 297, 291, 290)), - 304 -> Seq(Set(304, 303, 302, 293)), - 305 -> Seq(Set(305, 203), Set(305, 303, 299, 298)), - 306 -> Seq(Set(306, 305, 303, 299)), - 307 -> Seq(Set(307, 305, 303, 299)), - 308 -> Seq(Set(308, 306, 299, 293)), - 309 -> Seq(Set(309, 307, 302, 299)), - 310 -> Seq(Set(310, 309, 305, 302)), - 311 -> Seq(Set(311, 308, 306, 304)), - 312 -> Seq(Set(312, 307, 302, 301)), - 313 -> Seq(Set(313, 234), Set(313, 312, 310, 306)), - 314 -> Seq(Set(314, 299), Set(314, 311, 305, 300)), - 315 -> Seq(Set(315, 314, 306, 305)), - 316 -> Seq(Set(316, 181), Set(316, 309, 305, 304)), - 317 -> Seq(Set(317, 315, 313, 310)), - 318 -> Seq(Set(318, 313, 312, 310)), - 319 -> Seq(Set(319, 283), Set(319, 318, 317, 308)), - 320 -> Seq(Set(320, 319, 317, 316)), - 321 -> Seq(Set(321, 290), Set(321, 319, 316, 314)), - 322 -> Seq(Set(322, 255), Set(322, 321, 320, 305)), - 323 -> Seq(Set(323, 322, 320, 313)), - 324 -> Seq(Set(324, 321, 320, 318)), - 325 -> Seq(Set(325, 323, 320, 315)), - 326 -> Seq(Set(326, 325, 323, 316)), - 327 -> Seq(Set(327, 293), Set(327, 325, 322, 319)), - 328 -> Seq(Set(328, 323, 321, 319)), - 329 -> Seq(Set(329, 279), Set(329, 326, 323, 321)), - 330 -> Seq(Set(330, 328, 323, 322)), - 331 -> Seq(Set(331, 329, 325, 321)), - 332 -> Seq(Set(332, 209), Set(332, 325, 321, 320)), - 333 -> Seq(Set(333, 331), Set(333, 331, 329, 325)), - 334 -> Seq(Set(334, 333, 330, 327)), - 335 -> Seq(Set(335, 333, 328, 325)), - 336 -> Seq(Set(336, 335, 332, 329)), - 337 -> Seq(Set(337, 282), Set(337, 336, 331, 327)), - 338 -> Seq(Set(338, 336, 335, 332)), - 339 -> Seq(Set(339, 332, 329, 323)), - 340 -> Seq(Set(340, 337, 336, 329)), - 341 -> Seq(Set(341, 336, 330, 327)), - 342 -> Seq(Set(342, 217), Set(342, 341, 340, 331)), - 343 -> Seq(Set(343, 268), Set(343, 338, 335, 333)), - 344 -> Seq(Set(344, 338, 334, 333)), - 345 -> Seq(Set(345, 323), Set(345, 343, 341, 337)), - 346 -> Seq(Set(346, 344, 339, 335)), - 347 -> Seq(Set(347, 344, 337, 336)), - 348 -> Seq(Set(348, 344, 341, 340)), - 349 -> Seq(Set(349, 347, 344, 343)), - 350 -> Seq(Set(350, 297), Set(350, 340, 337, 336)), - 351 -> Seq(Set(351, 317), Set(351, 348, 345, 343)), - 352 -> Seq(Set(352, 346, 341, 339)), - 353 -> Seq(Set(353, 284), Set(353, 349, 346, 344)), - 354 -> Seq(Set(354, 349, 341, 340)), - 355 -> Seq(Set(355, 354, 350, 349)), - 356 -> Seq(Set(356, 349, 347, 346)), - 357 -> Seq(Set(357, 355, 347, 346)), - 358 -> Seq(Set(358, 351, 350, 344)), - 359 -> Seq(Set(359, 291), Set(359, 358, 352, 350)), - 360 -> Seq(Set(360, 359, 335, 334)), - 361 -> Seq(Set(361, 360, 357, 354)), - 362 -> Seq(Set(362, 299), Set(362, 360, 351, 344)), - 363 -> Seq(Set(363, 362, 356, 355)), - 364 -> Seq(Set(364, 297), Set(364, 363, 359, 352)), - 365 -> Seq(Set(365, 360, 359, 356)), - 366 -> Seq(Set(366, 337), Set(366, 362, 359, 352)), - 367 -> Seq(Set(367, 346), Set(367, 365, 363, 358)), - 368 -> Seq(Set(368, 361, 359, 351)), - 369 -> Seq(Set(369, 278), Set(369, 367, 359, 358)), - 370 -> Seq(Set(370, 231), Set(370, 368, 367, 365)), - 371 -> Seq(Set(371, 369, 368, 363)), - 372 -> Seq(Set(372, 369, 365, 357)), - 373 -> Seq(Set(373, 371, 366, 365)), - 374 -> Seq(Set(374, 369, 368, 366)), - 375 -> Seq(Set(375, 359), Set(375, 374, 368, 367)), - 376 -> Seq(Set(376, 371, 369, 368)), - 377 -> Seq(Set(377, 336), Set(377, 376, 374, 369)), - 378 -> Seq(Set(378, 335), Set(378, 374, 365, 363)), - 379 -> Seq(Set(379, 375, 370, 369)), - 380 -> Seq(Set(380, 333), Set(380, 377, 374, 366)), - 381 -> Seq(Set(381, 380, 379, 376)), - 382 -> Seq(Set(382, 301), Set(382, 379, 375, 364)), - 383 -> Seq(Set(383, 293), Set(383, 382, 378, 374)), - 384 -> Seq(Set(384, 378, 369, 368)), - 385 -> Seq(Set(385, 379), Set(385, 383, 381, 379)), - 386 -> Seq(Set(386, 303), Set(386, 381, 380, 376)), - 387 -> Seq(Set(387, 385, 379, 378)), - 388 -> Seq(Set(388, 387, 385, 374)), - 389 -> Seq(Set(389, 384, 380, 379)), - 390 -> Seq(Set(390, 301), Set(390, 388, 380, 377)), - 391 -> Seq(Set(391, 363), Set(391, 390, 389, 385)), - 392 -> Seq(Set(392, 386, 382, 379)), - 393 -> Seq(Set(393, 386), Set(393, 392, 391, 386)), - 394 -> Seq(Set(394, 259), Set(394, 392, 387, 386)) ) + 2 -> Seq(Set(2, 1)), + 3 -> Seq(Set(3, 2)), + 4 -> Seq(Set(4, 3)), + 5 -> Seq(Set(5, 3), Set(5, 4, 3, 2)), + 6 -> Seq(Set(6, 5), Set(6, 5, 3, 2)), + 7 -> Seq(Set(7, 6), Set(7, 6, 5, 4)), + 8 -> Seq(Set(8, 6, 5, 4)), + 9 -> Seq(Set(9, 5), Set(9, 8, 6, 5)), + 10 -> Seq(Set(10, 7), Set(10, 9, 7, 6)), + 11 -> Seq(Set(11, 9), Set(11, 10, 9, 7)), + 12 -> Seq(Set(12, 11, 8, 6)), + 13 -> Seq(Set(13, 12, 10, 9)), + 14 -> Seq(Set(14, 13, 11, 9)), + 15 -> Seq(Set(15, 14), Set(15, 14, 13, 11)), + 16 -> Seq(Set(16, 14, 13, 11)), + 17 -> Seq(Set(17, 14), Set(17, 16, 15, 14)), + 18 -> Seq(Set(18, 11), Set(18, 17, 16, 13)), + 19 -> Seq(Set(19, 18, 17, 14)), + 20 -> Seq(Set(20, 17), Set(20, 19, 16, 14)), + 21 -> Seq(Set(21, 19), Set(21, 20, 19, 16)), + 22 -> Seq(Set(22, 21), Set(22, 19, 18, 17)), + 23 -> Seq(Set(23, 18), Set(23, 22, 20, 18)), + 24 -> Seq(Set(24, 23, 21, 20)), + 25 -> Seq(Set(25, 22), Set(25, 24, 23, 22)), + 26 -> Seq(Set(26, 25, 24, 20)), + 27 -> Seq(Set(27, 26, 25, 22)), + 28 -> Seq(Set(28, 25), Set(28, 27, 24, 22)), + 29 -> Seq(Set(29, 27), Set(29, 28, 27, 25)), + 30 -> Seq(Set(30, 29, 26, 24)), + 31 -> Seq(Set(31, 28), Set(31, 30, 29, 28)), + 32 -> Seq(Set(32, 30, 26, 25)), + 33 -> Seq(Set(33, 20), Set(33, 32, 29, 27)), + 34 -> Seq(Set(34, 31, 30, 26)), + 35 -> Seq(Set(35, 33), Set(35, 34, 28, 27)), + 36 -> Seq(Set(36, 25), Set(36, 35, 29, 28)), + 37 -> Seq(Set(37, 36, 33, 31)), + 38 -> Seq(Set(38, 37, 33, 32)), + 39 -> Seq(Set(39, 35), Set(39, 38, 35, 32)), + 40 -> Seq(Set(40, 37, 36, 35)), + 41 -> Seq(Set(41, 38), Set(41, 40, 39, 38)), + 42 -> Seq(Set(42, 40, 37, 35)), + 43 -> Seq(Set(43, 42, 38, 37)), + 44 -> Seq(Set(44, 42, 39, 38)), + 45 -> Seq(Set(45, 44, 42, 41)), + 46 -> Seq(Set(46, 40, 39, 38)), + 47 -> Seq(Set(47, 42), Set(47, 46, 43, 42)), + 48 -> Seq(Set(48, 44, 41, 39)), + 49 -> Seq(Set(49, 40), Set(49, 45, 44, 43)), + 50 -> Seq(Set(50, 48, 47, 46)), + 51 -> Seq(Set(51, 50, 48, 45)), + 52 -> Seq(Set(52, 49), Set(52, 51, 49, 46)), + 53 -> Seq(Set(53, 52, 51, 47)), + 54 -> Seq(Set(54, 51, 48, 46)), + 55 -> Seq(Set(55, 31), Set(55, 54, 53, 49)), + 56 -> Seq(Set(56, 54, 52, 49)), + 57 -> Seq(Set(57, 50), Set(57, 55, 54, 52)), + 58 -> Seq(Set(58, 39), Set(58, 57, 53, 52)), + 59 -> Seq(Set(59, 57, 55, 52)), + 60 -> Seq(Set(60, 59), Set(60, 58, 56, 55)), + 61 -> Seq(Set(61, 60, 59, 56)), + 62 -> Seq(Set(62, 59, 57, 56)), + 63 -> Seq(Set(63, 62), Set(63, 62, 59, 58)), + 64 -> Seq(Set(64, 63, 61, 60)), + 65 -> Seq(Set(65, 47), Set(65, 64, 62, 61)), + 66 -> Seq(Set(66, 60, 58, 57)), + 67 -> Seq(Set(67, 66, 65, 62)), + 68 -> Seq(Set(68, 59), Set(68, 67, 63, 61)), + 69 -> Seq(Set(69, 67, 64, 63)), + 70 -> Seq(Set(70, 69, 67, 65)), + 71 -> Seq(Set(71, 65), Set(71, 70, 68, 66)), + 72 -> Seq(Set(72, 69, 63, 62)), + 73 -> Seq(Set(73, 48), Set(73, 71, 70, 69)), + 74 -> Seq(Set(74, 71, 70, 67)), + 75 -> Seq(Set(75, 74, 72, 69)), + 76 -> Seq(Set(76, 74, 72, 71)), + 77 -> Seq(Set(77, 75, 72, 71)), + 78 -> Seq(Set(78, 77, 76, 71)), + 79 -> Seq(Set(79, 70), Set(79, 77, 76, 75)), + 80 -> Seq(Set(80, 78, 76, 71)), + 81 -> Seq(Set(81, 77), Set(81, 79, 78, 75)), + 82 -> Seq(Set(82, 78, 76, 73)), + 83 -> Seq(Set(83, 81, 79, 76)), + 84 -> Seq(Set(84, 71), Set(84, 83, 77, 75)), + 85 -> Seq(Set(85, 84, 83, 77)), + 86 -> Seq(Set(86, 84, 81, 80)), + 87 -> Seq(Set(87, 74), Set(87, 86, 82, 80)), + 88 -> Seq(Set(88, 80, 79, 77)), + 89 -> Seq(Set(89, 51), Set(89, 86, 84, 83)), + 90 -> Seq(Set(90, 88, 87, 85)), + 91 -> Seq(Set(91, 90, 86, 83)), + 92 -> Seq(Set(92, 90, 87, 86)), + 93 -> Seq(Set(93, 91), Set(93, 91, 90, 87)), + 94 -> Seq(Set(94, 73), Set(94, 93, 89, 88)), + 95 -> Seq(Set(95, 84), Set(95, 94, 90, 88)), + 96 -> Seq(Set(96, 90, 87, 86)), + 97 -> Seq(Set(97, 91), Set(97, 95, 93, 91)), + 98 -> Seq(Set(98, 87), Set(98, 97, 91, 90)), + 99 -> Seq(Set(99, 95, 94, 92)), + 100 -> Seq(Set(100, 63), Set(100, 98, 93, 92)), + 101 -> Seq(Set(101, 100, 95, 94)), + 102 -> Seq(Set(102, 99, 97, 96)), + 103 -> Seq(Set(103, 94), Set(103, 102, 99, 94)), + 104 -> Seq(Set(104, 103, 94, 93)), + 105 -> Seq(Set(105, 89), Set(105, 104, 99, 98)), + 106 -> Seq(Set(106, 91), Set(106, 105, 101, 100)), + 107 -> Seq(Set(107, 105, 99, 98)), + 108 -> Seq(Set(108, 77), Set(108, 103, 97, 96)), + 109 -> Seq(Set(109, 107, 105, 104)), + 110 -> Seq(Set(110, 109, 106, 104)), + 111 -> Seq(Set(111, 101), Set(111, 109, 107, 104)), + 112 -> Seq(Set(112, 108, 106, 101)), + 113 -> Seq(Set(113, 104), Set(113, 111, 110, 108)), + 114 -> Seq(Set(114, 113, 112, 103)), + 115 -> Seq(Set(115, 110, 108, 107)), + 116 -> Seq(Set(116, 114, 111, 110)), + 117 -> Seq(Set(117, 116, 115, 112)), + 118 -> Seq(Set(118, 85), Set(118, 116, 113, 112)), + 119 -> Seq(Set(119, 111), Set(119, 116, 111, 110)), + 120 -> Seq(Set(120, 118, 114, 111)), + 121 -> Seq(Set(121, 103), Set(121, 120, 116, 113)), + 122 -> Seq(Set(122, 121, 120, 116)), + 123 -> Seq(Set(123, 121), Set(123, 122, 119, 115)), + 124 -> Seq(Set(124, 87), Set(124, 119, 118, 117)), + 125 -> Seq(Set(125, 120, 119, 118)), + 126 -> Seq(Set(126, 124, 122, 119)), + 127 -> Seq(Set(127, 126), Set(127, 126, 124, 120)), + 128 -> Seq(Set(128, 127, 126, 121)), + 129 -> Seq(Set(129, 124), Set(129, 128, 125, 124)), + 130 -> Seq(Set(130, 127), Set(130, 129, 128, 125)), + 131 -> Seq(Set(131, 129, 128, 123)), + 132 -> Seq(Set(132, 103), Set(132, 130, 127, 123)), + 133 -> Seq(Set(133, 131, 125, 124)), + 134 -> Seq(Set(134, 77), Set(134, 133, 129, 127)), + 135 -> Seq(Set(135, 124), Set(135, 132, 131, 129)), + 136 -> Seq(Set(136, 134, 133, 128)), + 137 -> Seq(Set(137, 116), Set(137, 136, 133, 126)), + 138 -> Seq(Set(138, 137, 131, 130)), + 139 -> Seq(Set(139, 136, 134, 131)), + 140 -> Seq(Set(140, 111), Set(140, 139, 136, 132)), + 141 -> Seq(Set(141, 140, 135, 128)), + 142 -> Seq(Set(142, 121), Set(142, 141, 139, 132)), + 143 -> Seq(Set(143, 141, 140, 138)), + 144 -> Seq(Set(144, 142, 140, 137)), + 145 -> Seq(Set(145, 93), Set(145, 144, 140, 139)), + 146 -> Seq(Set(146, 144, 143, 141)), + 147 -> Seq(Set(147, 145, 143, 136)), + 148 -> Seq(Set(148, 121), Set(148, 145, 143, 141)), + 149 -> Seq(Set(149, 142, 140, 139)), + 150 -> Seq(Set(150, 97), Set(150, 148, 147, 142)), + 151 -> Seq(Set(151, 148), Set(151, 150, 149, 148)), + 152 -> Seq(Set(152, 150, 149, 146)), + 153 -> Seq(Set(153, 152), Set(153, 149, 148, 145)), + 154 -> Seq(Set(154, 153, 149, 145)), + 155 -> Seq(Set(155, 151, 150, 148)), + 156 -> Seq(Set(156, 153, 151, 147)), + 157 -> Seq(Set(157, 155, 152, 151)), + 158 -> Seq(Set(158, 153, 152, 150)), + 159 -> Seq(Set(159, 128), Set(159, 156, 153, 148)), + 160 -> Seq(Set(160, 158, 157, 155)), + 161 -> Seq(Set(161, 143), Set(161, 159, 158, 155)), + 162 -> Seq(Set(162, 158, 155, 154)), + 163 -> Seq(Set(163, 160, 157, 156)), + 164 -> Seq(Set(164, 159, 158, 152)), + 165 -> Seq(Set(165, 162, 157, 156)), + 166 -> Seq(Set(166, 164, 163, 156)), + 167 -> Seq(Set(167, 161), Set(167, 165, 163, 161)), + 168 -> Seq(Set(168, 162, 159, 152)), + 169 -> Seq(Set(169, 135), Set(169, 164, 163, 161)), + 170 -> Seq(Set(170, 147), Set(170, 169, 166, 161)), + 171 -> Seq(Set(171, 169, 166, 165)), + 172 -> Seq(Set(172, 165), Set(172, 169, 165, 161)), + 173 -> Seq(Set(173, 171, 168, 165)), + 174 -> Seq(Set(174, 161), Set(174, 169, 166, 165)), + 175 -> Seq(Set(175, 169), Set(175, 173, 171, 169)), + 176 -> Seq(Set(176, 167, 165, 164)), + 177 -> Seq(Set(177, 169), Set(177, 175, 174, 172)), + 178 -> Seq(Set(178, 91), Set(178, 176, 171, 170)), + 179 -> Seq(Set(179, 178, 177, 175)), + 180 -> Seq(Set(180, 173, 170, 168)), + 181 -> Seq(Set(181, 180, 175, 174)), + 182 -> Seq(Set(182, 181, 176, 174)), + 183 -> Seq(Set(183, 127), Set(183, 179, 176, 175)), + 184 -> Seq(Set(184, 177, 176, 175)), + 185 -> Seq(Set(185, 161), Set(185, 184, 182, 177)), + 186 -> Seq(Set(186, 180, 178, 177)), + 187 -> Seq(Set(187, 182, 181, 180)), + 188 -> Seq(Set(188, 186, 183, 182)), + 189 -> Seq(Set(189, 187, 184, 183)), + 190 -> Seq(Set(190, 188, 184, 177)), + 191 -> Seq(Set(191, 182), Set(191, 187, 185, 184)), + 192 -> Seq(Set(192, 190, 178, 177)), + 193 -> Seq(Set(193, 178), Set(193, 189, 186, 184)), + 194 -> Seq(Set(194, 107), Set(194, 192, 191, 190)), + 195 -> Seq(Set(195, 193, 192, 187)), + 196 -> Seq(Set(196, 194, 187, 185)), + 197 -> Seq(Set(197, 195, 193, 188)), + 198 -> Seq(Set(198, 133), Set(198, 193, 190, 183)), + 199 -> Seq(Set(199, 165), Set(199, 198, 195, 190)), + 200 -> Seq(Set(200, 198, 197, 195)), + 201 -> Seq(Set(201, 187), Set(201, 199, 198, 195)), + 202 -> Seq(Set(202, 147), Set(202, 198, 196, 195)), + 203 -> Seq(Set(203, 202, 196, 195)), + 204 -> Seq(Set(204, 201, 200, 194)), + 205 -> Seq(Set(205, 203, 200, 196)), + 206 -> Seq(Set(206, 201, 197, 196)), + 207 -> Seq(Set(207, 164), Set(207, 206, 201, 198)), + 208 -> Seq(Set(208, 207, 205, 199)), + 209 -> Seq(Set(209, 203), Set(209, 207, 206, 204)), + 210 -> Seq(Set(210, 207, 206, 198)), + 211 -> Seq(Set(211, 203, 201, 200)), + 212 -> Seq(Set(212, 107), Set(212, 209, 208, 205)), + 213 -> Seq(Set(213, 211, 208, 207)), + 214 -> Seq(Set(214, 213, 211, 209)), + 215 -> Seq(Set(215, 192), Set(215, 212, 210, 209)), + 216 -> Seq(Set(216, 215, 213, 209)), + 217 -> Seq(Set(217, 172), Set(217, 213, 212, 211)), + 218 -> Seq(Set(218, 207), Set(218, 217, 211, 210)), + 219 -> Seq(Set(219, 218, 215, 211)), + 220 -> Seq(Set(220, 211, 210, 208)), + 221 -> Seq(Set(221, 219, 215, 213)), + 222 -> Seq(Set(222, 220, 217, 214)), + 223 -> Seq(Set(223, 190), Set(223, 221, 219, 218)), + 224 -> Seq(Set(224, 222, 217, 212)), + 225 -> Seq(Set(225, 193), Set(225, 224, 220, 215)), + 226 -> Seq(Set(226, 223, 219, 216)), + 227 -> Seq(Set(227, 223, 218, 217)), + 228 -> Seq(Set(228, 226, 217, 216)), + 229 -> Seq(Set(229, 228, 225, 219)), + 230 -> Seq(Set(230, 224, 223, 222)), + 231 -> Seq(Set(231, 205), Set(231, 229, 227, 224)), + 232 -> Seq(Set(232, 228, 223, 221)), + 233 -> Seq(Set(233, 159), Set(233, 232, 229, 224)), + 234 -> Seq(Set(234, 203), Set(234, 232, 225, 223)), + 235 -> Seq(Set(235, 234, 229, 226)), + 236 -> Seq(Set(236, 231), Set(236, 229, 228, 226)), + 237 -> Seq(Set(237, 236, 233, 230)), + 238 -> Seq(Set(238, 237, 236, 233)), + 239 -> Seq(Set(239, 203), Set(239, 238, 232, 227)), + 240 -> Seq(Set(240, 237, 235, 232)), + 241 -> Seq(Set(241, 171), Set(241, 237, 233, 232)), + 242 -> Seq(Set(242, 241, 236, 231)), + 243 -> Seq(Set(243, 242, 238, 235)), + 244 -> Seq(Set(244, 243, 240, 235)), + 245 -> Seq(Set(245, 244, 241, 239)), + 246 -> Seq(Set(246, 245, 244, 235)), + 247 -> Seq(Set(247, 165), Set(247, 245, 243, 238)), + 248 -> Seq(Set(248, 238, 234, 233)), + 249 -> Seq(Set(249, 163), Set(249, 248, 245, 242)), + 250 -> Seq(Set(250, 147), Set(250, 247, 245, 240)), + 251 -> Seq(Set(251, 249, 247, 244)), + 252 -> Seq(Set(252, 185), Set(252, 251, 247, 241)), + 253 -> Seq(Set(253, 252, 247, 246)), + 254 -> Seq(Set(254, 253, 252, 247)), + 255 -> Seq(Set(255, 203), Set(255, 253, 252, 250)), + 256 -> Seq(Set(256, 254, 251, 246)), + 257 -> Seq(Set(257, 245), Set(257, 255, 251, 250)), + 258 -> Seq(Set(258, 175), Set(258, 254, 252, 249)), + 259 -> Seq(Set(259, 257, 253, 249)), + 260 -> Seq(Set(260, 253, 252, 250)), + 261 -> Seq(Set(261, 257, 255, 254)), + 262 -> Seq(Set(262, 258, 254, 253)), + 263 -> Seq(Set(263, 170), Set(263, 261, 258, 252)), + 264 -> Seq(Set(264, 263, 255, 254)), + 265 -> Seq(Set(265, 223), Set(265, 263, 262, 260)), + 266 -> Seq(Set(266, 219), Set(266, 265, 260, 259)), + 267 -> Seq(Set(267, 264, 261, 259)), + 268 -> Seq(Set(268, 243), Set(268, 267, 264, 258)), + 269 -> Seq(Set(269, 268, 263, 262)), + 270 -> Seq(Set(270, 217), Set(270, 267, 263, 260)), + 271 -> Seq(Set(271, 213), Set(271, 265, 264, 260)), + 272 -> Seq(Set(272, 270, 266, 263)), + 273 -> Seq(Set(273, 250), Set(273, 272, 271, 266)), + 274 -> Seq(Set(274, 207), Set(274, 272, 267, 265)), + 275 -> Seq(Set(275, 266, 265, 264)), + 276 -> Seq(Set(276, 275, 273, 270)), + 277 -> Seq(Set(277, 274, 271, 265)), + 278 -> Seq(Set(278, 273), Set(278, 277, 274, 273)), + 279 -> Seq(Set(279, 274), Set(279, 278, 275, 274)), + 280 -> Seq(Set(280, 278, 275, 271)), + 281 -> Seq(Set(281, 188), Set(281, 280, 277, 272)), + 282 -> Seq(Set(282, 247), Set(282, 278, 277, 272)), + 283 -> Seq(Set(283, 278, 276, 271)), + 284 -> Seq(Set(284, 165), Set(284, 279, 278, 276)), + 285 -> Seq(Set(285, 280, 278, 275)), + 286 -> Seq(Set(286, 217), Set(286, 285, 276, 271)), + 287 -> Seq(Set(287, 216), Set(287, 285, 282, 281)), + 288 -> Seq(Set(288, 287, 278, 277)), + 289 -> Seq(Set(289, 268), Set(289, 286, 285, 277)), + 290 -> Seq(Set(290, 288, 287, 285)), + 291 -> Seq(Set(291, 286, 280, 279)), + 292 -> Seq(Set(292, 195), Set(292, 291, 289, 285)), + 293 -> Seq(Set(293, 292, 287, 282)), + 294 -> Seq(Set(294, 233), Set(294, 292, 291, 285)), + 295 -> Seq(Set(295, 247), Set(295, 293, 291, 290)), + 296 -> Seq(Set(296, 292, 287, 285)), + 297 -> Seq(Set(297, 292), Set(297, 296, 293, 292)), + 298 -> Seq(Set(298, 294, 290, 287)), + 299 -> Seq(Set(299, 295, 293, 288)), + 300 -> Seq(Set(300, 293), Set(300, 290, 288, 287)), + 301 -> Seq(Set(301, 299, 296, 292)), + 302 -> Seq(Set(302, 261), Set(302, 297, 293, 290)), + 303 -> Seq(Set(303, 297, 291, 290)), + 304 -> Seq(Set(304, 303, 302, 293)), + 305 -> Seq(Set(305, 203), Set(305, 303, 299, 298)), + 306 -> Seq(Set(306, 305, 303, 299)), + 307 -> Seq(Set(307, 305, 303, 299)), + 308 -> Seq(Set(308, 306, 299, 293)), + 309 -> Seq(Set(309, 307, 302, 299)), + 310 -> Seq(Set(310, 309, 305, 302)), + 311 -> Seq(Set(311, 308, 306, 304)), + 312 -> Seq(Set(312, 307, 302, 301)), + 313 -> Seq(Set(313, 234), Set(313, 312, 310, 306)), + 314 -> Seq(Set(314, 299), Set(314, 311, 305, 300)), + 315 -> Seq(Set(315, 314, 306, 305)), + 316 -> Seq(Set(316, 181), Set(316, 309, 305, 304)), + 317 -> Seq(Set(317, 315, 313, 310)), + 318 -> Seq(Set(318, 313, 312, 310)), + 319 -> Seq(Set(319, 283), Set(319, 318, 317, 308)), + 320 -> Seq(Set(320, 319, 317, 316)), + 321 -> Seq(Set(321, 290), Set(321, 319, 316, 314)), + 322 -> Seq(Set(322, 255), Set(322, 321, 320, 305)), + 323 -> Seq(Set(323, 322, 320, 313)), + 324 -> Seq(Set(324, 321, 320, 318)), + 325 -> Seq(Set(325, 323, 320, 315)), + 326 -> Seq(Set(326, 325, 323, 316)), + 327 -> Seq(Set(327, 293), Set(327, 325, 322, 319)), + 328 -> Seq(Set(328, 323, 321, 319)), + 329 -> Seq(Set(329, 279), Set(329, 326, 323, 321)), + 330 -> Seq(Set(330, 328, 323, 322)), + 331 -> Seq(Set(331, 329, 325, 321)), + 332 -> Seq(Set(332, 209), Set(332, 325, 321, 320)), + 333 -> Seq(Set(333, 331), Set(333, 331, 329, 325)), + 334 -> Seq(Set(334, 333, 330, 327)), + 335 -> Seq(Set(335, 333, 328, 325)), + 336 -> Seq(Set(336, 335, 332, 329)), + 337 -> Seq(Set(337, 282), Set(337, 336, 331, 327)), + 338 -> Seq(Set(338, 336, 335, 332)), + 339 -> Seq(Set(339, 332, 329, 323)), + 340 -> Seq(Set(340, 337, 336, 329)), + 341 -> Seq(Set(341, 336, 330, 327)), + 342 -> Seq(Set(342, 217), Set(342, 341, 340, 331)), + 343 -> Seq(Set(343, 268), Set(343, 338, 335, 333)), + 344 -> Seq(Set(344, 338, 334, 333)), + 345 -> Seq(Set(345, 323), Set(345, 343, 341, 337)), + 346 -> Seq(Set(346, 344, 339, 335)), + 347 -> Seq(Set(347, 344, 337, 336)), + 348 -> Seq(Set(348, 344, 341, 340)), + 349 -> Seq(Set(349, 347, 344, 343)), + 350 -> Seq(Set(350, 297), Set(350, 340, 337, 336)), + 351 -> Seq(Set(351, 317), Set(351, 348, 345, 343)), + 352 -> Seq(Set(352, 346, 341, 339)), + 353 -> Seq(Set(353, 284), Set(353, 349, 346, 344)), + 354 -> Seq(Set(354, 349, 341, 340)), + 355 -> Seq(Set(355, 354, 350, 349)), + 356 -> Seq(Set(356, 349, 347, 346)), + 357 -> Seq(Set(357, 355, 347, 346)), + 358 -> Seq(Set(358, 351, 350, 344)), + 359 -> Seq(Set(359, 291), Set(359, 358, 352, 350)), + 360 -> Seq(Set(360, 359, 335, 334)), + 361 -> Seq(Set(361, 360, 357, 354)), + 362 -> Seq(Set(362, 299), Set(362, 360, 351, 344)), + 363 -> Seq(Set(363, 362, 356, 355)), + 364 -> Seq(Set(364, 297), Set(364, 363, 359, 352)), + 365 -> Seq(Set(365, 360, 359, 356)), + 366 -> Seq(Set(366, 337), Set(366, 362, 359, 352)), + 367 -> Seq(Set(367, 346), Set(367, 365, 363, 358)), + 368 -> Seq(Set(368, 361, 359, 351)), + 369 -> Seq(Set(369, 278), Set(369, 367, 359, 358)), + 370 -> Seq(Set(370, 231), Set(370, 368, 367, 365)), + 371 -> Seq(Set(371, 369, 368, 363)), + 372 -> Seq(Set(372, 369, 365, 357)), + 373 -> Seq(Set(373, 371, 366, 365)), + 374 -> Seq(Set(374, 369, 368, 366)), + 375 -> Seq(Set(375, 359), Set(375, 374, 368, 367)), + 376 -> Seq(Set(376, 371, 369, 368)), + 377 -> Seq(Set(377, 336), Set(377, 376, 374, 369)), + 378 -> Seq(Set(378, 335), Set(378, 374, 365, 363)), + 379 -> Seq(Set(379, 375, 370, 369)), + 380 -> Seq(Set(380, 333), Set(380, 377, 374, 366)), + 381 -> Seq(Set(381, 380, 379, 376)), + 382 -> Seq(Set(382, 301), Set(382, 379, 375, 364)), + 383 -> Seq(Set(383, 293), Set(383, 382, 378, 374)), + 384 -> Seq(Set(384, 378, 369, 368)), + 385 -> Seq(Set(385, 379), Set(385, 383, 381, 379)), + 386 -> Seq(Set(386, 303), Set(386, 381, 380, 376)), + 387 -> Seq(Set(387, 385, 379, 378)), + 388 -> Seq(Set(388, 387, 385, 374)), + 389 -> Seq(Set(389, 384, 380, 379)), + 390 -> Seq(Set(390, 301), Set(390, 388, 380, 377)), + 391 -> Seq(Set(391, 363), Set(391, 390, 389, 385)), + 392 -> Seq(Set(392, 386, 382, 379)), + 393 -> Seq(Set(393, 386), Set(393, 392, 391, 386)), + 394 -> Seq(Set(394, 259), Set(394, 392, 387, 386)) + ) /** Second portion of known taps (a combined map hits the 64KB JVM method limit) */ private def tapsSecond = Map( - 395 -> Seq(Set(395, 390, 389, 384)), - 396 -> Seq(Set(396, 371), Set(396, 392, 390, 389)), - 397 -> Seq(Set(397, 392, 387, 385)), - 398 -> Seq(Set(398, 393, 392, 384)), - 399 -> Seq(Set(399, 313), Set(399, 397, 390, 388)), - 400 -> Seq(Set(400, 398, 397, 395)), - 401 -> Seq(Set(401, 249), Set(401, 399, 392, 389)), - 402 -> Seq(Set(402, 399, 398, 393)), - 403 -> Seq(Set(403, 398, 395, 394)), - 404 -> Seq(Set(404, 215), Set(404, 400, 398, 397)), - 405 -> Seq(Set(405, 398, 397, 388)), - 406 -> Seq(Set(406, 249), Set(406, 402, 397, 393)), - 407 -> Seq(Set(407, 336), Set(407, 402, 400, 398)), - 408 -> Seq(Set(408, 407, 403, 401)), - 409 -> Seq(Set(409, 322), Set(409, 406, 404, 402)), - 410 -> Seq(Set(410, 407, 406, 400)), - 411 -> Seq(Set(411, 408, 401, 399)), - 412 -> Seq(Set(412, 265), Set(412, 409, 404, 401)), - 413 -> Seq(Set(413, 407, 406, 403)), - 414 -> Seq(Set(414, 405, 401, 398)), - 415 -> Seq(Set(415, 313), Set(415, 413, 411, 406)), - 416 -> Seq(Set(416, 414, 411, 407)), - 417 -> Seq(Set(417, 310), Set(417, 416, 414, 407)), - 418 -> Seq(Set(418, 417, 415, 403)), - 419 -> Seq(Set(419, 415, 414, 404)), - 420 -> Seq(Set(420, 412, 410, 407)), - 421 -> Seq(Set(421, 419, 417, 416)), - 422 -> Seq(Set(422, 273), Set(422, 421, 416, 412)), - 423 -> Seq(Set(423, 398), Set(423, 420, 418, 414)), - 424 -> Seq(Set(424, 422, 417, 415)), - 425 -> Seq(Set(425, 413), Set(425, 422, 421, 418)), - 426 -> Seq(Set(426, 415, 414, 412)), - 427 -> Seq(Set(427, 422, 421, 416)), - 428 -> Seq(Set(428, 323), Set(428, 426, 425, 417)), - 429 -> Seq(Set(429, 422, 421, 419)), - 430 -> Seq(Set(430, 419, 417, 415)), - 431 -> Seq(Set(431, 311), Set(431, 430, 428, 426)), - 432 -> Seq(Set(432, 429, 428, 419)), - 433 -> Seq(Set(433, 400), Set(433, 430, 428, 422)), - 434 -> Seq(Set(434, 429, 423, 422)), - 435 -> Seq(Set(435, 430, 426, 423)), - 436 -> Seq(Set(436, 271), Set(436, 432, 431, 430)), - 437 -> Seq(Set(437, 436, 435, 431)), - 438 -> Seq(Set(438, 373), Set(438, 436, 432, 421)), - 439 -> Seq(Set(439, 390), Set(439, 437, 436, 431)), - 440 -> Seq(Set(440, 439, 437, 436)), - 441 -> Seq(Set(441, 410), Set(441, 440, 433, 430)), - 442 -> Seq(Set(442, 440, 437, 435)), - 443 -> Seq(Set(443, 442, 437, 433)), - 444 -> Seq(Set(444, 435, 432, 431)), - 445 -> Seq(Set(445, 441, 439, 438)), - 446 -> Seq(Set(446, 341), Set(446, 442, 439, 431)), - 447 -> Seq(Set(447, 374), Set(447, 446, 441, 438)), - 448 -> Seq(Set(448, 444, 442, 437)), - 449 -> Seq(Set(449, 315), Set(449, 446, 440, 438)), - 450 -> Seq(Set(450, 371), Set(450, 443, 438, 434)), - 451 -> Seq(Set(451, 450, 441, 435)), - 452 -> Seq(Set(452, 448, 447, 446)), - 453 -> Seq(Set(453, 449, 447, 438)), - 454 -> Seq(Set(454, 449, 445, 444)), - 455 -> Seq(Set(455, 417), Set(455, 453, 449, 444)), - 456 -> Seq(Set(456, 454, 445, 433)), - 457 -> Seq(Set(457, 441), Set(457, 454, 449, 446)), - 458 -> Seq(Set(458, 255), Set(458, 453, 448, 445)), - 459 -> Seq(Set(459, 457, 454, 447)), - 460 -> Seq(Set(460, 399), Set(460, 459, 455, 451)), - 461 -> Seq(Set(461, 460, 455, 454)), - 462 -> Seq(Set(462, 389), Set(462, 457, 451, 450)), - 463 -> Seq(Set(463, 370), Set(463, 456, 455, 452)), - 464 -> Seq(Set(464, 460, 455, 441)), - 465 -> Seq(Set(465, 406), Set(465, 463, 462, 457)), - 466 -> Seq(Set(466, 460, 455, 452)), - 467 -> Seq(Set(467, 466, 461, 456)), - 468 -> Seq(Set(468, 464, 459, 453)), - 469 -> Seq(Set(469, 467, 464, 460)), - 470 -> Seq(Set(470, 321), Set(470, 468, 462, 461)), - 471 -> Seq(Set(471, 470), Set(471, 469, 468, 465)), - 472 -> Seq(Set(472, 470, 469, 461)), - 473 -> Seq(Set(473, 470, 467, 465)), - 474 -> Seq(Set(474, 283), Set(474, 465, 463, 456)), - 475 -> Seq(Set(475, 471, 467, 466)), - 476 -> Seq(Set(476, 461), Set(476, 475, 468, 466)), - 477 -> Seq(Set(477, 470, 462, 461)), - 478 -> Seq(Set(478, 357), Set(478, 477, 474, 472)), - 479 -> Seq(Set(479, 375), Set(479, 475, 472, 470)), - 480 -> Seq(Set(480, 473, 467, 464)), - 481 -> Seq(Set(481, 343), Set(481, 480, 472, 471)), - 482 -> Seq(Set(482, 477, 476, 473)), - 483 -> Seq(Set(483, 479, 477, 474)), - 484 -> Seq(Set(484, 379), Set(484, 483, 482, 470)), - 485 -> Seq(Set(485, 479, 469, 468)), - 486 -> Seq(Set(486, 481, 478, 472)), - 487 -> Seq(Set(487, 393), Set(487, 485, 483, 478)), - 488 -> Seq(Set(488, 487, 485, 484)), - 489 -> Seq(Set(489, 406), Set(489, 484, 483, 480)), - 490 -> Seq(Set(490, 271), Set(490, 485, 483, 481)), - 491 -> Seq(Set(491, 488, 485, 480)), - 492 -> Seq(Set(492, 491, 485, 484)), - 493 -> Seq(Set(493, 490, 488, 483)), - 494 -> Seq(Set(494, 357), Set(494, 493, 489, 481)), - 495 -> Seq(Set(495, 419), Set(495, 494, 486, 480)), - 496 -> Seq(Set(496, 494, 491, 480)), - 497 -> Seq(Set(497, 419), Set(497, 493, 488, 486)), - 498 -> Seq(Set(498, 495, 489, 487)), - 499 -> Seq(Set(499, 494, 493, 488)), - 500 -> Seq(Set(500, 499, 494, 490)), - 501 -> Seq(Set(501, 499, 497, 496)), - 502 -> Seq(Set(502, 498, 497, 494)), - 503 -> Seq(Set(503, 500), Set(503, 502, 501, 500)), - 504 -> Seq(Set(504, 502, 490, 483)), - 505 -> Seq(Set(505, 349), Set(505, 500, 497, 493)), - 506 -> Seq(Set(506, 411), Set(506, 501, 494, 491)), - 507 -> Seq(Set(507, 504, 501, 494)), - 508 -> Seq(Set(508, 399), Set(508, 505, 500, 495)), - 509 -> Seq(Set(509, 506, 502, 501)), - 510 -> Seq(Set(510, 501, 500, 498)), - 511 -> Seq(Set(511, 501), Set(511, 509, 503, 501)), - 512 -> Seq(Set(512, 510, 507, 504)), - 513 -> Seq(Set(513, 428), Set(513, 505, 503, 500)), - 514 -> Seq(Set(514, 511, 509, 507)), - 515 -> Seq(Set(515, 511, 508, 501)), - 516 -> Seq(Set(516, 514, 511, 509)), - 517 -> Seq(Set(517, 515, 507, 505)), - 518 -> Seq(Set(518, 485), Set(518, 516, 515, 507)), - 519 -> Seq(Set(519, 440), Set(519, 517, 511, 507)), - 520 -> Seq(Set(520, 509, 507, 503)), - 521 -> Seq(Set(521, 489), Set(521, 519, 514, 512)), - 522 -> Seq(Set(522, 518, 509, 507)), - 523 -> Seq(Set(523, 521, 517, 510)), - 524 -> Seq(Set(524, 357), Set(524, 523, 519, 515)), - 525 -> Seq(Set(525, 524, 521, 519)), - 526 -> Seq(Set(526, 525, 521, 517)), - 527 -> Seq(Set(527, 480), Set(527, 526, 520, 518)), - 528 -> Seq(Set(528, 526, 522, 517)), - 529 -> Seq(Set(529, 487), Set(529, 528, 525, 522)), - 530 -> Seq(Set(530, 527, 523, 520)), - 531 -> Seq(Set(531, 529, 525, 519)), - 532 -> Seq(Set(532, 531), Set(532, 529, 528, 522)), - 533 -> Seq(Set(533, 531, 530, 529)), - 534 -> Seq(Set(534, 533, 529, 527)), - 535 -> Seq(Set(535, 533, 529, 527)), - 536 -> Seq(Set(536, 533, 531, 529)), - 537 -> Seq(Set(537, 443), Set(537, 536, 535, 527)), - 538 -> Seq(Set(538, 537, 536, 533)), - 539 -> Seq(Set(539, 535, 534, 529)), - 540 -> Seq(Set(540, 361), Set(540, 537, 534, 529)), - 541 -> Seq(Set(541, 537, 531, 528)), - 542 -> Seq(Set(542, 540, 539, 533)), - 543 -> Seq(Set(543, 527), Set(543, 538, 536, 532)), - 544 -> Seq(Set(544, 538, 535, 531)), - 545 -> Seq(Set(545, 423), Set(545, 539, 537, 532)), - 546 -> Seq(Set(546, 545, 544, 538)), - 547 -> Seq(Set(547, 543, 540, 534)), - 548 -> Seq(Set(548, 545, 543, 538)), - 549 -> Seq(Set(549, 546, 545, 533)), - 550 -> Seq(Set(550, 357), Set(550, 546, 533, 529)), - 551 -> Seq(Set(551, 416), Set(551, 550, 547, 542)), - 552 -> Seq(Set(552, 550, 547, 532)), - 553 -> Seq(Set(553, 514), Set(553, 550, 549, 542)), - 554 -> Seq(Set(554, 551, 546, 543)), - 555 -> Seq(Set(555, 551, 546, 545)), - 556 -> Seq(Set(556, 403), Set(556, 549, 546, 540)), - 557 -> Seq(Set(557, 552, 551, 550)), - 558 -> Seq(Set(558, 553, 549, 544)), - 559 -> Seq(Set(559, 525), Set(559, 557, 552, 550)), - 560 -> Seq(Set(560, 554, 551, 549)), - 561 -> Seq(Set(561, 490), Set(561, 558, 552, 550)), - 562 -> Seq(Set(562, 560, 558, 551)), - 563 -> Seq(Set(563, 561, 554, 549)), - 564 -> Seq(Set(564, 401), Set(564, 563, 561, 558)), - 565 -> Seq(Set(565, 564, 559, 554)), - 566 -> Seq(Set(566, 413), Set(566, 564, 561, 560)), - 567 -> Seq(Set(567, 424), Set(567, 563, 557, 556)), - 568 -> Seq(Set(568, 558, 557, 551)), - 569 -> Seq(Set(569, 492), Set(569, 568, 559, 557)), - 570 -> Seq(Set(570, 503), Set(570, 563, 558, 552)), - 571 -> Seq(Set(571, 569, 566, 561)), - 572 -> Seq(Set(572, 571, 564, 560)), - 573 -> Seq(Set(573, 569, 567, 563)), - 574 -> Seq(Set(574, 561), Set(574, 569, 565, 560)), - 575 -> Seq(Set(575, 429), Set(575, 572, 570, 569)), - 576 -> Seq(Set(576, 573, 572, 563)), - 577 -> Seq(Set(577, 552), Set(577, 575, 574, 569)), - 578 -> Seq(Set(578, 562, 556, 555)), - 579 -> Seq(Set(579, 572, 570, 567)), - 580 -> Seq(Set(580, 579, 576, 574)), - 581 -> Seq(Set(581, 575, 574, 568)), - 582 -> Seq(Set(582, 497), Set(582, 579, 576, 571)), - 583 -> Seq(Set(583, 453), Set(583, 581, 577, 575)), - 584 -> Seq(Set(584, 581, 571, 570)), - 585 -> Seq(Set(585, 464), Set(585, 583, 582, 577)), - 586 -> Seq(Set(586, 584, 581, 579)), - 587 -> Seq(Set(587, 586, 581, 576)), - 588 -> Seq(Set(588, 437), Set(588, 577, 572, 571)), - 589 -> Seq(Set(589, 586, 585, 579)), - 590 -> Seq(Set(590, 497), Set(590, 588, 587, 578)), - 591 -> Seq(Set(591, 587, 585, 582)), - 592 -> Seq(Set(592, 591, 573, 568)), - 593 -> Seq(Set(593, 507), Set(593, 588, 585, 584)), - 594 -> Seq(Set(594, 575), Set(594, 586, 584, 583)), - 595 -> Seq(Set(595, 594, 593, 586)), - 596 -> Seq(Set(596, 592, 591, 590)), - 597 -> Seq(Set(597, 588, 585, 583)), - 598 -> Seq(Set(598, 597, 592, 591)), - 599 -> Seq(Set(599, 569), Set(599, 593, 591, 590)), - 600 -> Seq(Set(600, 599, 590, 589)), - 601 -> Seq(Set(601, 400), Set(601, 600, 597, 589)), - 602 -> Seq(Set(602, 596, 594, 591)), - 603 -> Seq(Set(603, 600, 599, 597)), - 604 -> Seq(Set(604, 600, 598, 589)), - 605 -> Seq(Set(605, 600, 598, 595)), - 606 -> Seq(Set(606, 602, 599, 591)), - 607 -> Seq(Set(607, 502), Set(607, 600, 598, 595)), - 608 -> Seq(Set(608, 606, 602, 585)), - 609 -> Seq(Set(609, 578), Set(609, 601, 600, 597)), - 610 -> Seq(Set(610, 483), Set(610, 602, 600, 599)), - 611 -> Seq(Set(611, 609, 607, 601)), - 612 -> Seq(Set(612, 607, 602, 598)), - 613 -> Seq(Set(613, 609, 603, 594)), - 614 -> Seq(Set(614, 613, 612, 607)), - 615 -> Seq(Set(615, 404), Set(615, 614, 609, 608)), - 616 -> Seq(Set(616, 614, 602, 597)), - 617 -> Seq(Set(617, 417), Set(617, 612, 608, 607)), - 618 -> Seq(Set(618, 615, 604, 598)), - 619 -> Seq(Set(619, 614, 611, 610)), - 620 -> Seq(Set(620, 619, 618, 611)), - 621 -> Seq(Set(621, 616, 615, 609)), - 622 -> Seq(Set(622, 325), Set(622, 612, 610, 605)), - 623 -> Seq(Set(623, 555), Set(623, 614, 613, 612)), - 624 -> Seq(Set(624, 617, 615, 612)), - 625 -> Seq(Set(625, 492), Set(625, 620, 617, 613)), - 626 -> Seq(Set(626, 623, 621, 613)), - 627 -> Seq(Set(627, 622, 617, 613)), - 628 -> Seq(Set(628, 405), Set(628, 626, 617, 616)), - 629 -> Seq(Set(629, 627, 624, 623)), - 630 -> Seq(Set(630, 628, 626, 623)), - 631 -> Seq(Set(631, 324), Set(631, 625, 623, 617)), - 632 -> Seq(Set(632, 629, 619, 613)), - 633 -> Seq(Set(633, 532), Set(633, 632, 631, 626)), - 634 -> Seq(Set(634, 319), Set(634, 631, 629, 627)), - 635 -> Seq(Set(635, 631, 625, 621)), - 636 -> Seq(Set(636, 632, 628, 623)), - 637 -> Seq(Set(637, 636, 628, 623)), - 638 -> Seq(Set(638, 637, 633, 632)), - 639 -> Seq(Set(639, 623), Set(639, 636, 635, 629)), - 640 -> Seq(Set(640, 638, 637, 626)), - 641 -> Seq(Set(641, 630), Set(641, 640, 636, 622)), - 642 -> Seq(Set(642, 523), Set(642, 636, 633, 632)), - 643 -> Seq(Set(643, 641, 640, 632)), - 644 -> Seq(Set(644, 634, 633, 632)), - 645 -> Seq(Set(645, 641, 637, 634)), - 646 -> Seq(Set(646, 397), Set(646, 635, 634, 633)), - 647 -> Seq(Set(647, 642), Set(647, 646, 643, 642)), - 648 -> Seq(Set(648, 647, 626, 625)), - 649 -> Seq(Set(649, 612), Set(649, 648, 644, 638)), - 650 -> Seq(Set(650, 647), Set(650, 644, 635, 632)), - 651 -> Seq(Set(651, 646, 638, 637)), - 652 -> Seq(Set(652, 559), Set(652, 647, 643, 641)), - 653 -> Seq(Set(653, 646, 645, 643)), - 654 -> Seq(Set(654, 649, 643, 640)), - 655 -> Seq(Set(655, 567), Set(655, 653, 639, 638)), - 656 -> Seq(Set(656, 646, 638, 637)), - 657 -> Seq(Set(657, 619), Set(657, 656, 650, 649)), - 658 -> Seq(Set(658, 603), Set(658, 651, 648, 646)), - 659 -> Seq(Set(659, 657, 655, 644)), - 660 -> Seq(Set(660, 657, 656, 648)), - 661 -> Seq(Set(661, 657, 650, 649)), - 662 -> Seq(Set(662, 365), Set(662, 659, 656, 650)), - 663 -> Seq(Set(663, 406), Set(663, 655, 652, 649)), - 664 -> Seq(Set(664, 662, 660, 649)), - 665 -> Seq(Set(665, 632), Set(665, 661, 659, 654)), - 666 -> Seq(Set(666, 664, 659, 656)), - 667 -> Seq(Set(667, 664, 660, 649)), - 668 -> Seq(Set(668, 658, 656, 651)), - 669 -> Seq(Set(669, 667, 665, 664)), - 670 -> Seq(Set(670, 517), Set(670, 669, 665, 664)), - 671 -> Seq(Set(671, 656), Set(671, 669, 665, 662)), - 672 -> Seq(Set(672, 667, 666, 661)), - 673 -> Seq(Set(673, 645), Set(673, 666, 664, 663)), - 674 -> Seq(Set(674, 671, 665, 660)), - 675 -> Seq(Set(675, 674, 672, 669)), - 676 -> Seq(Set(676, 435), Set(676, 675, 671, 664)), - 677 -> Seq(Set(677, 674, 673, 669)), - 678 -> Seq(Set(678, 675, 673, 663)), - 679 -> Seq(Set(679, 613), Set(679, 676, 667, 661)), - 680 -> Seq(Set(680, 679, 650, 645)), - 681 -> Seq(Set(681, 678, 672, 670)), - 682 -> Seq(Set(682, 681, 679, 675)), - 683 -> Seq(Set(683, 682, 677, 672)), - 684 -> Seq(Set(684, 681, 671, 666)), - 685 -> Seq(Set(685, 684, 682, 681)), - 686 -> Seq(Set(686, 489), Set(686, 684, 674, 673)), - 687 -> Seq(Set(687, 674), Set(687, 682, 675, 673)), - 688 -> Seq(Set(688, 682, 674, 669)), - 689 -> Seq(Set(689, 675), Set(689, 686, 683, 681)), - 690 -> Seq(Set(690, 687, 683, 680)), - 691 -> Seq(Set(691, 689, 685, 678)), - 692 -> Seq(Set(692, 393), Set(692, 687, 686, 678)), - 693 -> Seq(Set(693, 691, 685, 678)), - 694 -> Seq(Set(694, 691, 681, 677)), - 695 -> Seq(Set(695, 483), Set(695, 694, 691, 686)), - 696 -> Seq(Set(696, 694, 686, 673)), - 697 -> Seq(Set(697, 430), Set(697, 689, 685, 681)), - 698 -> Seq(Set(698, 483), Set(698, 690, 689, 688)), - 699 -> Seq(Set(699, 698, 689, 684)), - 700 -> Seq(Set(700, 698, 695, 694)), - 701 -> Seq(Set(701, 699, 697, 685)), - 702 -> Seq(Set(702, 665), Set(702, 701, 699, 695)), - 703 -> Seq(Set(703, 702, 696, 691)), - 704 -> Seq(Set(704, 701, 699, 692)), - 705 -> Seq(Set(705, 686), Set(705, 704, 698, 697)), - 706 -> Seq(Set(706, 697, 695, 692)), - 707 -> Seq(Set(707, 702, 699, 692)), - 708 -> Seq(Set(708, 421), Set(708, 706, 704, 703)), - 709 -> Seq(Set(709, 708, 706, 705)), - 710 -> Seq(Set(710, 709, 696, 695)), - 711 -> Seq(Set(711, 619), Set(711, 704, 703, 700)), - 712 -> Seq(Set(712, 709, 708, 707)), - 713 -> Seq(Set(713, 672), Set(713, 706, 703, 696)), - 714 -> Seq(Set(714, 691), Set(714, 709, 707, 701)), - 715 -> Seq(Set(715, 714, 711, 708)), - 716 -> Seq(Set(716, 533), Set(716, 706, 705, 704)), - 717 -> Seq(Set(717, 716, 710, 701)), - 718 -> Seq(Set(718, 717, 716, 713)), - 719 -> Seq(Set(719, 569), Set(719, 711, 710, 707)), - 720 -> Seq(Set(720, 718, 712, 709)), - 721 -> Seq(Set(721, 712), Set(721, 720, 713, 712)), - 722 -> Seq(Set(722, 491), Set(722, 721, 718, 707)), - 723 -> Seq(Set(723, 717, 710, 707)), - 724 -> Seq(Set(724, 719, 716, 711)), - 725 -> Seq(Set(725, 720, 719, 716), Set(758)), - 726 -> Seq(Set(726, 721), Set(726, 725, 722, 721)), - 727 -> Seq(Set(727, 547), Set(727, 721, 719, 716)), - 728 -> Seq(Set(728, 726, 725, 724), Set(761)), - 729 -> Seq(Set(729, 671), Set(729, 726, 724, 718)), - 730 -> Seq(Set(730, 583), Set(730, 726, 715, 711)), - 731 -> Seq(Set(731, 729, 725, 723), Set(764)), - 732 -> Seq(Set(732, 729, 728, 725), Set(765)), - 733 -> Seq(Set(733, 731, 726, 725), Set(766)), - 734 -> Seq(Set(734, 724, 721, 720), Set(767)), - 735 -> Seq(Set(735, 691), Set(735, 733, 728, 727)), - 736 -> Seq(Set(736, 730, 728, 723), Set(769)), - 737 -> Seq(Set(737, 732), Set(737, 736, 733, 732)), - 738 -> Seq(Set(738, 391), Set(738, 730, 729, 727)), - 739 -> Seq(Set(739, 731, 723, 721), Set(772)), - 740 -> Seq(Set(740, 587), Set(740, 737, 728, 716)), - 741 -> Seq(Set(741, 738, 733, 732), Set(774)), - 742 -> Seq(Set(742, 741, 738, 730), Set(775)), - 743 -> Seq(Set(743, 653), Set(743, 742, 731, 730)), - 744 -> Seq(Set(744, 743, 733, 731), Set(777)), - 745 -> Seq(Set(745, 487), Set(745, 740, 738, 737)), - 746 -> Seq(Set(746, 395), Set(746, 738, 733, 728)), - 747 -> Seq(Set(747, 743, 741, 737), Set(780)), - 748 -> Seq(Set(748, 744, 743, 733), Set(781)), - 749 -> Seq(Set(749, 748, 743, 742), Set(782)), - 750 -> Seq(Set(750, 746, 741, 734), Set(783)), - 751 -> Seq(Set(751, 733), Set(751, 750, 748, 740)), - 752 -> Seq(Set(752, 749, 732, 731), Set(785)), - 753 -> Seq(Set(753, 595), Set(753, 748, 745, 740)), - 754 -> Seq(Set(754, 735), Set(754, 742, 740, 735)), - 755 -> Seq(Set(755, 754, 745, 743), Set(2048)), - 756 -> Seq(Set(756, 407), Set(756, 755, 747, 740)), - 757 -> Seq(Set(757, 756, 751, 750)), - 758 -> Seq(Set(758, 757, 746, 741)), - 759 -> Seq(Set(759, 661), Set(759, 757, 756, 750)), - 760 -> Seq(Set(760, 757, 747, 734)), - 761 -> Seq(Set(761, 758), Set(761, 760, 759, 758)), - 762 -> Seq(Set(762, 679), Set(762, 761, 755, 745)), - 763 -> Seq(Set(763, 754, 749, 747)), - 764 -> Seq(Set(764, 761, 759, 758)), - 765 -> Seq(Set(765, 760, 755, 754)), - 766 -> Seq(Set(766, 757, 747, 744)), - 767 -> Seq(Set(767, 599), Set(767, 763, 760, 759)), - 768 -> Seq(Set(768, 764, 751, 749)), - 769 -> Seq(Set(769, 649), Set(769, 763, 762, 760)), - 770 -> Seq(Set(770, 768, 765, 756)), - 771 -> Seq(Set(771, 765, 756, 754)), - 772 -> Seq(Set(772, 765), Set(772, 767, 766, 764)), - 773 -> Seq(Set(773, 767, 765, 763)), - 774 -> Seq(Set(774, 589), Set(774, 767, 760, 758)), - 775 -> Seq(Set(775, 408), Set(775, 771, 769, 768)), - 776 -> Seq(Set(776, 773, 764, 759)), - 777 -> Seq(Set(777, 748), Set(777, 776, 767, 761)), - 778 -> Seq(Set(778, 403), Set(778, 775, 762, 759)), - 779 -> Seq(Set(779, 776, 771, 769)), - 780 -> Seq(Set(780, 775, 772, 764)), - 781 -> Seq(Set(781, 779, 765, 764)), - 782 -> Seq(Set(782, 453), Set(782, 780, 779, 773)), - 783 -> Seq(Set(783, 715), Set(783, 782, 776, 773)), - 784 -> Seq(Set(784, 778, 775, 771)), - 785 -> Seq(Set(785, 693), Set(785, 780, 776, 775)), - 786 -> Seq(Set(786, 782, 780, 771)), + 395 -> Seq(Set(395, 390, 389, 384)), + 396 -> Seq(Set(396, 371), Set(396, 392, 390, 389)), + 397 -> Seq(Set(397, 392, 387, 385)), + 398 -> Seq(Set(398, 393, 392, 384)), + 399 -> Seq(Set(399, 313), Set(399, 397, 390, 388)), + 400 -> Seq(Set(400, 398, 397, 395)), + 401 -> Seq(Set(401, 249), Set(401, 399, 392, 389)), + 402 -> Seq(Set(402, 399, 398, 393)), + 403 -> Seq(Set(403, 398, 395, 394)), + 404 -> Seq(Set(404, 215), Set(404, 400, 398, 397)), + 405 -> Seq(Set(405, 398, 397, 388)), + 406 -> Seq(Set(406, 249), Set(406, 402, 397, 393)), + 407 -> Seq(Set(407, 336), Set(407, 402, 400, 398)), + 408 -> Seq(Set(408, 407, 403, 401)), + 409 -> Seq(Set(409, 322), Set(409, 406, 404, 402)), + 410 -> Seq(Set(410, 407, 406, 400)), + 411 -> Seq(Set(411, 408, 401, 399)), + 412 -> Seq(Set(412, 265), Set(412, 409, 404, 401)), + 413 -> Seq(Set(413, 407, 406, 403)), + 414 -> Seq(Set(414, 405, 401, 398)), + 415 -> Seq(Set(415, 313), Set(415, 413, 411, 406)), + 416 -> Seq(Set(416, 414, 411, 407)), + 417 -> Seq(Set(417, 310), Set(417, 416, 414, 407)), + 418 -> Seq(Set(418, 417, 415, 403)), + 419 -> Seq(Set(419, 415, 414, 404)), + 420 -> Seq(Set(420, 412, 410, 407)), + 421 -> Seq(Set(421, 419, 417, 416)), + 422 -> Seq(Set(422, 273), Set(422, 421, 416, 412)), + 423 -> Seq(Set(423, 398), Set(423, 420, 418, 414)), + 424 -> Seq(Set(424, 422, 417, 415)), + 425 -> Seq(Set(425, 413), Set(425, 422, 421, 418)), + 426 -> Seq(Set(426, 415, 414, 412)), + 427 -> Seq(Set(427, 422, 421, 416)), + 428 -> Seq(Set(428, 323), Set(428, 426, 425, 417)), + 429 -> Seq(Set(429, 422, 421, 419)), + 430 -> Seq(Set(430, 419, 417, 415)), + 431 -> Seq(Set(431, 311), Set(431, 430, 428, 426)), + 432 -> Seq(Set(432, 429, 428, 419)), + 433 -> Seq(Set(433, 400), Set(433, 430, 428, 422)), + 434 -> Seq(Set(434, 429, 423, 422)), + 435 -> Seq(Set(435, 430, 426, 423)), + 436 -> Seq(Set(436, 271), Set(436, 432, 431, 430)), + 437 -> Seq(Set(437, 436, 435, 431)), + 438 -> Seq(Set(438, 373), Set(438, 436, 432, 421)), + 439 -> Seq(Set(439, 390), Set(439, 437, 436, 431)), + 440 -> Seq(Set(440, 439, 437, 436)), + 441 -> Seq(Set(441, 410), Set(441, 440, 433, 430)), + 442 -> Seq(Set(442, 440, 437, 435)), + 443 -> Seq(Set(443, 442, 437, 433)), + 444 -> Seq(Set(444, 435, 432, 431)), + 445 -> Seq(Set(445, 441, 439, 438)), + 446 -> Seq(Set(446, 341), Set(446, 442, 439, 431)), + 447 -> Seq(Set(447, 374), Set(447, 446, 441, 438)), + 448 -> Seq(Set(448, 444, 442, 437)), + 449 -> Seq(Set(449, 315), Set(449, 446, 440, 438)), + 450 -> Seq(Set(450, 371), Set(450, 443, 438, 434)), + 451 -> Seq(Set(451, 450, 441, 435)), + 452 -> Seq(Set(452, 448, 447, 446)), + 453 -> Seq(Set(453, 449, 447, 438)), + 454 -> Seq(Set(454, 449, 445, 444)), + 455 -> Seq(Set(455, 417), Set(455, 453, 449, 444)), + 456 -> Seq(Set(456, 454, 445, 433)), + 457 -> Seq(Set(457, 441), Set(457, 454, 449, 446)), + 458 -> Seq(Set(458, 255), Set(458, 453, 448, 445)), + 459 -> Seq(Set(459, 457, 454, 447)), + 460 -> Seq(Set(460, 399), Set(460, 459, 455, 451)), + 461 -> Seq(Set(461, 460, 455, 454)), + 462 -> Seq(Set(462, 389), Set(462, 457, 451, 450)), + 463 -> Seq(Set(463, 370), Set(463, 456, 455, 452)), + 464 -> Seq(Set(464, 460, 455, 441)), + 465 -> Seq(Set(465, 406), Set(465, 463, 462, 457)), + 466 -> Seq(Set(466, 460, 455, 452)), + 467 -> Seq(Set(467, 466, 461, 456)), + 468 -> Seq(Set(468, 464, 459, 453)), + 469 -> Seq(Set(469, 467, 464, 460)), + 470 -> Seq(Set(470, 321), Set(470, 468, 462, 461)), + 471 -> Seq(Set(471, 470), Set(471, 469, 468, 465)), + 472 -> Seq(Set(472, 470, 469, 461)), + 473 -> Seq(Set(473, 470, 467, 465)), + 474 -> Seq(Set(474, 283), Set(474, 465, 463, 456)), + 475 -> Seq(Set(475, 471, 467, 466)), + 476 -> Seq(Set(476, 461), Set(476, 475, 468, 466)), + 477 -> Seq(Set(477, 470, 462, 461)), + 478 -> Seq(Set(478, 357), Set(478, 477, 474, 472)), + 479 -> Seq(Set(479, 375), Set(479, 475, 472, 470)), + 480 -> Seq(Set(480, 473, 467, 464)), + 481 -> Seq(Set(481, 343), Set(481, 480, 472, 471)), + 482 -> Seq(Set(482, 477, 476, 473)), + 483 -> Seq(Set(483, 479, 477, 474)), + 484 -> Seq(Set(484, 379), Set(484, 483, 482, 470)), + 485 -> Seq(Set(485, 479, 469, 468)), + 486 -> Seq(Set(486, 481, 478, 472)), + 487 -> Seq(Set(487, 393), Set(487, 485, 483, 478)), + 488 -> Seq(Set(488, 487, 485, 484)), + 489 -> Seq(Set(489, 406), Set(489, 484, 483, 480)), + 490 -> Seq(Set(490, 271), Set(490, 485, 483, 481)), + 491 -> Seq(Set(491, 488, 485, 480)), + 492 -> Seq(Set(492, 491, 485, 484)), + 493 -> Seq(Set(493, 490, 488, 483)), + 494 -> Seq(Set(494, 357), Set(494, 493, 489, 481)), + 495 -> Seq(Set(495, 419), Set(495, 494, 486, 480)), + 496 -> Seq(Set(496, 494, 491, 480)), + 497 -> Seq(Set(497, 419), Set(497, 493, 488, 486)), + 498 -> Seq(Set(498, 495, 489, 487)), + 499 -> Seq(Set(499, 494, 493, 488)), + 500 -> Seq(Set(500, 499, 494, 490)), + 501 -> Seq(Set(501, 499, 497, 496)), + 502 -> Seq(Set(502, 498, 497, 494)), + 503 -> Seq(Set(503, 500), Set(503, 502, 501, 500)), + 504 -> Seq(Set(504, 502, 490, 483)), + 505 -> Seq(Set(505, 349), Set(505, 500, 497, 493)), + 506 -> Seq(Set(506, 411), Set(506, 501, 494, 491)), + 507 -> Seq(Set(507, 504, 501, 494)), + 508 -> Seq(Set(508, 399), Set(508, 505, 500, 495)), + 509 -> Seq(Set(509, 506, 502, 501)), + 510 -> Seq(Set(510, 501, 500, 498)), + 511 -> Seq(Set(511, 501), Set(511, 509, 503, 501)), + 512 -> Seq(Set(512, 510, 507, 504)), + 513 -> Seq(Set(513, 428), Set(513, 505, 503, 500)), + 514 -> Seq(Set(514, 511, 509, 507)), + 515 -> Seq(Set(515, 511, 508, 501)), + 516 -> Seq(Set(516, 514, 511, 509)), + 517 -> Seq(Set(517, 515, 507, 505)), + 518 -> Seq(Set(518, 485), Set(518, 516, 515, 507)), + 519 -> Seq(Set(519, 440), Set(519, 517, 511, 507)), + 520 -> Seq(Set(520, 509, 507, 503)), + 521 -> Seq(Set(521, 489), Set(521, 519, 514, 512)), + 522 -> Seq(Set(522, 518, 509, 507)), + 523 -> Seq(Set(523, 521, 517, 510)), + 524 -> Seq(Set(524, 357), Set(524, 523, 519, 515)), + 525 -> Seq(Set(525, 524, 521, 519)), + 526 -> Seq(Set(526, 525, 521, 517)), + 527 -> Seq(Set(527, 480), Set(527, 526, 520, 518)), + 528 -> Seq(Set(528, 526, 522, 517)), + 529 -> Seq(Set(529, 487), Set(529, 528, 525, 522)), + 530 -> Seq(Set(530, 527, 523, 520)), + 531 -> Seq(Set(531, 529, 525, 519)), + 532 -> Seq(Set(532, 531), Set(532, 529, 528, 522)), + 533 -> Seq(Set(533, 531, 530, 529)), + 534 -> Seq(Set(534, 533, 529, 527)), + 535 -> Seq(Set(535, 533, 529, 527)), + 536 -> Seq(Set(536, 533, 531, 529)), + 537 -> Seq(Set(537, 443), Set(537, 536, 535, 527)), + 538 -> Seq(Set(538, 537, 536, 533)), + 539 -> Seq(Set(539, 535, 534, 529)), + 540 -> Seq(Set(540, 361), Set(540, 537, 534, 529)), + 541 -> Seq(Set(541, 537, 531, 528)), + 542 -> Seq(Set(542, 540, 539, 533)), + 543 -> Seq(Set(543, 527), Set(543, 538, 536, 532)), + 544 -> Seq(Set(544, 538, 535, 531)), + 545 -> Seq(Set(545, 423), Set(545, 539, 537, 532)), + 546 -> Seq(Set(546, 545, 544, 538)), + 547 -> Seq(Set(547, 543, 540, 534)), + 548 -> Seq(Set(548, 545, 543, 538)), + 549 -> Seq(Set(549, 546, 545, 533)), + 550 -> Seq(Set(550, 357), Set(550, 546, 533, 529)), + 551 -> Seq(Set(551, 416), Set(551, 550, 547, 542)), + 552 -> Seq(Set(552, 550, 547, 532)), + 553 -> Seq(Set(553, 514), Set(553, 550, 549, 542)), + 554 -> Seq(Set(554, 551, 546, 543)), + 555 -> Seq(Set(555, 551, 546, 545)), + 556 -> Seq(Set(556, 403), Set(556, 549, 546, 540)), + 557 -> Seq(Set(557, 552, 551, 550)), + 558 -> Seq(Set(558, 553, 549, 544)), + 559 -> Seq(Set(559, 525), Set(559, 557, 552, 550)), + 560 -> Seq(Set(560, 554, 551, 549)), + 561 -> Seq(Set(561, 490), Set(561, 558, 552, 550)), + 562 -> Seq(Set(562, 560, 558, 551)), + 563 -> Seq(Set(563, 561, 554, 549)), + 564 -> Seq(Set(564, 401), Set(564, 563, 561, 558)), + 565 -> Seq(Set(565, 564, 559, 554)), + 566 -> Seq(Set(566, 413), Set(566, 564, 561, 560)), + 567 -> Seq(Set(567, 424), Set(567, 563, 557, 556)), + 568 -> Seq(Set(568, 558, 557, 551)), + 569 -> Seq(Set(569, 492), Set(569, 568, 559, 557)), + 570 -> Seq(Set(570, 503), Set(570, 563, 558, 552)), + 571 -> Seq(Set(571, 569, 566, 561)), + 572 -> Seq(Set(572, 571, 564, 560)), + 573 -> Seq(Set(573, 569, 567, 563)), + 574 -> Seq(Set(574, 561), Set(574, 569, 565, 560)), + 575 -> Seq(Set(575, 429), Set(575, 572, 570, 569)), + 576 -> Seq(Set(576, 573, 572, 563)), + 577 -> Seq(Set(577, 552), Set(577, 575, 574, 569)), + 578 -> Seq(Set(578, 562, 556, 555)), + 579 -> Seq(Set(579, 572, 570, 567)), + 580 -> Seq(Set(580, 579, 576, 574)), + 581 -> Seq(Set(581, 575, 574, 568)), + 582 -> Seq(Set(582, 497), Set(582, 579, 576, 571)), + 583 -> Seq(Set(583, 453), Set(583, 581, 577, 575)), + 584 -> Seq(Set(584, 581, 571, 570)), + 585 -> Seq(Set(585, 464), Set(585, 583, 582, 577)), + 586 -> Seq(Set(586, 584, 581, 579)), + 587 -> Seq(Set(587, 586, 581, 576)), + 588 -> Seq(Set(588, 437), Set(588, 577, 572, 571)), + 589 -> Seq(Set(589, 586, 585, 579)), + 590 -> Seq(Set(590, 497), Set(590, 588, 587, 578)), + 591 -> Seq(Set(591, 587, 585, 582)), + 592 -> Seq(Set(592, 591, 573, 568)), + 593 -> Seq(Set(593, 507), Set(593, 588, 585, 584)), + 594 -> Seq(Set(594, 575), Set(594, 586, 584, 583)), + 595 -> Seq(Set(595, 594, 593, 586)), + 596 -> Seq(Set(596, 592, 591, 590)), + 597 -> Seq(Set(597, 588, 585, 583)), + 598 -> Seq(Set(598, 597, 592, 591)), + 599 -> Seq(Set(599, 569), Set(599, 593, 591, 590)), + 600 -> Seq(Set(600, 599, 590, 589)), + 601 -> Seq(Set(601, 400), Set(601, 600, 597, 589)), + 602 -> Seq(Set(602, 596, 594, 591)), + 603 -> Seq(Set(603, 600, 599, 597)), + 604 -> Seq(Set(604, 600, 598, 589)), + 605 -> Seq(Set(605, 600, 598, 595)), + 606 -> Seq(Set(606, 602, 599, 591)), + 607 -> Seq(Set(607, 502), Set(607, 600, 598, 595)), + 608 -> Seq(Set(608, 606, 602, 585)), + 609 -> Seq(Set(609, 578), Set(609, 601, 600, 597)), + 610 -> Seq(Set(610, 483), Set(610, 602, 600, 599)), + 611 -> Seq(Set(611, 609, 607, 601)), + 612 -> Seq(Set(612, 607, 602, 598)), + 613 -> Seq(Set(613, 609, 603, 594)), + 614 -> Seq(Set(614, 613, 612, 607)), + 615 -> Seq(Set(615, 404), Set(615, 614, 609, 608)), + 616 -> Seq(Set(616, 614, 602, 597)), + 617 -> Seq(Set(617, 417), Set(617, 612, 608, 607)), + 618 -> Seq(Set(618, 615, 604, 598)), + 619 -> Seq(Set(619, 614, 611, 610)), + 620 -> Seq(Set(620, 619, 618, 611)), + 621 -> Seq(Set(621, 616, 615, 609)), + 622 -> Seq(Set(622, 325), Set(622, 612, 610, 605)), + 623 -> Seq(Set(623, 555), Set(623, 614, 613, 612)), + 624 -> Seq(Set(624, 617, 615, 612)), + 625 -> Seq(Set(625, 492), Set(625, 620, 617, 613)), + 626 -> Seq(Set(626, 623, 621, 613)), + 627 -> Seq(Set(627, 622, 617, 613)), + 628 -> Seq(Set(628, 405), Set(628, 626, 617, 616)), + 629 -> Seq(Set(629, 627, 624, 623)), + 630 -> Seq(Set(630, 628, 626, 623)), + 631 -> Seq(Set(631, 324), Set(631, 625, 623, 617)), + 632 -> Seq(Set(632, 629, 619, 613)), + 633 -> Seq(Set(633, 532), Set(633, 632, 631, 626)), + 634 -> Seq(Set(634, 319), Set(634, 631, 629, 627)), + 635 -> Seq(Set(635, 631, 625, 621)), + 636 -> Seq(Set(636, 632, 628, 623)), + 637 -> Seq(Set(637, 636, 628, 623)), + 638 -> Seq(Set(638, 637, 633, 632)), + 639 -> Seq(Set(639, 623), Set(639, 636, 635, 629)), + 640 -> Seq(Set(640, 638, 637, 626)), + 641 -> Seq(Set(641, 630), Set(641, 640, 636, 622)), + 642 -> Seq(Set(642, 523), Set(642, 636, 633, 632)), + 643 -> Seq(Set(643, 641, 640, 632)), + 644 -> Seq(Set(644, 634, 633, 632)), + 645 -> Seq(Set(645, 641, 637, 634)), + 646 -> Seq(Set(646, 397), Set(646, 635, 634, 633)), + 647 -> Seq(Set(647, 642), Set(647, 646, 643, 642)), + 648 -> Seq(Set(648, 647, 626, 625)), + 649 -> Seq(Set(649, 612), Set(649, 648, 644, 638)), + 650 -> Seq(Set(650, 647), Set(650, 644, 635, 632)), + 651 -> Seq(Set(651, 646, 638, 637)), + 652 -> Seq(Set(652, 559), Set(652, 647, 643, 641)), + 653 -> Seq(Set(653, 646, 645, 643)), + 654 -> Seq(Set(654, 649, 643, 640)), + 655 -> Seq(Set(655, 567), Set(655, 653, 639, 638)), + 656 -> Seq(Set(656, 646, 638, 637)), + 657 -> Seq(Set(657, 619), Set(657, 656, 650, 649)), + 658 -> Seq(Set(658, 603), Set(658, 651, 648, 646)), + 659 -> Seq(Set(659, 657, 655, 644)), + 660 -> Seq(Set(660, 657, 656, 648)), + 661 -> Seq(Set(661, 657, 650, 649)), + 662 -> Seq(Set(662, 365), Set(662, 659, 656, 650)), + 663 -> Seq(Set(663, 406), Set(663, 655, 652, 649)), + 664 -> Seq(Set(664, 662, 660, 649)), + 665 -> Seq(Set(665, 632), Set(665, 661, 659, 654)), + 666 -> Seq(Set(666, 664, 659, 656)), + 667 -> Seq(Set(667, 664, 660, 649)), + 668 -> Seq(Set(668, 658, 656, 651)), + 669 -> Seq(Set(669, 667, 665, 664)), + 670 -> Seq(Set(670, 517), Set(670, 669, 665, 664)), + 671 -> Seq(Set(671, 656), Set(671, 669, 665, 662)), + 672 -> Seq(Set(672, 667, 666, 661)), + 673 -> Seq(Set(673, 645), Set(673, 666, 664, 663)), + 674 -> Seq(Set(674, 671, 665, 660)), + 675 -> Seq(Set(675, 674, 672, 669)), + 676 -> Seq(Set(676, 435), Set(676, 675, 671, 664)), + 677 -> Seq(Set(677, 674, 673, 669)), + 678 -> Seq(Set(678, 675, 673, 663)), + 679 -> Seq(Set(679, 613), Set(679, 676, 667, 661)), + 680 -> Seq(Set(680, 679, 650, 645)), + 681 -> Seq(Set(681, 678, 672, 670)), + 682 -> Seq(Set(682, 681, 679, 675)), + 683 -> Seq(Set(683, 682, 677, 672)), + 684 -> Seq(Set(684, 681, 671, 666)), + 685 -> Seq(Set(685, 684, 682, 681)), + 686 -> Seq(Set(686, 489), Set(686, 684, 674, 673)), + 687 -> Seq(Set(687, 674), Set(687, 682, 675, 673)), + 688 -> Seq(Set(688, 682, 674, 669)), + 689 -> Seq(Set(689, 675), Set(689, 686, 683, 681)), + 690 -> Seq(Set(690, 687, 683, 680)), + 691 -> Seq(Set(691, 689, 685, 678)), + 692 -> Seq(Set(692, 393), Set(692, 687, 686, 678)), + 693 -> Seq(Set(693, 691, 685, 678)), + 694 -> Seq(Set(694, 691, 681, 677)), + 695 -> Seq(Set(695, 483), Set(695, 694, 691, 686)), + 696 -> Seq(Set(696, 694, 686, 673)), + 697 -> Seq(Set(697, 430), Set(697, 689, 685, 681)), + 698 -> Seq(Set(698, 483), Set(698, 690, 689, 688)), + 699 -> Seq(Set(699, 698, 689, 684)), + 700 -> Seq(Set(700, 698, 695, 694)), + 701 -> Seq(Set(701, 699, 697, 685)), + 702 -> Seq(Set(702, 665), Set(702, 701, 699, 695)), + 703 -> Seq(Set(703, 702, 696, 691)), + 704 -> Seq(Set(704, 701, 699, 692)), + 705 -> Seq(Set(705, 686), Set(705, 704, 698, 697)), + 706 -> Seq(Set(706, 697, 695, 692)), + 707 -> Seq(Set(707, 702, 699, 692)), + 708 -> Seq(Set(708, 421), Set(708, 706, 704, 703)), + 709 -> Seq(Set(709, 708, 706, 705)), + 710 -> Seq(Set(710, 709, 696, 695)), + 711 -> Seq(Set(711, 619), Set(711, 704, 703, 700)), + 712 -> Seq(Set(712, 709, 708, 707)), + 713 -> Seq(Set(713, 672), Set(713, 706, 703, 696)), + 714 -> Seq(Set(714, 691), Set(714, 709, 707, 701)), + 715 -> Seq(Set(715, 714, 711, 708)), + 716 -> Seq(Set(716, 533), Set(716, 706, 705, 704)), + 717 -> Seq(Set(717, 716, 710, 701)), + 718 -> Seq(Set(718, 717, 716, 713)), + 719 -> Seq(Set(719, 569), Set(719, 711, 710, 707)), + 720 -> Seq(Set(720, 718, 712, 709)), + 721 -> Seq(Set(721, 712), Set(721, 720, 713, 712)), + 722 -> Seq(Set(722, 491), Set(722, 721, 718, 707)), + 723 -> Seq(Set(723, 717, 710, 707)), + 724 -> Seq(Set(724, 719, 716, 711)), + 725 -> Seq(Set(725, 720, 719, 716), Set(758)), + 726 -> Seq(Set(726, 721), Set(726, 725, 722, 721)), + 727 -> Seq(Set(727, 547), Set(727, 721, 719, 716)), + 728 -> Seq(Set(728, 726, 725, 724), Set(761)), + 729 -> Seq(Set(729, 671), Set(729, 726, 724, 718)), + 730 -> Seq(Set(730, 583), Set(730, 726, 715, 711)), + 731 -> Seq(Set(731, 729, 725, 723), Set(764)), + 732 -> Seq(Set(732, 729, 728, 725), Set(765)), + 733 -> Seq(Set(733, 731, 726, 725), Set(766)), + 734 -> Seq(Set(734, 724, 721, 720), Set(767)), + 735 -> Seq(Set(735, 691), Set(735, 733, 728, 727)), + 736 -> Seq(Set(736, 730, 728, 723), Set(769)), + 737 -> Seq(Set(737, 732), Set(737, 736, 733, 732)), + 738 -> Seq(Set(738, 391), Set(738, 730, 729, 727)), + 739 -> Seq(Set(739, 731, 723, 721), Set(772)), + 740 -> Seq(Set(740, 587), Set(740, 737, 728, 716)), + 741 -> Seq(Set(741, 738, 733, 732), Set(774)), + 742 -> Seq(Set(742, 741, 738, 730), Set(775)), + 743 -> Seq(Set(743, 653), Set(743, 742, 731, 730)), + 744 -> Seq(Set(744, 743, 733, 731), Set(777)), + 745 -> Seq(Set(745, 487), Set(745, 740, 738, 737)), + 746 -> Seq(Set(746, 395), Set(746, 738, 733, 728)), + 747 -> Seq(Set(747, 743, 741, 737), Set(780)), + 748 -> Seq(Set(748, 744, 743, 733), Set(781)), + 749 -> Seq(Set(749, 748, 743, 742), Set(782)), + 750 -> Seq(Set(750, 746, 741, 734), Set(783)), + 751 -> Seq(Set(751, 733), Set(751, 750, 748, 740)), + 752 -> Seq(Set(752, 749, 732, 731), Set(785)), + 753 -> Seq(Set(753, 595), Set(753, 748, 745, 740)), + 754 -> Seq(Set(754, 735), Set(754, 742, 740, 735)), + 755 -> Seq(Set(755, 754, 745, 743), Set(2048)), + 756 -> Seq(Set(756, 407), Set(756, 755, 747, 740)), + 757 -> Seq(Set(757, 756, 751, 750)), + 758 -> Seq(Set(758, 757, 746, 741)), + 759 -> Seq(Set(759, 661), Set(759, 757, 756, 750)), + 760 -> Seq(Set(760, 757, 747, 734)), + 761 -> Seq(Set(761, 758), Set(761, 760, 759, 758)), + 762 -> Seq(Set(762, 679), Set(762, 761, 755, 745)), + 763 -> Seq(Set(763, 754, 749, 747)), + 764 -> Seq(Set(764, 761, 759, 758)), + 765 -> Seq(Set(765, 760, 755, 754)), + 766 -> Seq(Set(766, 757, 747, 744)), + 767 -> Seq(Set(767, 599), Set(767, 763, 760, 759)), + 768 -> Seq(Set(768, 764, 751, 749)), + 769 -> Seq(Set(769, 649), Set(769, 763, 762, 760)), + 770 -> Seq(Set(770, 768, 765, 756)), + 771 -> Seq(Set(771, 765, 756, 754)), + 772 -> Seq(Set(772, 765), Set(772, 767, 766, 764)), + 773 -> Seq(Set(773, 767, 765, 763)), + 774 -> Seq(Set(774, 589), Set(774, 767, 760, 758)), + 775 -> Seq(Set(775, 408), Set(775, 771, 769, 768)), + 776 -> Seq(Set(776, 773, 764, 759)), + 777 -> Seq(Set(777, 748), Set(777, 776, 767, 761)), + 778 -> Seq(Set(778, 403), Set(778, 775, 762, 759)), + 779 -> Seq(Set(779, 776, 771, 769)), + 780 -> Seq(Set(780, 775, 772, 764)), + 781 -> Seq(Set(781, 779, 765, 764)), + 782 -> Seq(Set(782, 453), Set(782, 780, 779, 773)), + 783 -> Seq(Set(783, 715), Set(783, 782, 776, 773)), + 784 -> Seq(Set(784, 778, 775, 771)), + 785 -> Seq(Set(785, 693), Set(785, 780, 776, 775)), + 786 -> Seq(Set(786, 782, 780, 771)), 1024 -> Seq(Set(1024, 1015, 1002, 1001)), 2048 -> Seq(Set(2048, 2035, 2034, 2029)), - 4096 -> Seq(Set(4096, 4095, 4081, 4069)) ) + 4096 -> Seq(Set(4096, 4095, 4081, 4069)) + ) } diff --git a/src/main/scala/chisel3/util/random/PRNG.scala b/src/main/scala/chisel3/util/random/PRNG.scala index 3a44385a..2566c8d6 100644 --- a/src/main/scala/chisel3/util/random/PRNG.scala +++ b/src/main/scala/chisel3/util/random/PRNG.scala @@ -11,17 +11,17 @@ import chisel3.util.Valid */ class PRNGIO(val n: Int) extends Bundle { - /** A [[chisel3.util.Valid Valid]] interface that can be used to set the seed (internal PRNG state) + /** A [[chisel3.util.Valid Valid]] interface that can be used to set the seed (internal PRNG state) * @group Signals */ val seed: Valid[Vec[Bool]] = Input(Valid(Vec(n, Bool()))) - /** When asserted, the PRNG will increment by one + /** When asserted, the PRNG will increment by one * @group Signals */ val increment: Bool = Input(Bool()) - /** The current state of the PRNG + /** The current state of the PRNG * @group Signals */ val out: Vec[Bool] = Output(Vec(n, Bool())) @@ -34,7 +34,8 @@ class PRNGIO(val n: Int) extends Bundle { * @param updateSeed if true, when loading the seed the state will be updated as if the seed were the current state, if * false, the state will be set to the seed */ -abstract class PRNG(val width: Int, val seed: Option[BigInt], step: Int = 1, updateSeed: Boolean = false) extends Module { +abstract class PRNG(val width: Int, val seed: Option[BigInt], step: Int = 1, updateSeed: Boolean = false) + extends Module { require(width > 0, s"Width must be greater than zero! (Found '$width')") require(step > 0, s"Step size must be greater than one! (Found '$step')") @@ -51,7 +52,7 @@ abstract class PRNG(val width: Int, val seed: Option[BigInt], step: Int = 1, upd * the PRNG state should be manually reset to a safe value. [[LFSR]] handles this by, based on the chosen reduction * operator, either sets or resets the least significant bit of the state. */ - private [random] val state: Vec[Bool] = RegInit(resetValue) + private[random] val state: Vec[Bool] = RegInit(resetValue) /** State update function * @param s input state @@ -63,14 +64,15 @@ abstract class PRNG(val width: Int, val seed: Option[BigInt], step: Int = 1, upd * @param s input state * @return the next state after `step` applications of [[PRNG.delta]] */ - final def nextState(s: Seq[Bool]): Seq[Bool] = (0 until step).foldLeft(s){ case (s, _) => delta(s) } + final def nextState(s: Seq[Bool]): Seq[Bool] = (0 until step).foldLeft(s) { case (s, _) => delta(s) } - when (io.increment) { + when(io.increment) { state := nextState(state) } - when (io.seed.fire) { - state := (if (updateSeed) { nextState(io.seed.bits) } else { io.seed.bits }) + when(io.seed.fire) { + state := (if (updateSeed) { nextState(io.seed.bits) } + else { io.seed.bits }) } io.out := state diff --git a/src/main/scala/chisel3/verilog.scala b/src/main/scala/chisel3/verilog.scala index a91444de..b926a15c 100644 --- a/src/main/scala/chisel3/verilog.scala +++ b/src/main/scala/chisel3/verilog.scala @@ -8,8 +8,7 @@ object getVerilogString { } object emitVerilog { - def apply(gen: => RawModule, args: Array[String] = Array.empty, - annotations: AnnotationSeq = Seq.empty): Unit = { + def apply(gen: => RawModule, args: Array[String] = Array.empty, annotations: AnnotationSeq = Seq.empty): Unit = { (new ChiselStage).emitVerilog(gen, args, annotations) } } diff --git a/src/test/scala/chisel3/testers/TreadleBackend.scala b/src/test/scala/chisel3/testers/TreadleBackend.scala index 19b94e91..9375b10a 100644 --- a/src/test/scala/chisel3/testers/TreadleBackend.scala +++ b/src/test/scala/chisel3/testers/TreadleBackend.scala @@ -17,10 +17,12 @@ import java.io.File case object TreadleBackend extends TesterDriver.Backend { val MaxTreadleCycles = 10000L - def execute(t: () => BasicTester, - additionalVResources: Seq[String] = Seq(), - annotations: AnnotationSeq = Seq(), - nameHint: Option[String] = None): Boolean = { + def execute( + t: () => BasicTester, + additionalVResources: Seq[String] = Seq(), + annotations: AnnotationSeq = Seq(), + nameHint: Option[String] = None + ): Boolean = { val generatorAnnotation = chisel3.stage.ChiselGeneratorAnnotation(t) // This provides an opportunity to translate from top level generic flags to backend specific annos @@ -37,7 +39,7 @@ case object TreadleBackend extends TesterDriver.Backend { if (!annotationSeq.exists(_.isInstanceOf[NoTargetAnnotation])) { annotationSeq = annotationSeq :+ TargetDirAnnotation(targetName.getPath) } - if (!annotationSeq.exists { case CallResetAtStartupAnnotation => true ; case _ => false }) { + if (!annotationSeq.exists { case CallResetAtStartupAnnotation => true; case _ => false }) { annotationSeq = annotationSeq :+ CallResetAtStartupAnnotation } diff --git a/src/test/scala/chiselTests/AdderTree.scala b/src/test/scala/chiselTests/AdderTree.scala index 171fa616..29ef97a4 100644 --- a/src/test/scala/chiselTests/AdderTree.scala +++ b/src/test/scala/chiselTests/AdderTree.scala @@ -10,14 +10,14 @@ class AdderTree[T <: Bits with Num[T]](genType: T, vecSize: Int) extends Module val numIn = Input(Vec(vecSize, genType)) val numOut = Output(genType) }) - io.numOut := io.numIn.reduceTree((a : T, b : T) => (a + b)) + io.numOut := io.numIn.reduceTree((a: T, b: T) => (a + b)) } class AdderTreeTester(bitWidth: Int, numsToAdd: List[Int]) extends BasicTester { val genType = UInt(bitWidth.W) val dut = Module(new AdderTree(genType, numsToAdd.size)) dut.io.numIn := VecInit(numsToAdd.map(x => x.asUInt(bitWidth.W))) - val sumCorrect = dut.io.numOut === (numsToAdd.reduce(_+_) % (1 << bitWidth)).asUInt(bitWidth.W) + val sumCorrect = dut.io.numOut === (numsToAdd.reduce(_ + _) % (1 << bitWidth)).asUInt(bitWidth.W) assert(sumCorrect) stop() } @@ -27,7 +27,7 @@ class AdderTreeSpec extends ChiselPropSpec { forAll(safeUIntN(20)) { case (w: Int, v: List[Int]) => { whenever(v.size > 0 && w > 0) { - assertTesterPasses { new AdderTreeTester(w, v.map(x => math.abs(x) % ( 1 << w )).toList) } + assertTesterPasses { new AdderTreeTester(w, v.map(x => math.abs(x) % (1 << w)).toList) } } } } diff --git a/src/test/scala/chiselTests/AnalogIntegrationSpec.scala b/src/test/scala/chiselTests/AnalogIntegrationSpec.scala index 7478f2eb..035a9d91 100644 --- a/src/test/scala/chiselTests/AnalogIntegrationSpec.scala +++ b/src/test/scala/chiselTests/AnalogIntegrationSpec.scala @@ -53,7 +53,7 @@ class AnalogBlackBoxWrapper(n: Int, idxs: Seq[Int]) extends AnalogBlackBoxModule val bbs = idxs.map(i => Module(new AnalogBlackBoxModule(i))) io.bus <> bbs.head.io.bus // Always bulk connect io.bus to first bus io.port <> bbs.flatMap(_.io.port) // Connect ports - attach(bbs.map(_.io.bus):_*) // Attach all the buses + attach(bbs.map(_.io.bus): _*) // Attach all the buses } // Common superclass for AnalogDUT and AnalogSmallDUT @@ -80,7 +80,7 @@ class AnalogDUT extends AnalogDUTModule(5) { // 5 BlackBoxes // Connect all ports to top io.ports <> mods.flatMap(_.io.port) // Attach first 3 Modules - attach(mods.take(3).map(_.io.bus):_*) + attach(mods.take(3).map(_.io.bus): _*) // Attach last module to 1st through AnalogConnector val con = Module(new AnalogConnector) attach(con.io.bus1, mods.head.io.bus) @@ -100,10 +100,9 @@ class AnalogSmallDUT extends AnalogDUTModule(4) { // 4 BlackBoxes // Connect all ports to top io.ports <> mods.flatMap(_.io.port) // Attach first 3 Modules - attach(mods.take(3).map(_.io.bus):_*) + attach(mods.take(3).map(_.io.bus): _*) } - // This tester is primarily intended to be able to pass the dut to synthesis class AnalogIntegrationTester(mod: => AnalogDUTModule) extends BasicTester { val BusValue = 2.U(32.W) // arbitrary @@ -122,17 +121,17 @@ class AnalogIntegrationTester(mod: => AnalogDUTModule) extends BasicTester { // Error checking assert(dut.out === expectedValue) - when (cycle === idx.U) { + when(cycle === idx.U) { expectedValue := BusValue + idx.U dut.in.valid := true.B } } - when (done) { stop() } + when(done) { stop() } } class AnalogIntegrationSpec extends ChiselFlatSpec { - behavior of "Verilator" + behavior.of("Verilator") it should "support simple bidirectional wires" in { assertTesterPasses( new AnalogIntegrationTester(new AnalogSmallDUT), diff --git a/src/test/scala/chiselTests/AnalogSpec.scala b/src/test/scala/chiselTests/AnalogSpec.scala index 42dafb6e..3d03af78 100644 --- a/src/test/scala/chiselTests/AnalogSpec.scala +++ b/src/test/scala/chiselTests/AnalogSpec.scala @@ -6,7 +6,7 @@ import chisel3._ import chisel3.stage.ChiselStage import chisel3.util._ import chisel3.testers.{BasicTester, TesterDriver} -import chisel3.experimental.{Analog, BaseModule, attach} +import chisel3.experimental.{attach, Analog, BaseModule} // IO for Modules that just connect bus to out class AnalogReaderIO extends Bundle { @@ -59,9 +59,14 @@ class VecAnalogReaderWrapper extends RawModule with AnalogReader { } class VecBundleAnalogReaderWrapper extends RawModule with AnalogReader { - val vecBunBus = IO(Vec(1, new Bundle { - val analog = Analog(32.W) - })) + val vecBunBus = IO( + Vec( + 1, + new Bundle { + val analog = Analog(32.W) + } + ) + ) def bus = vecBunBus(0).analog val out = IO(Output(UInt(32.W))) val mod = Module(new AnalogReaderBlackBox) @@ -74,7 +79,7 @@ abstract class AnalogTester extends BasicTester { final val BusValue = "hdeadbeef".U final val (cycle, done) = Counter(true.B, 2) - when (done) { stop() } + when(done) { stop() } final val writer = Module(new AnalogWriterBlackBox) writer.io.in := BusValue @@ -84,85 +89,103 @@ abstract class AnalogTester extends BasicTester { } class AnalogSpec extends ChiselFlatSpec with Utils { - behavior of "Analog" + behavior.of("Analog") it should "NOT be bindable to registers" in { - a [ChiselException] should be thrownBy extractCause[ChiselException] { - ChiselStage.elaborate { new Module { - val io = IO(new Bundle {}) - val reg = Reg(Analog(32.W)) - }} + a[ChiselException] should be thrownBy extractCause[ChiselException] { + ChiselStage.elaborate { + new Module { + val io = IO(new Bundle {}) + val reg = Reg(Analog(32.W)) + } + } } } it should "NOT be bindable to a direction" in { - a [ChiselException] should be thrownBy extractCause[ChiselException] { - ChiselStage.elaborate { new Module { - val io = IO(new Bundle { - val a = Input(Analog(32.W)) - }) - }} + a[ChiselException] should be thrownBy extractCause[ChiselException] { + ChiselStage.elaborate { + new Module { + val io = IO(new Bundle { + val a = Input(Analog(32.W)) + }) + } + } } - a [ChiselException] should be thrownBy extractCause[ChiselException] { - ChiselStage.elaborate { new Module { - val io = IO(new Bundle { - val a = Output(Analog(32.W)) - }) - }} + a[ChiselException] should be thrownBy extractCause[ChiselException] { + ChiselStage.elaborate { + new Module { + val io = IO(new Bundle { + val a = Output(Analog(32.W)) + }) + } + } } } it should "be flippable" in { - ChiselStage.elaborate { new Module { - val io = IO(new Bundle { - val a = Flipped(Analog(32.W)) - }) - }} + ChiselStage.elaborate { + new Module { + val io = IO(new Bundle { + val a = Flipped(Analog(32.W)) + }) + } + } } // There is no binding on the type of a memory // Should this be an error? ignore should "NOT be a legal type for Mem" in { - a [ChiselException] should be thrownBy extractCause[ChiselException] { - ChiselStage.elaborate { new Module { - val io = IO(new Bundle {}) - val mem = Mem(16, Analog(32.W)) - }} + a[ChiselException] should be thrownBy extractCause[ChiselException] { + ChiselStage.elaborate { + new Module { + val io = IO(new Bundle {}) + val mem = Mem(16, Analog(32.W)) + } + } } } it should "NOT be bindable to Mem ports" in { - a [ChiselException] should be thrownBy extractCause[ChiselException] { - ChiselStage.elaborate { new Module { - val io = IO(new Bundle {}) - val mem = Mem(16, Analog(32.W)) - val port = mem(5.U) - }} + a[ChiselException] should be thrownBy extractCause[ChiselException] { + ChiselStage.elaborate { + new Module { + val io = IO(new Bundle {}) + val mem = Mem(16, Analog(32.W)) + val port = mem(5.U) + } + } } } // TODO This should probably be caught in Chisel // Also note this relies on executing Firrtl from Chisel directly it should "NOT be connectable to UInts" in { - a [Exception] should be thrownBy { - runTester { new BasicTester { - val uint = WireDefault(0.U(32.W)) - val sint = Wire(Analog(32.W)) - sint := uint - }} + a[Exception] should be thrownBy { + runTester { + new BasicTester { + val uint = WireDefault(0.U(32.W)) + val sint = Wire(Analog(32.W)) + sint := uint + } + } } } it should "work with 2 blackboxes bulk connected" in { - assertTesterPasses(new AnalogTester { - val mod = Module(new AnalogReaderBlackBox) - mod.io.bus <> writer.io.bus - check(mod) - }, Seq("/chisel3/AnalogBlackBox.v"), TesterDriver.verilatorOnly) + assertTesterPasses( + new AnalogTester { + val mod = Module(new AnalogReaderBlackBox) + mod.io.bus <> writer.io.bus + check(mod) + }, + Seq("/chisel3/AnalogBlackBox.v"), + TesterDriver.verilatorOnly + ) } it should "error if any bulk connected more than once" in { - a [ChiselException] should be thrownBy extractCause[ChiselException] { + a[ChiselException] should be thrownBy extractCause[ChiselException] { ChiselStage.elaborate(new Module { val io = IO(new Bundle {}) val wires = List.fill(3)(Wire(Analog(32.W))) @@ -170,7 +193,7 @@ class AnalogSpec extends ChiselFlatSpec with Utils { wires(0) <> wires(2) }) } - a [ChiselException] should be thrownBy extractCause[ChiselException] { + a[ChiselException] should be thrownBy extractCause[ChiselException] { ChiselStage.elaborate(new Module { val io = IO(new Bundle {}) val wires = List.fill(2)(Wire(Analog(32.W))) @@ -217,82 +240,113 @@ class AnalogSpec extends ChiselFlatSpec with Utils { } it should "work with 3 blackboxes attached" in { - assertTesterPasses(new AnalogTester { - val mods = Seq.fill(2)(Module(new AnalogReaderBlackBox)) - attach(writer.io.bus, mods(0).io.bus, mods(1).io.bus) - mods.foreach(check(_)) - }, Seq("/chisel3/AnalogBlackBox.v"), TesterDriver.verilatorOnly) + assertTesterPasses( + new AnalogTester { + val mods = Seq.fill(2)(Module(new AnalogReaderBlackBox)) + attach(writer.io.bus, mods(0).io.bus, mods(1).io.bus) + mods.foreach(check(_)) + }, + Seq("/chisel3/AnalogBlackBox.v"), + TesterDriver.verilatorOnly + ) } it should "work with 3 blackboxes separately attached via a wire" in { - assertTesterPasses(new AnalogTester { - val mods = Seq.fill(2)(Module(new AnalogReaderBlackBox)) - val busWire = Wire(Analog(32.W)) - attach(busWire, writer.io.bus) - attach(busWire, mods(0).io.bus) - attach(mods(1).io.bus, busWire) - mods.foreach(check(_)) - }, Seq("/chisel3/AnalogBlackBox.v"), TesterDriver.verilatorOnly) + assertTesterPasses( + new AnalogTester { + val mods = Seq.fill(2)(Module(new AnalogReaderBlackBox)) + val busWire = Wire(Analog(32.W)) + attach(busWire, writer.io.bus) + attach(busWire, mods(0).io.bus) + attach(mods(1).io.bus, busWire) + mods.foreach(check(_)) + }, + Seq("/chisel3/AnalogBlackBox.v"), + TesterDriver.verilatorOnly + ) } // This does not currently work in Verilator unless Firrtl does constant prop and dead code // elimination on these wires ignore should "work with intermediate wires attached to each other" in { - assertTesterPasses(new AnalogTester { - val mod = Module(new AnalogReaderBlackBox) - val busWire = Seq.fill(2)(Wire(Analog(32.W))) - attach(busWire(0), writer.io.bus) - attach(busWire(1), mod.io.bus) - attach(busWire(0), busWire(1)) - check(mod) - }, Seq("/chisel3/AnalogBlackBox.v"), TesterDriver.verilatorOnly) + assertTesterPasses( + new AnalogTester { + val mod = Module(new AnalogReaderBlackBox) + val busWire = Seq.fill(2)(Wire(Analog(32.W))) + attach(busWire(0), writer.io.bus) + attach(busWire(1), mod.io.bus) + attach(busWire(0), busWire(1)) + check(mod) + }, + Seq("/chisel3/AnalogBlackBox.v"), + TesterDriver.verilatorOnly + ) } it should "work with blackboxes at different levels of the module hierarchy" in { - assertTesterPasses(new AnalogTester { - val mods = Seq(Module(new AnalogReaderBlackBox), Module(new AnalogReaderWrapper)) - val busWire = Wire(writer.io.bus.cloneType) - attach(writer.io.bus, mods(0).bus, mods(1).bus) - mods.foreach(check(_)) - }, Seq("/chisel3/AnalogBlackBox.v"), TesterDriver.verilatorOnly) + assertTesterPasses( + new AnalogTester { + val mods = Seq(Module(new AnalogReaderBlackBox), Module(new AnalogReaderWrapper)) + val busWire = Wire(writer.io.bus.cloneType) + attach(writer.io.bus, mods(0).bus, mods(1).bus) + mods.foreach(check(_)) + }, + Seq("/chisel3/AnalogBlackBox.v"), + TesterDriver.verilatorOnly + ) } // This does not currently work in Verilator, but does work in VCS ignore should "support two analog ports in the same module" in { - assertTesterPasses(new AnalogTester { - val reader = Module(new AnalogReaderBlackBox) - val connector = Module(new AnalogConnector) - connector.io.bus1 <> writer.io.bus - reader.io.bus <> connector.io.bus2 - check(reader) - }, Seq("/chisel3/AnalogBlackBox.v"), TesterDriver.verilatorOnly) + assertTesterPasses( + new AnalogTester { + val reader = Module(new AnalogReaderBlackBox) + val connector = Module(new AnalogConnector) + connector.io.bus1 <> writer.io.bus + reader.io.bus <> connector.io.bus2 + check(reader) + }, + Seq("/chisel3/AnalogBlackBox.v"), + TesterDriver.verilatorOnly + ) } it should "NOT support conditional connection of analog types" in { - a [ChiselException] should be thrownBy { - assertTesterPasses(new AnalogTester { - val mod = Module(new AnalogReaderBlackBox) - when (cycle > 3.U) { - mod.io.bus <> writer.io.bus - } - check(mod) - }, Seq("/chisel3/AnalogBlackBox.v")) + a[ChiselException] should be thrownBy { + assertTesterPasses( + new AnalogTester { + val mod = Module(new AnalogReaderBlackBox) + when(cycle > 3.U) { + mod.io.bus <> writer.io.bus + } + check(mod) + }, + Seq("/chisel3/AnalogBlackBox.v") + ) } } it should "work with Vecs of Analog" in { - assertTesterPasses(new AnalogTester { - val mod = Module(new VecAnalogReaderWrapper) - mod.bus <> writer.io.bus - check(mod) - }, Seq("/chisel3/AnalogBlackBox.v"), TesterDriver.verilatorOnly) + assertTesterPasses( + new AnalogTester { + val mod = Module(new VecAnalogReaderWrapper) + mod.bus <> writer.io.bus + check(mod) + }, + Seq("/chisel3/AnalogBlackBox.v"), + TesterDriver.verilatorOnly + ) } it should "work with Vecs of Bundles of Analog" in { - assertTesterPasses(new AnalogTester { - val mod = Module(new VecBundleAnalogReaderWrapper) - mod.bus <> writer.io.bus - check(mod) - }, Seq("/chisel3/AnalogBlackBox.v"), TesterDriver.verilatorOnly) + assertTesterPasses( + new AnalogTester { + val mod = Module(new VecBundleAnalogReaderWrapper) + mod.bus <> writer.io.bus + check(mod) + }, + Seq("/chisel3/AnalogBlackBox.v"), + TesterDriver.verilatorOnly + ) } } diff --git a/src/test/scala/chiselTests/AnnotatingDiamondSpec.scala b/src/test/scala/chiselTests/AnnotatingDiamondSpec.scala index cfa07e26..af73d5d4 100644 --- a/src/test/scala/chiselTests/AnnotatingDiamondSpec.scala +++ b/src/test/scala/chiselTests/AnnotatingDiamondSpec.scala @@ -3,17 +3,12 @@ package chiselTests import chisel3._ -import chisel3.experimental.{ChiselAnnotation, RunFirrtlTransform, annotate} +import chisel3.experimental.{annotate, ChiselAnnotation, RunFirrtlTransform} import chisel3.internal.InstanceId import chisel3.stage.{ChiselGeneratorAnnotation, ChiselStage} import chisel3.testers.BasicTester import firrtl.{CircuitForm, CircuitState, DependencyAPIMigration, LowForm, Transform} -import firrtl.annotations.{ - CircuitName, - CircuitTarget, - SingleTargetAnnotation, - Target -} +import firrtl.annotations.{CircuitName, CircuitTarget, SingleTargetAnnotation, Target} import firrtl.stage.Forms import org.scalatest._ import org.scalatest.freespec.AnyFreeSpec @@ -25,10 +20,12 @@ import org.scalatest.matchers.should.Matchers case class IdentityAnnotation(target: Target, value: String) extends SingleTargetAnnotation[Target] { def duplicate(n: Target): IdentityAnnotation = this.copy(target = n) } + /** ChiselAnnotation that corresponds to the above FIRRTL annotation */ case class IdentityChiselAnnotation(target: InstanceId, value: String) - extends ChiselAnnotation with RunFirrtlTransform { - def toFirrtl: IdentityAnnotation = IdentityAnnotation(target.toNamed, value) + extends ChiselAnnotation + with RunFirrtlTransform { + def toFirrtl: IdentityAnnotation = IdentityAnnotation(target.toNamed, value) def transformClass: Class[IdentityTransform] = classOf[IdentityTransform] } object identify { @@ -47,7 +44,7 @@ class IdentityTransform extends Transform with DependencyAPIMigration { def execute(state: CircuitState): CircuitState = { val annosx = state.annotations.map { case IdentityAnnotation(t, value) => IdentityAnnotation(t, value + ":seen") - case other => other + case other => other } state.copy(annotations = annosx) } @@ -109,8 +106,8 @@ class ModB(widthB: Int) extends Module { class TopOfDiamond extends Module { val io = IO(new Bundle { - val in = Input(UInt(32.W)) - val out = Output(UInt(32.W)) + val in = Input(UInt(32.W)) + val out = Output(UInt(32.W)) }) val x = Reg(UInt(32.W)) val y = Reg(UInt(32.W)) @@ -146,21 +143,24 @@ class AnnotatingDiamondSpec extends AnyFreeSpec with Matchers { |that happens only after emit has been called on circuit""".stripMargin in { val annos = (new ChiselStage) - .execute(Array("--target-dir", "test_run_dir", "--no-run-firrtl"), - Seq(ChiselGeneratorAnnotation(() => new TopOfDiamond))) + .execute( + Array("--target-dir", "test_run_dir", "--no-run-firrtl"), + Seq(ChiselGeneratorAnnotation(() => new TopOfDiamond)) + ) .filter { case _: IdentityAnnotation => true - case _ => false - }.toSeq + case _ => false + } + .toSeq info("Found ten (10) 'IdentityAnnotation's") - annos should have length (10) + (annos should have).length(10) info("Found IdentityAnnotation targeting '~*|ModC' with value 'ModC(16)'") - annos should contain (IdentityAnnotation(CircuitTarget("TopOfDiamond").module("ModC"), "ModC(16)")) + annos should contain(IdentityAnnotation(CircuitTarget("TopOfDiamond").module("ModC"), "ModC(16)")) info("Found IdentityAnnotation targeting '~*|ModC_1:seen' with value 'ModC(32)'") - annos should contain (IdentityAnnotation(CircuitTarget("TopOfDiamond").module("ModC_1"), "ModC(32)")) + annos should contain(IdentityAnnotation(CircuitTarget("TopOfDiamond").module("ModC_1"), "ModC(32)")) } } } diff --git a/src/test/scala/chiselTests/AnnotationNoDedup.scala b/src/test/scala/chiselTests/AnnotationNoDedup.scala index d99a0021..2150f925 100644 --- a/src/test/scala/chiselTests/AnnotationNoDedup.scala +++ b/src/test/scala/chiselTests/AnnotationNoDedup.scala @@ -9,7 +9,6 @@ import firrtl.stage.FirrtlCircuitAnnotation import org.scalatest.freespec.AnyFreeSpec import org.scalatest.matchers.should.Matchers - class MuchUsedModule extends Module { val io = IO(new Bundle { val in = Input(UInt(16.W)) @@ -35,7 +34,7 @@ class UsesMuchUsedModule(addAnnos: Boolean) extends Module { mod3.io.in := mod2.io.out io.out := mod3.io.out - if(addAnnos) { + if (addAnnos) { doNotDedup(mod1) doNotDedup(mod3) } @@ -46,29 +45,35 @@ class AnnotationNoDedup extends AnyFreeSpec with Matchers { "Firrtl provides transform that reduces identical modules to a single instance" - { "Annotations can be added which will prevent this deduplication for specific modules instances" in { val lowFirrtl = stage - .execute(Array("-X", "low", "--target-dir", "test_run_dir"), - Seq(ChiselGeneratorAnnotation(() => new UsesMuchUsedModule(addAnnos = true)))) + .execute( + Array("-X", "low", "--target-dir", "test_run_dir"), + Seq(ChiselGeneratorAnnotation(() => new UsesMuchUsedModule(addAnnos = true))) + ) .collectFirst { case FirrtlCircuitAnnotation(circuit) => circuit.serialize - }.getOrElse(fail) - lowFirrtl should include ("module MuchUsedModule :") - lowFirrtl should include ("module MuchUsedModule_1 :") - lowFirrtl should include ("module MuchUsedModule_3 :") - lowFirrtl should not include "module MuchUsedModule_2 :" - lowFirrtl should not include "module MuchUsedModule_4 :" + } + .getOrElse(fail) + lowFirrtl should include("module MuchUsedModule :") + lowFirrtl should include("module MuchUsedModule_1 :") + lowFirrtl should include("module MuchUsedModule_3 :") + (lowFirrtl should not).include("module MuchUsedModule_2 :") + (lowFirrtl should not).include("module MuchUsedModule_4 :") } "Turning off these annotations dedups all the occurrences" in { val lowFirrtl = stage - .execute(Array("-X", "low", "--target-dir", "test_run_dir"), - Seq(ChiselGeneratorAnnotation(() => new UsesMuchUsedModule(addAnnos = false)))) + .execute( + Array("-X", "low", "--target-dir", "test_run_dir"), + Seq(ChiselGeneratorAnnotation(() => new UsesMuchUsedModule(addAnnos = false))) + ) .collectFirst { case FirrtlCircuitAnnotation(circuit) => circuit.serialize - }.getOrElse(fail) - lowFirrtl should include ("module MuchUsedModule :") - lowFirrtl should not include "module MuchUsedModule_1 :" - lowFirrtl should not include "module MuchUsedModule_3 :" - lowFirrtl should not include "module MuchUsedModule_2 :" - lowFirrtl should not include "module MuchUsedModule_4 :" + } + .getOrElse(fail) + lowFirrtl should include("module MuchUsedModule :") + (lowFirrtl should not).include("module MuchUsedModule_1 :") + (lowFirrtl should not).include("module MuchUsedModule_3 :") + (lowFirrtl should not).include("module MuchUsedModule_2 :") + (lowFirrtl should not).include("module MuchUsedModule_4 :") } } } diff --git a/src/test/scala/chiselTests/AsTypeOfTester.scala b/src/test/scala/chiselTests/AsTypeOfTester.scala index c0365177..2141cac2 100644 --- a/src/test/scala/chiselTests/AsTypeOfTester.scala +++ b/src/test/scala/chiselTests/AsTypeOfTester.scala @@ -3,13 +3,13 @@ package chiselTests import chisel3._ -import chisel3.experimental.{DataMirror, FixedPoint, ChiselEnum} +import chisel3.experimental.{ChiselEnum, DataMirror, FixedPoint} import chisel3.testers.BasicTester class AsTypeOfBundleTester extends BasicTester { class MultiTypeBundle extends Bundle { - val u = UInt(4.W) - val s = SInt(4.W) + val u = UInt(4.W) + val s = SInt(4.W) val fp = FixedPoint(4.W, 3.BP) } @@ -55,12 +55,12 @@ class AsTypeOfVecTester extends BasicTester { class AsTypeOfTruncationTester extends BasicTester { val truncate = (64 + 3).U.asTypeOf(UInt(3.W)) - val expand = 1.U.asTypeOf(UInt(3.W)) + val expand = 1.U.asTypeOf(UInt(3.W)) - assert( DataMirror.widthOf(truncate).get == 3 ) - assert( truncate === 3.U ) - assert( DataMirror.widthOf(expand).get == 3 ) - assert( expand === 1.U ) + assert(DataMirror.widthOf(truncate).get == 3) + assert(truncate === 3.U) + assert(DataMirror.widthOf(expand).get == 3) + assert(expand === 1.U) stop() } @@ -123,26 +123,26 @@ class AsChiselEnumTester extends BasicTester { } class AsTypeOfSpec extends ChiselFlatSpec { - behavior of "asTypeOf" + behavior.of("asTypeOf") it should "work with Bundles containing Bits Types" in { - assertTesterPasses{ new AsTypeOfBundleTester } + assertTesterPasses { new AsTypeOfBundleTester } } it should "work with Bundles that have fields of zero width" in { - assertTesterPasses{ new AsTypeOfBundleZeroWidthTester } + assertTesterPasses { new AsTypeOfBundleZeroWidthTester } } it should "work with Vecs containing Bits Types" in { - assertTesterPasses{ new AsTypeOfVecTester } + assertTesterPasses { new AsTypeOfVecTester } } it should "expand and truncate UInts of different width" in { - assertTesterPasses{ new AsTypeOfTruncationTester } + assertTesterPasses { new AsTypeOfTruncationTester } } it should "work for casting implicit Reset to Bool" in { - assertTesterPasses{ new ResetAsTypeOfBoolTester } + assertTesterPasses { new ResetAsTypeOfBoolTester } } it should "work for casting to and from ChiselEnums" in { diff --git a/src/test/scala/chiselTests/Assert.scala b/src/test/scala/chiselTests/Assert.scala index 0cb554f5..1849ddf8 100644 --- a/src/test/scala/chiselTests/Assert.scala +++ b/src/test/scala/chiselTests/Assert.scala @@ -11,7 +11,7 @@ class FailingAssertTester() extends BasicTester { assert(false.B) // Wait to come out of reset val (_, done) = Counter(!reset.asBool, 4) - when (done) { + when(done) { stop() } } @@ -20,13 +20,13 @@ class SucceedingAssertTester() extends BasicTester { assert(true.B) // Wait to come out of reset val (_, done) = Counter(!reset.asBool, 4) - when (done) { + when(done) { stop() } } class PipelinedResetModule extends Module { - val io = IO(new Bundle { }) + val io = IO(new Bundle {}) val a = RegInit(0xbeef.U) val b = RegInit(0xbeef.U) assert(a === b) @@ -39,7 +39,7 @@ class PipelinedResetTester extends BasicTester { module.reset := RegNext(RegNext(RegNext(reset))) val (_, done) = Counter(!reset.asBool, 4) - when (done) { + when(done) { stop() } } @@ -63,22 +63,22 @@ class BadUnescapedPercentAssertTester extends BasicTester { class AssertSpec extends ChiselFlatSpec with Utils { "A failing assertion" should "fail the testbench" in { - assert(!runTester{ new FailingAssertTester }) + assert(!runTester { new FailingAssertTester }) } "A succeeding assertion" should "not fail the testbench" in { - assertTesterPasses{ new SucceedingAssertTester } + assertTesterPasses { new SucceedingAssertTester } } "An assertion" should "not assert until we come out of reset" in { - assertTesterPasses{ new PipelinedResetTester } + assertTesterPasses { new PipelinedResetTester } } "Assertions" should "allow the modulo operator % in the message" in { - assertTesterPasses{ new ModuloAssertTester } + assertTesterPasses { new ModuloAssertTester } } they should "allow printf-style format strings with arguments" in { - assertTesterPasses{ new FormattedAssertTester } + assertTesterPasses { new FormattedAssertTester } } they should "not allow unescaped % in the message" in { - a [java.util.UnknownFormatConversionException] should be thrownBy { + a[java.util.UnknownFormatConversionException] should be thrownBy { extractCause[java.util.UnknownFormatConversionException] { ChiselStage.elaborate { new BadUnescapedPercentAssertTester } } diff --git a/src/test/scala/chiselTests/AsyncResetSpec.scala b/src/test/scala/chiselTests/AsyncResetSpec.scala index d49f390c..ac7ae0d1 100644 --- a/src/test/scala/chiselTests/AsyncResetSpec.scala +++ b/src/test/scala/chiselTests/AsyncResetSpec.scala @@ -24,16 +24,16 @@ class AsyncResetTester extends BasicTester { } reg := 5.U // Normal connection - when (count === 3.U) { + when(count === 3.U) { assert(reg === 5.U) } - when (count >= 5.U && count < 7.U) { + when(count >= 5.U && count < 7.U) { assert(reg === 123.U) - } .elsewhen (count >= 7.U) { + }.elsewhen(count >= 7.U) { assert(reg === 5.U) } - when (done) { + when(done) { stop() } } @@ -66,25 +66,25 @@ class AsyncResetAggregateTester extends BasicTester { reg(1).x := 7.U reg(1).y := 8.U - when (count === 3.U) { + when(count === 3.U) { assert(reg(0).x === 5.U) assert(reg(0).y === 6.U) assert(reg(1).x === 7.U) assert(reg(1).y === 8.U) } - when (count >= 5.U && count < 7.U) { + when(count >= 5.U && count < 7.U) { assert(reg(0).x === 0.U) assert(reg(0).y === 0.U) assert(reg(1).x === 0.U) assert(reg(1).y === 0.U) - } .elsewhen (count >= 7.U) { + }.elsewhen(count >= 7.U) { assert(reg(0).x === 5.U) assert(reg(0).y === 6.U) assert(reg(1).x === 7.U) assert(reg(1).y === 8.U) } - when (done) { + when(done) { stop() } } @@ -98,7 +98,7 @@ class AsyncResetQueueTester extends BasicTester { val asyncResetNext = RegNext(false.B, false.B) val asyncReset = asyncResetNext.asAsyncReset - val queue = withClockAndReset (slowClk, asyncReset) { + val queue = withClockAndReset(slowClk, asyncReset) { Module(new Queue(UInt(8.W), 4)) } queue.io.enq.valid := true.B @@ -107,15 +107,15 @@ class AsyncResetQueueTester extends BasicTester { queue.io.deq.ready := false.B val doCheck = RegNext(false.B, false.B) - when (queue.io.count === 3.U) { + when(queue.io.count === 3.U) { asyncResetNext := true.B doCheck := true.B } - when (doCheck) { + when(doCheck) { assert(queue.io.count === 0.U) } - when (done) { + when(done) { stop() } } @@ -140,7 +140,7 @@ class AsyncResetDontCareModule extends RawModule { class AsyncResetSpec extends ChiselFlatSpec with Utils { - behavior of "AsyncReset" + behavior.of("AsyncReset") it should "be able to be connected to DontCare" in { ChiselStage.elaborate(new AsyncResetDontCareModule) @@ -153,7 +153,7 @@ class AsyncResetSpec extends ChiselFlatSpec with Utils { } it should "NOT be allowed with non-literal reset values" in { - a [NonLiteralAsyncResetValueException] should be thrownBy extractCause[NonLiteralAsyncResetValueException] { + a[NonLiteralAsyncResetValueException] should be thrownBy extractCause[NonLiteralAsyncResetValueException] { compile(new BasicTester { val x = WireInit(123.U + 456.U) withReset(reset.asAsyncReset)(RegInit(x)) @@ -162,7 +162,7 @@ class AsyncResetSpec extends ChiselFlatSpec with Utils { } it should "NOT be allowed to connect directly to a Bool" in { - a [ChiselException] should be thrownBy extractCause[ChiselException] { + a[ChiselException] should be thrownBy extractCause[ChiselException] { ChiselStage.elaborate(new BasicTester { val bool = Wire(Bool()) val areset = reset.asAsyncReset @@ -199,12 +199,12 @@ class AsyncResetSpec extends ChiselFlatSpec with Utils { val reg = withReset(reset.asAsyncReset)(RegNext(initValue, 27.S)) initValue := -43.S val (count, done) = Counter(true.B, 4) - when (count === 0.U) { + when(count === 0.U) { chisel3.assert(reg === 27.S) - } .otherwise { + }.otherwise { chisel3.assert(reg === -43.S) } - when (done) { stop() } + when(done) { stop() } }) } @@ -212,12 +212,12 @@ class AsyncResetSpec extends ChiselFlatSpec with Utils { assertTesterPasses(new BasicTester { val reg = withReset(reset.asAsyncReset)(RegNext(-6.0.F(2.BP), 3.F(2.BP))) val (count, done) = Counter(true.B, 4) - when (count === 0.U) { + when(count === 0.U) { chisel3.assert(reg === 3.F(2.BP)) - } .otherwise { + }.otherwise { chisel3.assert(reg === -6.0.F(2.BP)) } - when (done) { stop() } + when(done) { stop() } }) } @@ -230,12 +230,12 @@ class AsyncResetSpec extends ChiselFlatSpec with Utils { x } val (count, done) = Counter(true.B, 4) - when (count === 0.U) { + when(count === 0.U) { chisel3.assert(reg === 13.I) - } .otherwise { + }.otherwise { chisel3.assert(reg === 7.I) } - when (done) { stop() } + when(done) { stop() } }) } @@ -249,12 +249,12 @@ class AsyncResetSpec extends ChiselFlatSpec with Utils { RegNext(0xbad0cad0L.U.asTypeOf(new MyBundle), 0xdeadbeefL.U.asTypeOf(new MyBundle)) } val (count, done) = Counter(true.B, 4) - when (count === 0.U) { + when(count === 0.U) { chisel3.assert(reg.asUInt === 0xdeadbeefL.U) - } .otherwise { + }.otherwise { chisel3.assert(reg.asUInt === 0xbad0cad0L.U) } - when (done) { stop() } + when(done) { stop() } }) } it should "allow literals cast to Vecs as reset values" in { @@ -263,12 +263,12 @@ class AsyncResetSpec extends ChiselFlatSpec with Utils { RegNext(0xbad0cad0L.U.asTypeOf(Vec(4, UInt(8.W))), 0xdeadbeefL.U.asTypeOf(Vec(4, UInt(8.W)))) } val (count, done) = Counter(true.B, 4) - when (count === 0.U) { + when(count === 0.U) { chisel3.assert(reg.asUInt === 0xdeadbeefL.U) - } .otherwise { + }.otherwise { chisel3.assert(reg.asUInt === 0xbad0cad0L.U) } - when (done) { stop() } + when(done) { stop() } }) } } diff --git a/src/test/scala/chiselTests/AutoClonetypeSpec.scala b/src/test/scala/chiselTests/AutoClonetypeSpec.scala index ef58f1ed..2ab4c800 100644 --- a/src/test/scala/chiselTests/AutoClonetypeSpec.scala +++ b/src/test/scala/chiselTests/AutoClonetypeSpec.scala @@ -42,7 +42,7 @@ class ModuleWithInner extends Module { val out = UInt(i.W) } - val io = IO(new Bundle{}) + val io = IO(new Bundle {}) val myWire = Wire(new InnerBundle(14)) require(myWire.i == 14) @@ -75,54 +75,64 @@ class InheritingBundle extends QueueIO(UInt(8.W), 8) { class AutoClonetypeSpec extends ChiselFlatSpec with Utils { "Bundles with Scala args" should "not need clonetype" in { - elaborate { new Module { - val io = IO(new Bundle{}) + elaborate { + new Module { + val io = IO(new Bundle {}) - val myWire = Wire(new BundleWithIntArg(8)) - assert(myWire.i == 8) - } } + val myWire = Wire(new BundleWithIntArg(8)) + assert(myWire.i == 8) + } + } } "Bundles with Scala implicit args" should "not need clonetype" in { - elaborate { new Module { - val io = IO(new Bundle{}) + elaborate { + new Module { + val io = IO(new Bundle {}) - implicit val implicitInt: Int = 4 - val myWire = Wire(new BundleWithImplicit()) + implicit val implicitInt: Int = 4 + val myWire = Wire(new BundleWithImplicit()) - assert(myWire.ii == 4) - } } + assert(myWire.ii == 4) + } + } } "Bundles with Scala explicit and impicit args" should "not need clonetype" in { - elaborate { new Module { - val io = IO(new Bundle{}) + elaborate { + new Module { + val io = IO(new Bundle {}) - implicit val implicitInt: Int = 4 - val myWire = Wire(new BundleWithArgAndImplicit(8)) + implicit val implicitInt: Int = 4 + val myWire = Wire(new BundleWithArgAndImplicit(8)) - assert(myWire.i == 8) - assert(myWire.ii == 4) - } } + assert(myWire.i == 8) + assert(myWire.ii == 4) + } + } } "Subtyped Bundles" should "not need clonetype" in { - elaborate { new Module { - val io = IO(new Bundle{}) + elaborate { + new Module { + val io = IO(new Bundle {}) - val myWire = Wire(new SubBundle(8, 4)) + val myWire = Wire(new SubBundle(8, 4)) - assert(myWire.i == 8) - assert(myWire.i2 == 4) - } } - elaborate { new Module { - val io = IO(new Bundle{}) + assert(myWire.i == 8) + assert(myWire.i2 == 4) + } + } + elaborate { + new Module { + val io = IO(new Bundle {}) - val myWire = Wire(new SubBundleVal(8, 4)) + val myWire = Wire(new SubBundleVal(8, 4)) - assert(myWire.i == 8) - assert(myWire.i2 == 4) - } } + assert(myWire.i == 8) + assert(myWire.i2 == 4) + } + } } "Autoclonetype" should "work outside of a builder context" in { @@ -130,10 +140,12 @@ class AutoClonetypeSpec extends ChiselFlatSpec with Utils { } "Subtyped Bundles that don't clone well" should "be now be supported!" in { - elaborate { new Module { - val io = IO(new Bundle{}) - val myWire = Wire(new SubBundleInvalid(8, 4)) - } } + elaborate { + new Module { + val io = IO(new Bundle {}) + val myWire = Wire(new SubBundleInvalid(8, 4)) + } + } } "Inner bundles with Scala args" should "not need clonetype" in { @@ -141,76 +153,92 @@ class AutoClonetypeSpec extends ChiselFlatSpec with Utils { } "Bundles with arguments as fields" should "not need clonetype" in { - elaborate { new Module { - val io = IO(Output(new BundleWithArgumentField(UInt(8.W), UInt(8.W)))) - io.x := 1.U - io.y := 1.U - } } + elaborate { + new Module { + val io = IO(Output(new BundleWithArgumentField(UInt(8.W), UInt(8.W)))) + io.x := 1.U + io.y := 1.U + } + } } it should "also work when giving directions to the fields" in { - elaborate { new Module { - val io = IO(new BundleWithArgumentField(Input(UInt(8.W)), Output(UInt(8.W)))) - io.y := io.x - } } + elaborate { + new Module { + val io = IO(new BundleWithArgumentField(Input(UInt(8.W)), Output(UInt(8.W)))) + io.y := io.x + } + } } "Bundles inside companion objects" should "not need clonetype" in { - elaborate { new Module { - val io = IO(Output(new CompanionObjectWithBundle.Inner)) - io.data := 1.U - } } + elaborate { + new Module { + val io = IO(Output(new CompanionObjectWithBundle.Inner)) + io.data := 1.U + } + } } "Parameterized bundles inside companion objects" should "not need clonetype" in { - elaborate { new Module { - val io = IO(Output(new CompanionObjectWithBundle.ParameterizedInner(8))) - io.data := 1.U - } } + elaborate { + new Module { + val io = IO(Output(new CompanionObjectWithBundle.ParameterizedInner(8))) + io.data := 1.U + } + } } "Nested directioned anonymous Bundles" should "not need clonetype" in { - elaborate { new Module { - val io = IO(new NestedAnonymousBundle) - val a = WireDefault(io) - io.a.a := 1.U - } } + elaborate { + new Module { + val io = IO(new NestedAnonymousBundle) + val a = WireDefault(io) + io.a.a := 1.U + } + } } "3.0 null compatibility" should "not need clonetype" in { - elaborate { new Module { - class InnerClassThing { - def createBundle: Bundle = new Bundle { - val a = Output(UInt(8.W)) + elaborate { + new Module { + class InnerClassThing { + def createBundle: Bundle = new Bundle { + val a = Output(UInt(8.W)) + } } + val io = IO((new InnerClassThing).createBundle) + val a = WireDefault(io) } - val io = IO((new InnerClassThing).createBundle) - val a = WireDefault(io) - } } + } } "Aliased fields" should "be caught" in { - a [ChiselException] should be thrownBy extractCause[ChiselException] { - elaborate { new Module { - val bundleFieldType = UInt(8.W) - val io = IO(Output(new Bundle { - val a = bundleFieldType - })) - io.a := 0.U - } } + a[ChiselException] should be thrownBy extractCause[ChiselException] { + elaborate { + new Module { + val bundleFieldType = UInt(8.W) + val io = IO(Output(new Bundle { + val a = bundleFieldType + })) + io.a := 0.U + } + } } } "Aliased fields from inadequate autoclonetype" should "be caught" in { - a [ChiselException] should be thrownBy extractCause[ChiselException] { + a[ChiselException] should be thrownBy extractCause[ChiselException] { class BadBundle(val typeTuple: (Data, Int)) extends Bundle { val a = typeTuple._1 } - elaborate { new Module { - val io = IO(Output(new BadBundle(UInt(8.W), 1))) - io.a := 0.U - } } + elaborate { + new Module { + val io = IO(Output(new BadBundle(UInt(8.W), 1))) + io.a := 0.U + } + } } } @@ -250,7 +278,7 @@ class AutoClonetypeSpec extends ChiselFlatSpec with Utils { elaborate(new MyModule(3)) } - behavior of "Compiler Plugin Autoclonetype" + behavior.of("Compiler Plugin Autoclonetype") it should "NOT break code that extends chisel3.util Bundles if they use the plugin" in { class MyModule extends MultiIOModule { @@ -266,34 +294,40 @@ class AutoClonetypeSpec extends ChiselFlatSpec with Utils { class MyBundle(i: Int) extends Bundle { val foo = UInt(i.W) } - elaborate { new MultiIOModule { - val in = IO(Input(new MyBundle(8))) - val out = IO(Output(new MyBundle(8))) - out := in - }} + elaborate { + new MultiIOModule { + val in = IO(Input(new MyBundle(8))) + val out = IO(Output(new MyBundle(8))) + out := in + } + } } it should "support type-parameterized Bundles" in { class MyBundle[T <: Data](gen: T) extends Bundle { val foo = gen } - elaborate { new MultiIOModule { - val in = IO(Input(new MyBundle(UInt(8.W)))) - val out = IO(Output(new MyBundle(UInt(8.W)))) - out := in - }} + elaborate { + new MultiIOModule { + val in = IO(Input(new MyBundle(UInt(8.W)))) + val out = IO(Output(new MyBundle(UInt(8.W)))) + out := in + } + } } it should "support Bundles with non-val implicit parameters" in { class MyBundle(implicit i: Int) extends Bundle { val foo = UInt(i.W) } - elaborate { new MultiIOModule { - implicit val x = 8 - val in = IO(Input(new MyBundle)) - val out = IO(Output(new MyBundle)) - out := in - }} + elaborate { + new MultiIOModule { + implicit val x = 8 + val in = IO(Input(new MyBundle)) + val out = IO(Output(new MyBundle)) + out := in + } + } } it should "support Bundles with multiple parameter lists" in { @@ -313,11 +347,13 @@ class AutoClonetypeSpec extends ChiselFlatSpec with Utils { class MyBundle(i: Int) extends Bundle { val foo = UInt(i.W) } - elaborate { new MultiIOModule { - val in = IO(Input(new MyBundle(8))) - val out = IO(Output(new MyBundle(8))) - out := in - }} + elaborate { + new MultiIOModule { + val in = IO(Input(new MyBundle(8))) + val out = IO(Output(new MyBundle(8))) + out := in + } + } } it should "support Bundles that capture type parameters from their parent scope" in { diff --git a/src/test/scala/chiselTests/AutoNestedCloneSpec.scala b/src/test/scala/chiselTests/AutoNestedCloneSpec.scala index 258d0823..b75c0c00 100644 --- a/src/test/scala/chiselTests/AutoNestedCloneSpec.scala +++ b/src/test/scala/chiselTests/AutoNestedCloneSpec.scala @@ -14,7 +14,7 @@ class BundleWithAnonymousInner(val w: Int) extends Bundle { class AutoNestedCloneSpec extends ChiselFlatSpec with Matchers with Utils { - behavior of "autoCloneType of inner Bundle in Chisel3" + behavior.of("autoCloneType of inner Bundle in Chisel3") it should "clone a doubly-nested inner bundle successfully" in { elaborate { @@ -36,7 +36,7 @@ class AutoNestedCloneSpec extends ChiselFlatSpec with Matchers with Utils { elaborate { class TestTop(val w: Int) extends Module { val io = IO(new Bundle {}) - val myWire = Wire(new Bundle{ val a = UInt(w.W) }) + val myWire = Wire(new Bundle { val a = UInt(w.W) }) } new TestTop(2) } @@ -45,13 +45,13 @@ class AutoNestedCloneSpec extends ChiselFlatSpec with Matchers with Utils { it should "pick the correct $outer instance for an anonymous inner bundle" in { elaborate { class Inner(val w: Int) extends Module { - val io = IO(new Bundle{ + val io = IO(new Bundle { val in = Input(UInt(w.W)) val out = Output(UInt(w.W)) }) } class Outer(val w: Int) extends Module { - val io = IO(new Bundle{ + val io = IO(new Bundle { val in = Input(UInt(w.W)) val out = Output(UInt(w.W)) }) @@ -125,7 +125,7 @@ class AutoNestedCloneSpec extends ChiselFlatSpec with Matchers with Utils { val foo = new Bundle { val x = Input(Vec(n, gen)) } - val bar = Output(Option(new { def mkBundle = new Bundle { val x = Vec(n, gen) }}).get.mkBundle) + val bar = Output(Option(new { def mkBundle = new Bundle { val x = Vec(n, gen) } }).get.mkBundle) } val io = IO(new MyBundle(4, UInt(8.W))) val myWire = WireInit(io.foo) diff --git a/src/test/scala/chiselTests/BetterNamingTests.scala b/src/test/scala/chiselTests/BetterNamingTests.scala index a55d3e08..8fd1c11f 100644 --- a/src/test/scala/chiselTests/BetterNamingTests.scala +++ b/src/test/scala/chiselTests/BetterNamingTests.scala @@ -31,10 +31,14 @@ class IterableNaming extends NamedModuleTester { val seq = Seq.tabulate(3) { i => Seq.tabulate(2) { j => expectName(WireDefault((i * j).U), s"seq_${i}_${j}") } } - val optSet = Some(Set(expectName(WireDefault(0.U), "optSet_0"), - expectName(WireDefault(1.U), "optSet_1"), - expectName(WireDefault(2.U), "optSet_2"), - expectName(WireDefault(3.U), "optSet_3"))) + val optSet = Some( + Set( + expectName(WireDefault(0.U), "optSet_0"), + expectName(WireDefault(1.U), "optSet_1"), + expectName(WireDefault(2.U), "optSet_2"), + expectName(WireDefault(3.U), "optSet_3") + ) + ) val stack = { val s = mutable.Stack[Module]() @@ -62,7 +66,7 @@ class DigitFieldNamesInRecord extends NamedModuleTester { */ class BetterNamingTests extends ChiselFlatSpec { - behavior of "Better Naming" + behavior.of("Better Naming") it should "provide unique counters for each name" in { var module: PerNameIndexing = null @@ -77,7 +81,7 @@ class BetterNamingTests extends ChiselFlatSpec { } it should "allow digits to be field names in Records" in { - var module: DigitFieldNamesInRecord = null + var module: DigitFieldNamesInRecord = null ChiselStage.elaborate { module = new DigitFieldNamesInRecord; module } assert(module.getNameFailures() == Nil) } @@ -92,6 +96,6 @@ class BetterNamingTests extends ChiselFlatSpec { } val withLits = ChiselStage.emitChirrtl(new MyModule(true)) val noLits = ChiselStage.emitChirrtl(new MyModule(false)) - withLits should equal (noLits) + withLits should equal(noLits) } } diff --git a/src/test/scala/chiselTests/BitwiseOps.scala b/src/test/scala/chiselTests/BitwiseOps.scala index 9cbadbc1..2c050bfa 100644 --- a/src/test/scala/chiselTests/BitwiseOps.scala +++ b/src/test/scala/chiselTests/BitwiseOps.scala @@ -14,14 +14,15 @@ class BitwiseOpsTester(w: Int, _a: Int, _b: Int) extends BasicTester { assert((a | b) === (_a | _b).asUInt) assert((a ^ b) === (_a ^ _b).asUInt) assert((a.orR) === (_a != 0).asBool) - assert((a.andR) === (s"%${w}s".format(BigInt(_a).toString(2)).foldLeft(true)(_ && _ == '1') ).asBool) + assert((a.andR) === (s"%${w}s".format(BigInt(_a).toString(2)).foldLeft(true)(_ && _ == '1')).asBool) stop() } class BitwiseOpsSpec extends ChiselPropSpec { property("All bit-wise ops should return the correct result") { - forAll(safeUIntPair) { case(w: Int, a: Int, b: Int) => - assertTesterPasses{ new BitwiseOpsTester(w, a, b) } + forAll(safeUIntPair) { + case (w: Int, a: Int, b: Int) => + assertTesterPasses { new BitwiseOpsTester(w, a, b) } } } } diff --git a/src/test/scala/chiselTests/BlackBox.scala b/src/test/scala/chiselTests/BlackBox.scala index d3d52f96..27cdbbc4 100644 --- a/src/test/scala/chiselTests/BlackBox.scala +++ b/src/test/scala/chiselTests/BlackBox.scala @@ -5,7 +5,7 @@ package chiselTests import chisel3._ import chisel3.experimental._ import chisel3.stage.ChiselStage -import chisel3.testers.{TesterDriver, BasicTester} +import chisel3.testers.{BasicTester, TesterDriver} import chisel3.util._ class BlackBoxInverter extends BlackBox { @@ -120,8 +120,7 @@ class BlackBoxWithClockTester extends BasicTester { when(end) { stop() } } -class BlackBoxConstant(value: Int) extends BlackBox( - Map("VALUE" -> value, "WIDTH" -> log2Ceil(value + 1))) { +class BlackBoxConstant(value: Int) extends BlackBox(Map("VALUE" -> value, "WIDTH" -> log2Ceil(value + 1))) { require(value >= 0, "value must be a UInt!") val io = IO(new Bundle { val out = Output(UInt(log2Ceil(value + 1).W)) @@ -147,8 +146,8 @@ class BlackBoxTypeParam(w: Int, raw: String) extends BlackBox(Map("T" -> RawPara } class BlackBoxWithParamsTester extends BasicTester { - val blackBoxOne = Module(new BlackBoxConstant(1)) - val blackBoxFour = Module(new BlackBoxConstant(4)) + val blackBoxOne = Module(new BlackBoxConstant(1)) + val blackBoxFour = Module(new BlackBoxConstant(4)) val blackBoxStringParamOne = Module(new BlackBoxStringParam("one")) val blackBoxStringParamTwo = Module(new BlackBoxStringParam("two")) val blackBoxRealParamOne = Module(new BlackBoxRealParam(1.0)) @@ -158,7 +157,7 @@ class BlackBoxWithParamsTester extends BasicTester { val (cycles, end) = Counter(true.B, 4) - assert(blackBoxOne.io.out === 1.U) + assert(blackBoxOne.io.out === 1.U) assert(blackBoxFour.io.out === 4.U) assert(blackBoxStringParamOne.io.out === 1.U) assert(blackBoxStringParamTwo.io.out === 2.U) @@ -172,47 +171,28 @@ class BlackBoxWithParamsTester extends BasicTester { class BlackBoxSpec extends ChiselFlatSpec { "A BlackBoxed inverter" should "work" in { - assertTesterPasses( - {new BlackBoxTester}, - Seq("/chisel3/BlackBoxTest.v"), - TesterDriver.verilatorOnly) + assertTesterPasses({ new BlackBoxTester }, Seq("/chisel3/BlackBoxTest.v"), TesterDriver.verilatorOnly) } "A BlackBoxed with flipped IO" should "work" in { - assertTesterPasses( - {new BlackBoxFlipTester}, - Seq("/chisel3/BlackBoxTest.v"), - TesterDriver.verilatorOnly) + assertTesterPasses({ new BlackBoxFlipTester }, Seq("/chisel3/BlackBoxTest.v"), TesterDriver.verilatorOnly) } "Multiple BlackBoxes" should "work" in { - assertTesterPasses( - {new MultiBlackBoxTester}, - Seq("/chisel3/BlackBoxTest.v"), - TesterDriver.verilatorOnly) + assertTesterPasses({ new MultiBlackBoxTester }, Seq("/chisel3/BlackBoxTest.v"), TesterDriver.verilatorOnly) } "A BlackBoxed register" should "work" in { - assertTesterPasses( - {new BlackBoxWithClockTester}, - Seq("/chisel3/BlackBoxTest.v"), - TesterDriver.verilatorOnly) + assertTesterPasses({ new BlackBoxWithClockTester }, Seq("/chisel3/BlackBoxTest.v"), TesterDriver.verilatorOnly) } "BlackBoxes with parameters" should "work" in { - assertTesterPasses( - {new BlackBoxWithParamsTester}, - Seq("/chisel3/BlackBoxTest.v"), - TesterDriver.verilatorOnly) + assertTesterPasses({ new BlackBoxWithParamsTester }, Seq("/chisel3/BlackBoxTest.v"), TesterDriver.verilatorOnly) } "DataMirror.modulePorts" should "work with BlackBox" in { ChiselStage.elaborate(new Module { - val io = IO(new Bundle {}) - val m = Module(new BlackBoxPassthrough) - assert(DataMirror.modulePorts(m) == Seq("in" -> m.io.in, "out" -> m.io.out)) - } - ) + val io = IO(new Bundle {}) + val m = Module(new BlackBoxPassthrough) + assert(DataMirror.modulePorts(m) == Seq("in" -> m.io.in, "out" -> m.io.out)) + }) } "A BlackBoxed using suggestName(\"io\")" should "work (but don't do this)" in { - assertTesterPasses( - {new BlackBoxTesterSuggestName}, - Seq("/chisel3/BlackBoxTest.v"), - TesterDriver.verilatorOnly) + assertTesterPasses({ new BlackBoxTesterSuggestName }, Seq("/chisel3/BlackBoxTest.v"), TesterDriver.verilatorOnly) } } diff --git a/src/test/scala/chiselTests/BlackBoxImpl.scala b/src/test/scala/chiselTests/BlackBoxImpl.scala index 2fa3d8a6..4cc72dd0 100644 --- a/src/test/scala/chiselTests/BlackBoxImpl.scala +++ b/src/test/scala/chiselTests/BlackBoxImpl.scala @@ -5,7 +5,7 @@ package chiselTests import java.io.File import chisel3._ -import chisel3.util.{HasBlackBoxInline, HasBlackBoxResource, HasBlackBoxPath} +import chisel3.util.{HasBlackBoxInline, HasBlackBoxPath, HasBlackBoxResource} import chisel3.stage.{ChiselGeneratorAnnotation, ChiselStage} import firrtl.transforms.BlackBoxNotFoundException import org.scalacheck.Test.Failed @@ -13,22 +13,23 @@ import org.scalatest.Succeeded import org.scalatest.freespec.AnyFreeSpec import org.scalatest.matchers.should.Matchers - -class BlackBoxAdd(n : Int) extends HasBlackBoxInline { +class BlackBoxAdd(n: Int) extends HasBlackBoxInline { val io = IO(new Bundle { val in = Input(UInt(16.W)) val out = Output(UInt(16.W)) }) - setInline("BlackBoxAdd.v", + setInline( + "BlackBoxAdd.v", s""" - |module BlackBoxAdd( - | input [15:0] in, - | output [15:0] out - |); - | assign out = in + $n; - |endmodule - """.stripMargin) + |module BlackBoxAdd( + | input [15:0] in, + | output [15:0] out + |); + | assign out = in + $n; + |endmodule + """.stripMargin + ) } class UsesBlackBoxAddViaInline extends Module { @@ -89,7 +90,7 @@ class UsesBlackBoxMinusViaPath extends Module { } class BlackBoxResourceNotFound extends HasBlackBoxResource { - val io = IO(new Bundle{}) + val io = IO(new Bundle {}) addResource("/missing.resource") } @@ -102,29 +103,35 @@ class BlackBoxImplSpec extends AnyFreeSpec with Matchers { val stage = new ChiselStage "BlackBox can have verilator source implementation" - { "Implementations can be contained in-line" in { - stage.execute(Array("-X", "verilog", "--target-dir", targetDir), - Seq(ChiselGeneratorAnnotation(() => new UsesBlackBoxAddViaInline))) + stage.execute( + Array("-X", "verilog", "--target-dir", targetDir), + Seq(ChiselGeneratorAnnotation(() => new UsesBlackBoxAddViaInline)) + ) val verilogOutput = new File(targetDir, "BlackBoxAdd.v") - verilogOutput.exists() should be (true) + verilogOutput.exists() should be(true) verilogOutput.delete() } "Implementations can be contained in resource files" in { - stage.execute(Array("-X", "low", "--target-dir", targetDir), - Seq(ChiselGeneratorAnnotation(() => new UsesBlackBoxMinusViaResource))) + stage.execute( + Array("-X", "low", "--target-dir", targetDir), + Seq(ChiselGeneratorAnnotation(() => new UsesBlackBoxMinusViaResource)) + ) val verilogOutput = new File(targetDir, "BlackBoxTest.v") - verilogOutput.exists() should be (true) + verilogOutput.exists() should be(true) verilogOutput.delete() } "Implementations can be contained in arbitrary files" in { - stage.execute(Array("-X", "low", "--target-dir", targetDir), - Seq(ChiselGeneratorAnnotation(() => new UsesBlackBoxMinusViaPath))) + stage.execute( + Array("-X", "low", "--target-dir", targetDir), + Seq(ChiselGeneratorAnnotation(() => new UsesBlackBoxMinusViaPath)) + ) val verilogOutput = new File(targetDir, "BlackBoxTest.v") - verilogOutput.exists() should be (true) + verilogOutput.exists() should be(true) verilogOutput.delete() Succeeded } "Resource files that do not exist produce Chisel errors" in { - assertThrows[BlackBoxNotFoundException]{ + assertThrows[BlackBoxNotFoundException] { ChiselStage.emitChirrtl(new UsesMissingBlackBoxResource) } } diff --git a/src/test/scala/chiselTests/BoringUtilsSpec.scala b/src/test/scala/chiselTests/BoringUtilsSpec.scala index 39859581..9be2d75a 100644 --- a/src/test/scala/chiselTests/BoringUtilsSpec.scala +++ b/src/test/scala/chiselTests/BoringUtilsSpec.scala @@ -8,7 +8,7 @@ import chisel3.testers._ import chisel3.experimental.{BaseModule, ChiselAnnotation, RunFirrtlTransform} import chisel3.util.experimental.BoringUtils -import firrtl.{CircuitForm, CircuitState, ChirrtlForm, DependencyAPIMigration, Transform} +import firrtl.{ChirrtlForm, CircuitForm, CircuitState, DependencyAPIMigration, Transform} import firrtl.annotations.{Annotation, NoTargetAnnotation} import firrtl.options.Dependency import firrtl.transforms.{DontTouchAnnotation, NoDedupAnnotation} @@ -18,7 +18,7 @@ import firrtl.stage.Forms abstract class ShouldntAssertTester(cyclesToWait: BigInt = 4) extends BasicTester { val dut: BaseModule val (_, done) = Counter(true.B, 2) - when (done) { stop() } + when(done) { stop() } } class StripNoDedupAnnotation extends Transform with DependencyAPIMigration { @@ -27,14 +27,14 @@ class StripNoDedupAnnotation extends Transform with DependencyAPIMigration { override def optionalPrerequisiteOf = Dependency[WiringTransform] +: Forms.ChirrtlEmitters override def invalidates(a: Transform) = false def execute(state: CircuitState): CircuitState = { - state.copy(annotations = state.annotations.filter{ case _: NoDedupAnnotation => false; case _ => true }) + state.copy(annotations = state.annotations.filter { case _: NoDedupAnnotation => false; case _ => true }) } } class BoringUtilsSpec extends ChiselFlatSpec with ChiselRunners { class BoringInverter extends Module { - val io = IO(new Bundle{}) + val io = IO(new Bundle {}) val a = Wire(UInt(1.W)) val notA = Wire(UInt(1.W)) val b = Wire(UInt(1.W)) @@ -46,11 +46,13 @@ class BoringUtilsSpec extends ChiselFlatSpec with ChiselRunners { BoringUtils.addSink(b, "x") } - behavior of "BoringUtils.{addSink, addSource}" + behavior.of("BoringUtils.{addSink, addSource}") it should "connect two wires within a module" in { - runTester(new ShouldntAssertTester { val dut = Module(new BoringInverter) }, - annotations = TesterDriver.verilatorOnly) should be (true) + runTester( + new ShouldntAssertTester { val dut = Module(new BoringInverter) }, + annotations = TesterDriver.verilatorOnly + ) should be(true) } trait WireX { this: BaseModule => @@ -77,10 +79,10 @@ class BoringUtilsSpec extends ChiselFlatSpec with ChiselRunners { val sinks = Seq.fill(6)(Module(new Sink)) /* Sources are differentiated by their input connections only. */ - sources.zip(Seq(0, 1, 2)).map{ case (a, b) => a.in := b.U } + sources.zip(Seq(0, 1, 2)).map { case (a, b) => a.in := b.U } /* Sinks are differentiated by their post-boring outputs. */ - sinks.zip(Seq(0, 1, 1, 2, 2, 2)).map{ case (a, b) => chisel3.assert(a.out === b.U) } + sinks.zip(Seq(0, 1, 1, 2, 2, 2)).map { case (a, b) => chisel3.assert(a.out === b.U) } } /** This is testing a complicated wiring pattern and exercising @@ -95,22 +97,22 @@ class BoringUtilsSpec extends ChiselFlatSpec with ChiselRunners { trait FailViaDedup { this: TopTester => case object FooAnnotation extends NoTargetAnnotation - chisel3.experimental.annotate( - new ChiselAnnotation with RunFirrtlTransform { - def toFirrtl: Annotation = FooAnnotation - def transformClass: Class[_ <: Transform] = classOf[StripNoDedupAnnotation] } ) + chisel3.experimental.annotate(new ChiselAnnotation with RunFirrtlTransform { + def toFirrtl: Annotation = FooAnnotation + def transformClass: Class[_ <: Transform] = classOf[StripNoDedupAnnotation] + }) } - behavior of "BoringUtils.bore" + behavior.of("BoringUtils.bore") it should "connect across modules using BoringUtils.bore" in { - runTester(new TopTester, annotations = TesterDriver.verilatorOnly) should be (true) + runTester(new TopTester, annotations = TesterDriver.verilatorOnly) should be(true) } it should "throw an exception if NoDedupAnnotations are removed" in { - intercept[WiringException] { runTester(new TopTester with FailViaDedup, - annotations = Seq(TesterDriver.VerilatorBackend)) } - .getMessage should startWith ("Unable to determine source mapping for sink") + intercept[WiringException] { + runTester(new TopTester with FailViaDedup, annotations = Seq(TesterDriver.VerilatorBackend)) + }.getMessage should startWith("Unable to determine source mapping for sink") } class InternalBore extends RawModule { @@ -127,7 +129,7 @@ class BoringUtilsSpec extends ChiselFlatSpec with ChiselRunners { } it should "work for an internal (same module) BoringUtils.bore" in { - runTester(new InternalBoreTester, annotations = TesterDriver.verilatorOnly) should be (true) + runTester(new InternalBoreTester, annotations = TesterDriver.verilatorOnly) should be(true) } } diff --git a/src/test/scala/chiselTests/BundleLiteralSpec.scala b/src/test/scala/chiselTests/BundleLiteralSpec.scala index b4adde4a..bc6522bb 100644 --- a/src/test/scala/chiselTests/BundleLiteralSpec.scala +++ b/src/test/scala/chiselTests/BundleLiteralSpec.scala @@ -29,50 +29,57 @@ class BundleLiteralSpec extends ChiselFlatSpec with Utils { } "bundle literals" should "pack" in { - assertTesterPasses{ new BasicTester { - val bundleLit = (new MyBundle).Lit(_.a -> 42.U, _.b -> false.B, _.c -> MyEnum.sB) - bundleLit.litOption should equal (Some(169)) // packed as 42 (8-bit), false=0 (1-bit), sB=1 (1-bit) - chisel3.assert(bundleLit.asUInt() === bundleLit.litOption.get.U) // sanity-check consistency with runtime - - val longBundleLit = (new LongBundle).Lit( - _.a -> 0xDEADDEADBEEFL.U, _.b -> (-0x0BEEF00DL).S(32.W), _.c -> 4.5.F(16.W, 4.BP)) - longBundleLit.litOption should equal (Some( - (BigInt(0xDEADDEADBEEFL) << 48) - + (BigInt(0xFFFFFFFFL - 0xBEEF00DL + 1) << 16) - + BigInt(72))) - chisel3.assert(longBundleLit.asUInt() === longBundleLit.litOption.get.U) - - stop() - } } + assertTesterPasses { + new BasicTester { + val bundleLit = (new MyBundle).Lit(_.a -> 42.U, _.b -> false.B, _.c -> MyEnum.sB) + bundleLit.litOption should equal(Some(169)) // packed as 42 (8-bit), false=0 (1-bit), sB=1 (1-bit) + chisel3.assert(bundleLit.asUInt() === bundleLit.litOption.get.U) // sanity-check consistency with runtime + + val longBundleLit = + (new LongBundle).Lit(_.a -> 0xdeaddeadbeefL.U, _.b -> (-0x0beef00dL).S(32.W), _.c -> 4.5.F(16.W, 4.BP)) + longBundleLit.litOption should equal( + Some( + (BigInt(0xdeaddeadbeefL) << 48) + + (BigInt(0xffffffffL - 0xbeef00dL + 1) << 16) + + BigInt(72) + ) + ) + chisel3.assert(longBundleLit.asUInt() === longBundleLit.litOption.get.U) + + stop() + } + } } "bundle literals" should "work in RTL" in { val outsideBundleLit = (new MyBundle).Lit(_.a -> 42.U, _.b -> true.B, _.c -> MyEnum.sB) - assertTesterPasses{ new BasicTester{ - // TODO: add direct bundle compare operations, when that feature is added - chisel3.assert(outsideBundleLit.a === 42.U) - chisel3.assert(outsideBundleLit.b === true.B) - chisel3.assert(outsideBundleLit.c === MyEnum.sB) - chisel3.assert(outsideBundleLit.isLit()) - chisel3.assert(outsideBundleLit.litValue().U === outsideBundleLit.asUInt()) - val bundleLit = (new MyBundle).Lit(_.a -> 42.U, _.b -> true.B, _.c -> MyEnum.sB) - chisel3.assert(bundleLit.a === 42.U) - chisel3.assert(bundleLit.b === true.B) - chisel3.assert(bundleLit.c === MyEnum.sB) - - chisel3.assert(bundleLit.a === outsideBundleLit.a) - chisel3.assert(bundleLit.b === outsideBundleLit.b) - chisel3.assert(bundleLit.c === outsideBundleLit.c) - - val bundleWire = Wire(new MyBundle) - bundleWire := outsideBundleLit - - chisel3.assert(bundleWire.a === 42.U) - chisel3.assert(bundleWire.b === true.B) - chisel3.assert(bundleWire.c === MyEnum.sB) - - stop() - } } + assertTesterPasses { + new BasicTester { + // TODO: add direct bundle compare operations, when that feature is added + chisel3.assert(outsideBundleLit.a === 42.U) + chisel3.assert(outsideBundleLit.b === true.B) + chisel3.assert(outsideBundleLit.c === MyEnum.sB) + chisel3.assert(outsideBundleLit.isLit()) + chisel3.assert(outsideBundleLit.litValue().U === outsideBundleLit.asUInt()) + val bundleLit = (new MyBundle).Lit(_.a -> 42.U, _.b -> true.B, _.c -> MyEnum.sB) + chisel3.assert(bundleLit.a === 42.U) + chisel3.assert(bundleLit.b === true.B) + chisel3.assert(bundleLit.c === MyEnum.sB) + + chisel3.assert(bundleLit.a === outsideBundleLit.a) + chisel3.assert(bundleLit.b === outsideBundleLit.b) + chisel3.assert(bundleLit.c === outsideBundleLit.c) + + val bundleWire = Wire(new MyBundle) + bundleWire := outsideBundleLit + + chisel3.assert(bundleWire.a === 42.U) + chisel3.assert(bundleWire.b === true.B) + chisel3.assert(bundleWire.c === MyEnum.sB) + + stop() + } + } } "bundle literals of vec literals" should "work" in { @@ -82,11 +89,11 @@ class BundleLiteralSpec extends ChiselFlatSpec with Utils { val a = Vec(2, UInt(4.W)) val b = Vec(2, Interval(range)) }.Lit( - _.a -> Vec(2, UInt(4.W)).Lit(0 -> 0xA.U, 1 -> 0xB.U), + _.a -> Vec(2, UInt(4.W)).Lit(0 -> 0xa.U, 1 -> 0xb.U), _.b -> Vec(2, Interval(range)).Lit(0 -> (1.5).I(range), 1 -> (0.25).I(range)) ) - chisel3.assert(bundleWithVecs.a(0) === 0xA.U) - chisel3.assert(bundleWithVecs.a(1) === 0xB.U) + chisel3.assert(bundleWithVecs.a(0) === 0xa.U) + chisel3.assert(bundleWithVecs.a(1) === 0xb.U) chisel3.assert(bundleWithVecs.b(0) === (1.5).I(range)) chisel3.assert(bundleWithVecs.b(1) === (0.25).I(range)) stop() @@ -94,17 +101,19 @@ class BundleLiteralSpec extends ChiselFlatSpec with Utils { } "partial bundle literals" should "work in RTL" in { - assertTesterPasses{ new BasicTester{ - val bundleLit = (new MyBundle).Lit(_.a -> 42.U) - chisel3.assert(bundleLit.a === 42.U) + assertTesterPasses { + new BasicTester { + val bundleLit = (new MyBundle).Lit(_.a -> 42.U) + chisel3.assert(bundleLit.a === 42.U) - val bundleWire = Wire(new MyBundle) - bundleWire := bundleLit + val bundleWire = Wire(new MyBundle) + bundleWire := bundleLit - chisel3.assert(bundleWire.a === 42.U) + chisel3.assert(bundleWire.a === 42.U) - stop() - } } + stop() + } + } } class MyOuterBundle extends Bundle { @@ -118,120 +127,138 @@ class BundleLiteralSpec extends ChiselFlatSpec with Utils { } "contained bundles" should "work" in { - assertTesterPasses{ new BasicTester{ - // Specify the inner Bundle value as a Bundle literal - val explicitBundleLit = (new MyOuterBundle).Lit( - _.a -> (new MyBundle).Lit(_.a -> 42.U, _.b -> true.B, _.c -> MyEnum.sB) - ) - chisel3.assert(explicitBundleLit.a.a === 42.U) - chisel3.assert(explicitBundleLit.a.b === true.B) - chisel3.assert(explicitBundleLit.a.c === MyEnum.sB) - chisel3.assert(explicitBundleLit.a.isLit()) - chisel3.assert(explicitBundleLit.a.litValue().U === explicitBundleLit.a.asUInt()) - - // Specify the inner Bundle fields directly - val expandedBundleLit = (new MyOuterBundle).Lit( - _.a.a -> 42.U, _.a.b -> true.B, - _.b.c -> false.B, _.b.d -> 255.U, _.b.e -> MyEnum.sB, - _.f -> MyEnum.sB - ) - chisel3.assert(expandedBundleLit.a.a === 42.U) - chisel3.assert(expandedBundleLit.a.b === true.B) - chisel3.assert(expandedBundleLit.f === MyEnum.sB) - chisel3.assert(expandedBundleLit.b.c === false.B) - chisel3.assert(expandedBundleLit.b.d === 255.U) - chisel3.assert(expandedBundleLit.b.e === MyEnum.sB) - chisel3.assert(! expandedBundleLit.a.isLit()) // element e is missing - chisel3.assert(expandedBundleLit.b.isLit()) - chisel3.assert(! expandedBundleLit.isLit()) // element a.e is missing - chisel3.assert(expandedBundleLit.b.litValue().U === expandedBundleLit.b.asUInt()) - - // Anonymously contruct the inner Bundle literal - // A bit of weird syntax that depends on implementation details of the Bundle literal constructor - val childBundleLit = (new MyOuterBundle).Lit( - b => b.b -> b.b.Lit(_.c -> false.B, _.d -> 255.U, _.e -> MyEnum.sB) - ) - chisel3.assert(childBundleLit.b.c === false.B) - chisel3.assert(childBundleLit.b.d === 255.U) - chisel3.assert(childBundleLit.b.e === MyEnum.sB) - chisel3.assert(childBundleLit.b.isLit()) - chisel3.assert(! childBundleLit.isLit()) // elements a and f are missing - chisel3.assert(childBundleLit.b.litValue().U === childBundleLit.b.asUInt()) - - stop() - } } + assertTesterPasses { + new BasicTester { + // Specify the inner Bundle value as a Bundle literal + val explicitBundleLit = (new MyOuterBundle).Lit( + _.a -> (new MyBundle).Lit(_.a -> 42.U, _.b -> true.B, _.c -> MyEnum.sB) + ) + chisel3.assert(explicitBundleLit.a.a === 42.U) + chisel3.assert(explicitBundleLit.a.b === true.B) + chisel3.assert(explicitBundleLit.a.c === MyEnum.sB) + chisel3.assert(explicitBundleLit.a.isLit()) + chisel3.assert(explicitBundleLit.a.litValue().U === explicitBundleLit.a.asUInt()) + + // Specify the inner Bundle fields directly + val expandedBundleLit = (new MyOuterBundle).Lit( + _.a.a -> 42.U, + _.a.b -> true.B, + _.b.c -> false.B, + _.b.d -> 255.U, + _.b.e -> MyEnum.sB, + _.f -> MyEnum.sB + ) + chisel3.assert(expandedBundleLit.a.a === 42.U) + chisel3.assert(expandedBundleLit.a.b === true.B) + chisel3.assert(expandedBundleLit.f === MyEnum.sB) + chisel3.assert(expandedBundleLit.b.c === false.B) + chisel3.assert(expandedBundleLit.b.d === 255.U) + chisel3.assert(expandedBundleLit.b.e === MyEnum.sB) + chisel3.assert(!expandedBundleLit.a.isLit()) // element e is missing + chisel3.assert(expandedBundleLit.b.isLit()) + chisel3.assert(!expandedBundleLit.isLit()) // element a.e is missing + chisel3.assert(expandedBundleLit.b.litValue().U === expandedBundleLit.b.asUInt()) + + // Anonymously contruct the inner Bundle literal + // A bit of weird syntax that depends on implementation details of the Bundle literal constructor + val childBundleLit = + (new MyOuterBundle).Lit(b => b.b -> b.b.Lit(_.c -> false.B, _.d -> 255.U, _.e -> MyEnum.sB)) + chisel3.assert(childBundleLit.b.c === false.B) + chisel3.assert(childBundleLit.b.d === 255.U) + chisel3.assert(childBundleLit.b.e === MyEnum.sB) + chisel3.assert(childBundleLit.b.isLit()) + chisel3.assert(!childBundleLit.isLit()) // elements a and f are missing + chisel3.assert(childBundleLit.b.litValue().U === childBundleLit.b.asUInt()) + + stop() + } + } } "Bundle literals" should "assign" in { - assertTesterPasses{ new BasicTester{ - val bundleWire = Wire(Output(new MyBundle)) - val bundleLit = (new MyBundle).Lit(_.a -> 42.U, _.b -> true.B, _.c -> MyEnum.sB) - bundleWire := bundleLit - - chisel3.assert(bundleWire.a === 42.U) - chisel3.assert(bundleWire.b === true.B) - chisel3.assert(bundleWire.c === MyEnum.sB) - stop() - } } + assertTesterPasses { + new BasicTester { + val bundleWire = Wire(Output(new MyBundle)) + val bundleLit = (new MyBundle).Lit(_.a -> 42.U, _.b -> true.B, _.c -> MyEnum.sB) + bundleWire := bundleLit + + chisel3.assert(bundleWire.a === 42.U) + chisel3.assert(bundleWire.b === true.B) + chisel3.assert(bundleWire.c === MyEnum.sB) + stop() + } + } } "partially initialized Bundle literals" should "assign" in { - assertTesterPasses{ new BasicTester{ - val bundleWire = Wire(Output(new MyBundle)) - val bundleLit = (new MyBundle).Lit(_.a -> 42.U) - bundleWire := bundleLit - - chisel3.assert(bundleWire.a === 42.U) - stop() - } } + assertTesterPasses { + new BasicTester { + val bundleWire = Wire(Output(new MyBundle)) + val bundleLit = (new MyBundle).Lit(_.a -> 42.U) + bundleWire := bundleLit + + chisel3.assert(bundleWire.a === 42.U) + stop() + } + } } "Bundle literals" should "work as register reset values" in { - assertTesterPasses{ new BasicTester{ - val r = RegInit((new MyBundle).Lit(_.a -> 42.U, _.b -> true.B, _.c -> MyEnum.sB)) - r := (r.asUInt + 1.U).asTypeOf(new MyBundle) // prevent constprop - - // check reset values on first cycle out of reset - chisel3.assert(r.a === 42.U) - chisel3.assert(r.b === true.B) - chisel3.assert(r.c === MyEnum.sB) - stop() - } } + assertTesterPasses { + new BasicTester { + val r = RegInit((new MyBundle).Lit(_.a -> 42.U, _.b -> true.B, _.c -> MyEnum.sB)) + r := (r.asUInt + 1.U).asTypeOf(new MyBundle) // prevent constprop + + // check reset values on first cycle out of reset + chisel3.assert(r.a === 42.U) + chisel3.assert(r.b === true.B) + chisel3.assert(r.c === MyEnum.sB) + stop() + } + } } "partially initialized Bundle literals" should "work as register reset values" in { - assertTesterPasses{ new BasicTester{ - val r = RegInit((new MyBundle).Lit(_.a -> 42.U)) - r.a := r.a + 1.U // prevent const prop - chisel3.assert(r.a === 42.U) // coming out of reset - stop() - } } + assertTesterPasses { + new BasicTester { + val r = RegInit((new MyBundle).Lit(_.a -> 42.U)) + r.a := r.a + 1.U // prevent const prop + chisel3.assert(r.a === 42.U) // coming out of reset + stop() + } + } } "Fields extracted from BundleLiterals" should "work as register reset values" in { - assertTesterPasses{ new BasicTester{ - val r = RegInit((new MyBundle).Lit(_.a -> 42.U).a) - r := r + 1.U // prevent const prop - chisel3.assert(r === 42.U) // coming out of reset - stop() - } } + assertTesterPasses { + new BasicTester { + val r = RegInit((new MyBundle).Lit(_.a -> 42.U).a) + r := r + 1.U // prevent const prop + chisel3.assert(r === 42.U) // coming out of reset + stop() + } + } } "DontCare fields extracted from BundleLiterals" should "work as register reset values" in { - assertTesterPasses{ new BasicTester{ - val r = RegInit((new MyBundle).Lit(_.a -> 42.U).b) - r := reset.asBool - printf(p"r = $r\n") // Can't assert because reset value is DontCare - stop() - } } + assertTesterPasses { + new BasicTester { + val r = RegInit((new MyBundle).Lit(_.a -> 42.U).b) + r := reset.asBool + printf(p"r = $r\n") // Can't assert because reset value is DontCare + stop() + } + } } "DontCare fields extracted from BundleLiterals" should "work in other Expressions" in { - assertTesterPasses{ new BasicTester{ - val x = (new MyBundle).Lit(_.a -> 42.U).b || true.B - chisel3.assert(x === true.B) - stop() - } } + assertTesterPasses { + new BasicTester { + val x = (new MyBundle).Lit(_.a -> 42.U).b || true.B + chisel3.assert(x === true.B) + stop() + } + } } "bundle literals with bad field specifiers" should "fail" in { @@ -240,12 +267,12 @@ class BundleLiteralSpec extends ChiselFlatSpec with Utils { ChiselStage.elaborate { new RawModule { val bundle = new MyBundle - bundle.Lit(x => bundle.a -> 0.U) // DONT DO THIS, this gets past a syntax error to exercise the failure + bundle.Lit(x => bundle.a -> 0.U) // DONT DO THIS, this gets past a syntax error to exercise the failure } } } } - exc.getMessage should include ("not a field") + exc.getMessage should include("not a field") } "bundle literals with duplicate fields" should "fail" in { @@ -258,21 +285,22 @@ class BundleLiteralSpec extends ChiselFlatSpec with Utils { } } } - exc.getMessage should include ("duplicate") - exc.getMessage should include (".a") + exc.getMessage should include("duplicate") + exc.getMessage should include(".a") } "bundle literals with non-literal values" should "fail" in { val exc = intercept[BundleLiteralException] { extractCause[BundleLiteralException] { - ChiselStage.elaborate { new RawModule { - (new MyBundle).Lit(_.a -> UInt()) - } + ChiselStage.elaborate { + new RawModule { + (new MyBundle).Lit(_.a -> UInt()) + } } } } - exc.getMessage should include ("non-literal value") - exc.getMessage should include (".a") + exc.getMessage should include("non-literal value") + exc.getMessage should include(".a") } "bundle literals with non-type-equivalent element fields" should "fail" in { @@ -285,8 +313,8 @@ class BundleLiteralSpec extends ChiselFlatSpec with Utils { } } } - exc.getMessage should include ("non-type-equivalent value") - exc.getMessage should include (".a") + exc.getMessage should include("non-type-equivalent value") + exc.getMessage should include(".a") } "bundle literals with non-type-equivalent sub-bundles" should "fail" in { @@ -299,8 +327,8 @@ class BundleLiteralSpec extends ChiselFlatSpec with Utils { } } } - exc.getMessage should include ("non-type-equivalent value") - exc.getMessage should include (".b") + exc.getMessage should include("non-type-equivalent value") + exc.getMessage should include(".b") } "bundle literals with non-type-equivalent enum element fields" should "fail" in { @@ -313,14 +341,16 @@ class BundleLiteralSpec extends ChiselFlatSpec with Utils { } } } - exc.getMessage should include ("non-type-equivalent enum value") - exc.getMessage should include (".c") + exc.getMessage should include("non-type-equivalent enum value") + exc.getMessage should include(".c") } "partial bundle literals" should "fail to pack" in { - ChiselStage.elaborate { new RawModule { - val bundleLit = (new MyBundle).Lit(_.a -> 42.U) - bundleLit.litOption should equal (None) - } } + ChiselStage.elaborate { + new RawModule { + val bundleLit = (new MyBundle).Lit(_.a -> 42.U) + bundleLit.litOption should equal(None) + } + } } } diff --git a/src/test/scala/chiselTests/BundleSpec.scala b/src/test/scala/chiselTests/BundleSpec.scala index d9f82e6d..720f877f 100644 --- a/src/test/scala/chiselTests/BundleSpec.scala +++ b/src/test/scala/chiselTests/BundleSpec.scala @@ -61,13 +61,13 @@ class BundleSpec extends ChiselFlatSpec with BundleSpecUtils with Utils { } "Bulk connect on Bundles" should "check that the fields match" in { - (the [ChiselException] thrownBy extractCause[ChiselException] { + (the[ChiselException] thrownBy extractCause[ChiselException] { ChiselStage.elaborate { new MyModule(new BundleFooBar, new BundleFoo) } - }).getMessage should include ("Right Record missing field") + }).getMessage should include("Right Record missing field") - (the [ChiselException] thrownBy extractCause[ChiselException] { + (the[ChiselException] thrownBy extractCause[ChiselException] { ChiselStage.elaborate { new MyModule(new BundleFoo, new BundleFooBar) } - }).getMessage should include ("Left Record missing field") + }).getMessage should include("Left Record missing field") } "Bundles" should "not be able to use Seq for constructing hardware" in { @@ -120,33 +120,39 @@ class BundleSpec extends ChiselFlatSpec with BundleSpecUtils with Utils { } (the[ChiselException] thrownBy extractCause[ChiselException] { - ChiselStage.elaborate { new Module { - val io = IO(Output(new AliasedBundle)) - io.a := 0.U - io.b := 1.U - } } + ChiselStage.elaborate { + new Module { + val io = IO(Output(new AliasedBundle)) + io.a := 0.U + io.b := 1.U + } + } }).getMessage should include("contains aliased fields named (a,b),(c,d)") } "Bundles" should "not have bound hardware" in { (the[ChiselException] thrownBy extractCause[ChiselException] { - ChiselStage.elaborate { new Module { - class MyBundle(val foo: UInt) extends Bundle - val in = IO(Input(new MyBundle(123.U))) // This should error: value passed in instead of type - val out = IO(Output(new MyBundle(UInt(8.W)))) + ChiselStage.elaborate { + new Module { + class MyBundle(val foo: UInt) extends Bundle + val in = IO(Input(new MyBundle(123.U))) // This should error: value passed in instead of type + val out = IO(Output(new MyBundle(UInt(8.W)))) - out := in - } } + out := in + } + } }).getMessage should include("must be a Chisel type, not hardware") } "Bundles" should "not recursively contain aggregates with bound hardware" in { (the[ChiselException] thrownBy extractCause[ChiselException] { - ChiselStage.elaborate { new Module { - class MyBundle(val foo: UInt) extends Bundle - val out = IO(Output(Vec(2, UInt(8.W)))) - val in = IO(Input(new MyBundle(out(0)))) // This should error: Bound aggregate passed - out := in - } } + ChiselStage.elaborate { + new Module { + class MyBundle(val foo: UInt) extends Bundle + val out = IO(Output(Vec(2, UInt(8.W)))) + val in = IO(Input(new MyBundle(out(0)))) // This should error: Bound aggregate passed + out := in + } + } }).getMessage should include("must be a Chisel type, not hardware") } "Unbound bundles sharing a field" should "not error" in { diff --git a/src/test/scala/chiselTests/BundleWire.scala b/src/test/scala/chiselTests/BundleWire.scala index 830fb7e4..3b58d52a 100644 --- a/src/test/scala/chiselTests/BundleWire.scala +++ b/src/test/scala/chiselTests/BundleWire.scala @@ -11,12 +11,12 @@ class Coord extends Bundle { class BundleWire(n: Int) extends Module { val io = IO(new Bundle { - val in = Input(new Coord) + val in = Input(new Coord) val outs = Output(Vec(n, new Coord)) }) val coords = Wire(Vec(n, new Coord)) for (i <- 0 until n) { - coords(i) := io.in + coords(i) := io.in io.outs(i) := coords(i) } } @@ -57,14 +57,13 @@ class BundleWireSpec extends ChiselPropSpec { property("All vec elems should match the inputs") { forAll(vecSizes, safeUInts, safeUInts) { (n: Int, x: Int, y: Int) => - assertTesterPasses{ new BundleWireTester(n, x, y) } + assertTesterPasses { new BundleWireTester(n, x, y) } } } } class BundleToUIntSpec extends ChiselPropSpec { property("Bundles with same data but different, underlying elements should compare as UInt") { - assertTesterPasses( new BundleToUnitTester ) + assertTesterPasses(new BundleToUnitTester) } } - diff --git a/src/test/scala/chiselTests/ChiselSpec.scala b/src/test/scala/chiselTests/ChiselSpec.scala index 8647d903..6f560b94 100644 --- a/src/test/scala/chiselTests/ChiselSpec.scala +++ b/src/test/scala/chiselTests/ChiselSpec.scala @@ -4,7 +4,12 @@ package chiselTests import chisel3._ import chisel3.aop.Aspect -import chisel3.stage.{ChiselGeneratorAnnotation, ChiselStage, NoRunFirrtlCompilerAnnotation, PrintFullStackTraceAnnotation} +import chisel3.stage.{ + ChiselGeneratorAnnotation, + ChiselStage, + NoRunFirrtlCompilerAnnotation, + PrintFullStackTraceAnnotation +} import chisel3.testers._ import firrtl.annotations.Annotation import firrtl.ir.Circuit @@ -27,26 +32,29 @@ import scala.reflect.ClassTag /** Common utility functions for Chisel unit tests. */ trait ChiselRunners extends Assertions with BackendCompilationUtilities { - def runTester(t: => BasicTester, - additionalVResources: Seq[String] = Seq(), - annotations: AnnotationSeq = Seq() - ): Boolean = { + def runTester( + t: => BasicTester, + additionalVResources: Seq[String] = Seq(), + annotations: AnnotationSeq = Seq() + ): Boolean = { // Change this to enable Treadle as a backend val defaultBackend = chisel3.testers.TesterDriver.defaultBackend val hasBackend = TestUtils.containsBackend(annotations) val annos: Seq[Annotation] = if (hasBackend) annotations else defaultBackend +: annotations TesterDriver.execute(() => t, additionalVResources, annos) } - def assertTesterPasses(t: => BasicTester, - additionalVResources: Seq[String] = Seq(), - annotations: AnnotationSeq = Seq() - ): Unit = { + def assertTesterPasses( + t: => BasicTester, + additionalVResources: Seq[String] = Seq(), + annotations: AnnotationSeq = Seq() + ): Unit = { assert(runTester(t, additionalVResources, annotations)) } - def assertTesterFails(t: => BasicTester, - additionalVResources: Seq[String] = Seq(), - annotations: Seq[chisel3.aop.Aspect[_]] = Seq() - ): Unit = { + def assertTesterFails( + t: => BasicTester, + additionalVResources: Seq[String] = Seq(), + annotations: Seq[chisel3.aop.Aspect[_]] = Seq() + ): Unit = { assert(!runTester(t, additionalVResources, annotations)) } @@ -57,7 +65,7 @@ trait ChiselRunners extends Assertions with BackendCompilationUtilities { // Sanity check that firrtl doesn't change the width x := 0.U.asTypeOf(chiselTypeOf(x)) val (_, done) = chisel3.util.Counter(true.B, 2) - when (done) { + when(done) { chisel3.assert(~(x.asUInt) === -1.S(expected.W).asUInt) stop() } @@ -70,7 +78,7 @@ trait ChiselRunners extends Assertions with BackendCompilationUtilities { assert(!x.isWidthKnown, s"Asserting that width should be inferred yet width is known to Chisel!") x := 0.U.asTypeOf(chiselTypeOf(x)) val (_, done) = chisel3.util.Counter(true.B, 2) - when (done) { + when(done) { chisel3.assert(~(x.asUInt) === -1.S(expected.W).asUInt) stop() } @@ -84,11 +92,14 @@ trait ChiselRunners extends Assertions with BackendCompilationUtilities { */ def compile(t: => RawModule): String = { (new ChiselStage) - .execute(Array("--target-dir", createTestDirectory(this.getClass.getSimpleName).toString), - Seq(ChiselGeneratorAnnotation(() => t))) + .execute( + Array("--target-dir", createTestDirectory(this.getClass.getSimpleName).toString), + Seq(ChiselGeneratorAnnotation(() => t)) + ) .collectFirst { case EmittedVerilogCircuitAnnotation(a) => a.value - }.getOrElse(fail("No Verilog circuit was emitted by the FIRRTL compiler!")) + } + .getOrElse(fail("No Verilog circuit was emitted by the FIRRTL compiler!")) } def elaborateAndGetModule[A <: RawModule](t: => A): A = { @@ -147,9 +158,9 @@ abstract class ChiselPropSpec extends AnyPropSpec with ChiselRunners with ScalaC n <- Gen.choose(1, 10) } yield { if (dir) { - Range(m, (m+n)*step, step) + Range(m, (m + n) * step, step) } else { - Range((m+n)*step, m, -step) + Range((m + n) * step, m, -step) } } @@ -185,7 +196,7 @@ abstract class ChiselPropSpec extends AnyPropSpec with ChiselRunners with ScalaC w <- smallPosInts i <- Gen.containerOfN[List, Int](n, Gen.choose(0, (1 << w) - 1)) j <- Gen.containerOfN[List, Int](n, Gen.choose(0, (1 << w) - 1)) - } yield (w, i zip j) + } yield (w, i.zip(j)) // Generator which gives a width w and a pair of numbers up to w bits. val safeUIntPair = for { @@ -291,7 +302,6 @@ trait Utils { } } - /** A tester which runs generator and uses an aspect to check the returned object * @param gen function to generate a Chisel module * @param f a function to check the Chisel module @@ -300,14 +310,16 @@ trait Utils { def aspectTest[T <: RawModule](gen: () => T)(f: T => Unit)(implicit scalaMajorVersion: Int): Unit = { // Runs chisel stage def run[T <: RawModule](gen: () => T, annotations: AnnotationSeq): AnnotationSeq = { - new ChiselStage().run(Seq(ChiselGeneratorAnnotation(gen), NoRunFirrtlCompilerAnnotation, PrintFullStackTraceAnnotation) ++ annotations) + new ChiselStage().run( + Seq(ChiselGeneratorAnnotation(gen), NoRunFirrtlCompilerAnnotation, PrintFullStackTraceAnnotation) ++ annotations + ) } // Creates a wrapping aspect to contain checking function case object BuiltAspect extends Aspect[T] { - override def toAnnotation(top: T): AnnotationSeq = {f(top); Nil} + override def toAnnotation(top: T): AnnotationSeq = { f(top); Nil } } val currentMajorVersion = scala.util.Properties.versionNumberString.split('.')(1).toInt - if(currentMajorVersion >= scalaMajorVersion) { + if (currentMajorVersion >= scalaMajorVersion) { run(gen, Seq(BuiltAspect)) } } @@ -326,25 +338,27 @@ trait Utils { * @tparam A the type of the exception to extract * @return nothing */ - def extractCause[A <: Throwable : ClassTag](thunk: => Any): Unit = { + def extractCause[A <: Throwable: ClassTag](thunk: => Any): Unit = { def unrollCauses(a: Throwable): Seq[Throwable] = a match { case null => Seq.empty case _ => a +: unrollCauses(a.getCause) } - val exceptions: Seq[_ <: Throwable] = try { - thunk - Seq.empty - } catch { - case a: Throwable => unrollCauses(a) - } + val exceptions: Seq[_ <: Throwable] = + try { + thunk + Seq.empty + } catch { + case a: Throwable => unrollCauses(a) + } - exceptions.collectFirst{ case a: A => a } match { + exceptions.collectFirst { case a: A => a } match { case Some(a) => throw a - case None => exceptions match { - case Nil => () - case h :: t => throw h - } + case None => + exceptions match { + case Nil => () + case h :: t => throw h + } } } diff --git a/src/test/scala/chiselTests/ChiselTestUtilitiesSpec.scala b/src/test/scala/chiselTests/ChiselTestUtilitiesSpec.scala index 40358d11..451ba885 100644 --- a/src/test/scala/chiselTests/ChiselTestUtilitiesSpec.scala +++ b/src/test/scala/chiselTests/ChiselTestUtilitiesSpec.scala @@ -38,7 +38,7 @@ class ChiselTestUtilitiesSpec extends ChiselFlatSpec { } it should "error if the expected width is wrong" in { - a [TestFailedException] shouldBe thrownBy { + a[TestFailedException] shouldBe thrownBy { assertInferredWidth(8) { val w = Wire(UInt()) w := 2.U(2.W) diff --git a/src/test/scala/chiselTests/Clock.scala b/src/test/scala/chiselTests/Clock.scala index 3eb949fb..c28e1344 100644 --- a/src/test/scala/chiselTests/Clock.scala +++ b/src/test/scala/chiselTests/Clock.scala @@ -24,7 +24,6 @@ class WithClockAndNoReset extends RawModule { out := a } - class ClockSpec extends ChiselPropSpec { property("Bool.asClock.asUInt should pass a signal through unaltered") { assertTesterPasses { new ClockAsUIntTester } @@ -32,6 +31,6 @@ class ClockSpec extends ChiselPropSpec { property("Should be able to use withClock in a module with no reset") { val circuit = ChiselStage.emitChirrtl(new WithClockAndNoReset) - circuit.contains("reg a : UInt<1>, clock2") should be (true) + circuit.contains("reg a : UInt<1>, clock2") should be(true) } } diff --git a/src/test/scala/chiselTests/CloneModuleSpec.scala b/src/test/scala/chiselTests/CloneModuleSpec.scala index 8359bc28..4a70db85 100644 --- a/src/test/scala/chiselTests/CloneModuleSpec.scala +++ b/src/test/scala/chiselTests/CloneModuleSpec.scala @@ -4,7 +4,7 @@ package chiselTests import chisel3._ import chisel3.stage.ChiselStage -import chisel3.util.{Decoupled, Queue, EnqIO, DeqIO, QueueIO, log2Ceil} +import chisel3.util.{log2Ceil, Decoupled, DeqIO, EnqIO, Queue, QueueIO} import chisel3.experimental.{CloneModuleAsRecord, IO} import chisel3.testers.BasicTester @@ -51,7 +51,7 @@ class QueueCloneTester(x: Int, multiIO: Boolean = false) extends BasicTester { dut.io.enq.bits := x.U dut.io.enq.valid := start dut.io.deq.ready := accept - when (dut.io.deq.fire) { + when(dut.io.deq.fire) { assert(dut.io.deq.bits === x.U) stop() } @@ -80,14 +80,15 @@ class CloneModuleAsRecordAnnotate extends Module { class CloneModuleSpec extends ChiselPropSpec { val xVals = Table( - ("x"), // First tuple defines column names - (42), // Subsequent tuples define the data + ("x"), // First tuple defines column names + (42), // Subsequent tuples define the data (63), - (99)) + (99) + ) property("QueueCloneTester should return the correct result") { - forAll (xVals) { (x: Int) => - assertTesterPasses{ new QueueCloneTester(x) } + forAll(xVals) { (x: Int) => + assertTesterPasses { new QueueCloneTester(x) } } } @@ -97,13 +98,13 @@ class CloneModuleSpec extends ChiselPropSpec { } property("Clone of MultiIOModule should simulate correctly") { - forAll (xVals) { (x: Int) => - assertTesterPasses{ new QueueCloneTester(x, multiIO=true) } + forAll(xVals) { (x: Int) => + assertTesterPasses { new QueueCloneTester(x, multiIO = true) } } } property("Clones of MultiIOModules should share the same module") { - val c = ChiselStage.convert(new QueueClone(multiIO=true)) + val c = ChiselStage.convert(new QueueClone(multiIO = true)) assert(c.modules.length == 3) } @@ -116,39 +117,39 @@ class CloneModuleSpec extends ChiselPropSpec { } // ********** Checking the output of CloneModuleAsRecord ********** // Note that we overrode desiredName so that Top is named "Top" - mod.q1.io.enq.toTarget.serialize should be ("~Top|Queue>io.enq") - mod.q2_io.deq.toTarget.serialize should be ("~Top|Queue>io.deq") - mod.q1.io.enq.toAbsoluteTarget.serialize should be ("~Top|Top/q1:Queue>io.enq") - mod.q2_io.deq.toAbsoluteTarget.serialize should be ("~Top|Top/q2:Queue>io.deq") + mod.q1.io.enq.toTarget.serialize should be("~Top|Queue>io.enq") + mod.q2_io.deq.toTarget.serialize should be("~Top|Queue>io.deq") + mod.q1.io.enq.toAbsoluteTarget.serialize should be("~Top|Top/q1:Queue>io.enq") + mod.q2_io.deq.toAbsoluteTarget.serialize should be("~Top|Top/q2:Queue>io.deq") // Legacy APIs that nevertheless were tricky to get right - mod.q1.io.enq.toNamed.serialize should be ("Top.Queue.io.enq") - mod.q2_io.deq.toNamed.serialize should be ("Top.Queue.io.deq") - mod.q1.io.enq.instanceName should be ("io.enq") - mod.q2_io.deq.instanceName should be ("io.deq") - mod.q1.io.enq.pathName should be ("Top.q1.io.enq") - mod.q2_io.deq.pathName should be ("Top.q2.io.deq") - mod.q1.io.enq.parentPathName should be ("Top.q1") - mod.q2_io.deq.parentPathName should be ("Top.q2") - mod.q1.io.enq.parentModName should be ("Queue") - mod.q2_io.deq.parentModName should be ("Queue") + mod.q1.io.enq.toNamed.serialize should be("Top.Queue.io.enq") + mod.q2_io.deq.toNamed.serialize should be("Top.Queue.io.deq") + mod.q1.io.enq.instanceName should be("io.enq") + mod.q2_io.deq.instanceName should be("io.deq") + mod.q1.io.enq.pathName should be("Top.q1.io.enq") + mod.q2_io.deq.pathName should be("Top.q2.io.deq") + mod.q1.io.enq.parentPathName should be("Top.q1") + mod.q2_io.deq.parentPathName should be("Top.q2") + mod.q1.io.enq.parentModName should be("Queue") + mod.q2_io.deq.parentModName should be("Queue") // ********** Checking the wire cloned from the output of CloneModuleAsRecord ********** val wire_io = mod.q2_wire("io").asInstanceOf[QueueIO[UInt]] - mod.q2_wire.toTarget.serialize should be ("~Top|Top>q2_wire") - wire_io.enq.toTarget.serialize should be ("~Top|Top>q2_wire.io.enq") - mod.q2_wire.toAbsoluteTarget.serialize should be ("~Top|Top>q2_wire") - wire_io.enq.toAbsoluteTarget.serialize should be ("~Top|Top>q2_wire.io.enq") + mod.q2_wire.toTarget.serialize should be("~Top|Top>q2_wire") + wire_io.enq.toTarget.serialize should be("~Top|Top>q2_wire.io.enq") + mod.q2_wire.toAbsoluteTarget.serialize should be("~Top|Top>q2_wire") + wire_io.enq.toAbsoluteTarget.serialize should be("~Top|Top>q2_wire.io.enq") // Legacy APIs - mod.q2_wire.toNamed.serialize should be ("Top.Top.q2_wire") - wire_io.enq.toNamed.serialize should be ("Top.Top.q2_wire.io.enq") - mod.q2_wire.instanceName should be ("q2_wire") - wire_io.enq.instanceName should be ("q2_wire.io.enq") - mod.q2_wire.pathName should be ("Top.q2_wire") - wire_io.enq.pathName should be ("Top.q2_wire.io.enq") - mod.q2_wire.parentPathName should be ("Top") - wire_io.enq.parentPathName should be ("Top") - mod.q2_wire.parentModName should be ("Top") - wire_io.enq.parentModName should be ("Top") + mod.q2_wire.toNamed.serialize should be("Top.Top.q2_wire") + wire_io.enq.toNamed.serialize should be("Top.Top.q2_wire.io.enq") + mod.q2_wire.instanceName should be("q2_wire") + wire_io.enq.instanceName should be("q2_wire.io.enq") + mod.q2_wire.pathName should be("Top.q2_wire") + wire_io.enq.pathName should be("Top.q2_wire.io.enq") + mod.q2_wire.parentPathName should be("Top") + wire_io.enq.parentPathName should be("Top") + mod.q2_wire.parentModName should be("Top") + wire_io.enq.parentModName should be("Top") } } diff --git a/src/test/scala/chiselTests/CompatibilityInteroperabilitySpec.scala b/src/test/scala/chiselTests/CompatibilityInteroperabilitySpec.scala index 4b03dfa5..8210b120 100644 --- a/src/test/scala/chiselTests/CompatibilityInteroperabilitySpec.scala +++ b/src/test/scala/chiselTests/CompatibilityInteroperabilitySpec.scala @@ -114,7 +114,6 @@ class CompatibiltyInteroperabilitySpec extends ChiselFlatSpec { }) } - "Bundles defined in Chisel._" should "work in chisel3._ Modules" in { import chisel3._ import chisel3.testers.BasicTester @@ -153,9 +152,8 @@ class CompatibiltyInteroperabilitySpec extends ChiselFlatSpec { }) } - "Similar Bundles defined in the chisel3._ and Chisel._" should - "successfully bulk connect in chisel3._" in { + "successfully bulk connect in chisel3._" in { import chisel3._ import chisel3.testers.BasicTester import Chisel3Components._ @@ -227,12 +225,11 @@ class CompatibiltyInteroperabilitySpec extends ChiselFlatSpec { val cond = Bool(INPUT) val out = UInt(OUTPUT, width = 32) } - val children = Seq(Module(new PassthroughModule), - Module(new PassthroughMultiIOModule), - Module(new PassthroughRawModule)) + val children = + Seq(Module(new PassthroughModule), Module(new PassthroughMultiIOModule), Module(new PassthroughRawModule)) io.out := children.map(_.io.out).reduce(_ + _) children.foreach { child => - when (io.cond) { + when(io.cond) { child.io.in := io.in } } @@ -355,4 +352,3 @@ class CompatibiltyInteroperabilitySpec extends ChiselFlatSpec { compile(new Top(false)) } } - diff --git a/src/test/scala/chiselTests/CompatibilitySpec.scala b/src/test/scala/chiselTests/CompatibilitySpec.scala index 7ac67b7c..d134c380 100644 --- a/src/test/scala/chiselTests/CompatibilitySpec.scala +++ b/src/test/scala/chiselTests/CompatibilitySpec.scala @@ -23,7 +23,7 @@ object CompatibilityCustomCompileOptions { class CompatibiltySpec extends ChiselFlatSpec with ScalaCheckDrivenPropertyChecks with Utils { import Chisel._ - behavior of "Chisel compatibility layer" + behavior.of("Chisel compatibility layer") it should "accept direction arguments" in { ChiselStage.elaborate(new Module { @@ -39,10 +39,10 @@ class CompatibiltySpec extends ChiselFlatSpec with ScalaCheckDrivenPropertyCheck val b = Bool(directionArgument) val u = UInt(directionArgument, width) } - io.b shouldBe a [Bool] + io.b shouldBe a[Bool] io.b.getWidth shouldEqual 1 io.b.dir shouldEqual (expectedDirection) - io.u shouldBe a [UInt] + io.u shouldBe a[UInt] io.u.getWidth shouldEqual width io.u.dir shouldEqual (expectedDirection) }) @@ -52,7 +52,7 @@ class CompatibiltySpec extends ChiselFlatSpec with ScalaCheckDrivenPropertyCheck // Choose a random value val value: Int = Gen.choose(0, Int.MaxValue).sample.get val l = UInt(value) - l shouldBe a [UInt] + l shouldBe a[UInt] l shouldBe 'lit l.getWidth shouldEqual BigInt(value).bitLength l.litValue() shouldEqual value @@ -60,9 +60,10 @@ class CompatibiltySpec extends ChiselFlatSpec with ScalaCheckDrivenPropertyCheck it should "map utility objects into the package object" in { val value: Int = Gen.choose(2, 2048).sample.get - log2Up(value) shouldBe (1 max BigInt(value - 1).bitLength) + log2Up(value) shouldBe (1.max(BigInt(value - 1).bitLength)) log2Ceil(value) shouldBe (BigInt(value - 1).bitLength) - log2Down(value) shouldBe ((1 max BigInt(value - 1).bitLength) - (if (value > 0 && ((value & (value - 1)) == 0)) 0 else 1)) + log2Down(value) shouldBe ((1.max(BigInt(value - 1).bitLength)) - (if (value > 0 && ((value & (value - 1)) == 0)) 0 + else 1)) log2Floor(value) shouldBe (BigInt(value - 1).bitLength - (if (value > 0 && ((value & (value - 1)) == 0)) 0 else 1)) isPow2(BigInt(1) << value) shouldBe true isPow2((BigInt(1) << value) - 1) shouldBe false @@ -76,7 +77,7 @@ class CompatibiltySpec extends ChiselFlatSpec with ScalaCheckDrivenPropertyCheck bs(maskPosition) = '?' val bitPatString = bs.toString val bp = BitPat("b" + bitPatString) - bp shouldBe a [BitPat] + bp shouldBe a[BitPat] bp.getWidth shouldEqual binaryString.length } @@ -87,92 +88,92 @@ class CompatibiltySpec extends ChiselFlatSpec with ScalaCheckDrivenPropertyCheck val io = new Bundle {} val data = UInt(width = 3) val wire = Wire(data) - new ArbiterIO(data, 2) shouldBe a [ArbiterIO[UInt]] - Module(new LockingRRArbiter(data, 2, 2, None)) shouldBe a [LockingRRArbiter[UInt]] - Module(new RRArbiter(data, 2)) shouldBe a [RRArbiter[UInt]] - Module(new Arbiter(data, 2)) shouldBe a [Arbiter[UInt]] - new Counter(2) shouldBe a [Counter] - new ValidIO(data) shouldBe a [ValidIO[UInt]] - new DecoupledIO(data) shouldBe a [DecoupledIO[UInt]] - new QueueIO(data, 2) shouldBe a [QueueIO[UInt]] - Module(new Pipe(data, 2)) shouldBe a [Pipe[UInt]] - - FillInterleaved(2, wire) shouldBe a [UInt] - PopCount(wire) shouldBe a [UInt] - Fill(2, wire) shouldBe a [UInt] - Reverse(wire) shouldBe a [UInt] - Cat(wire, wire) shouldBe a [UInt] - Log2(wire) shouldBe a [UInt] + new ArbiterIO(data, 2) shouldBe a[ArbiterIO[UInt]] + Module(new LockingRRArbiter(data, 2, 2, None)) shouldBe a[LockingRRArbiter[UInt]] + Module(new RRArbiter(data, 2)) shouldBe a[RRArbiter[UInt]] + Module(new Arbiter(data, 2)) shouldBe a[Arbiter[UInt]] + new Counter(2) shouldBe a[Counter] + new ValidIO(data) shouldBe a[ValidIO[UInt]] + new DecoupledIO(data) shouldBe a[DecoupledIO[UInt]] + new QueueIO(data, 2) shouldBe a[QueueIO[UInt]] + Module(new Pipe(data, 2)) shouldBe a[Pipe[UInt]] + + FillInterleaved(2, wire) shouldBe a[UInt] + PopCount(wire) shouldBe a[UInt] + Fill(2, wire) shouldBe a[UInt] + Reverse(wire) shouldBe a[UInt] + Cat(wire, wire) shouldBe a[UInt] + Log2(wire) shouldBe a[UInt] // 'switch' and 'is' are tested below in Risc - Counter(2) shouldBe a [Counter] - DecoupledIO(wire) shouldBe a [DecoupledIO[UInt]] + Counter(2) shouldBe a[Counter] + DecoupledIO(wire) shouldBe a[DecoupledIO[UInt]] val dcd = Wire(Decoupled(data)) - dcd shouldBe a [DecoupledIO[UInt]] - Queue(dcd) shouldBe a [DecoupledIO[UInt]] - Queue(dcd, 0) shouldBe a [DecoupledIO[UInt]] - Enum(UInt(), 2) shouldBe a [List[UInt]] - ListLookup(wire, List(wire), Array((BitPat("b1"), List(wire)))) shouldBe a [List[UInt]] - Lookup(wire, wire, Seq((BitPat("b1"), wire))) shouldBe a [UInt] - Mux1H(wire, Seq(wire)) shouldBe a [UInt] - PriorityMux(Seq(Bool(false)), Seq(data)) shouldBe a [UInt] - MuxLookup(wire, wire, Seq((wire, wire))) shouldBe a [UInt] - MuxCase(wire, Seq((Bool(true), wire))) shouldBe a [UInt] - OHToUInt(wire) shouldBe a [UInt] - PriorityEncoder(wire) shouldBe a [UInt] - UIntToOH(wire) shouldBe a [UInt] - PriorityEncoderOH(wire) shouldBe a [UInt] - RegNext(wire) shouldBe a [UInt] - RegInit(wire) shouldBe a [UInt] - RegEnable(wire, Bool(true)) shouldBe a [UInt] - ShiftRegister(wire, 2) shouldBe a [UInt] - Valid(data) shouldBe a [ValidIO[UInt]] - Pipe(Wire(Valid(data)), 2) shouldBe a [ValidIO[UInt]] + dcd shouldBe a[DecoupledIO[UInt]] + Queue(dcd) shouldBe a[DecoupledIO[UInt]] + Queue(dcd, 0) shouldBe a[DecoupledIO[UInt]] + Enum(UInt(), 2) shouldBe a[List[UInt]] + ListLookup(wire, List(wire), Array((BitPat("b1"), List(wire)))) shouldBe a[List[UInt]] + Lookup(wire, wire, Seq((BitPat("b1"), wire))) shouldBe a[UInt] + Mux1H(wire, Seq(wire)) shouldBe a[UInt] + PriorityMux(Seq(Bool(false)), Seq(data)) shouldBe a[UInt] + MuxLookup(wire, wire, Seq((wire, wire))) shouldBe a[UInt] + MuxCase(wire, Seq((Bool(true), wire))) shouldBe a[UInt] + OHToUInt(wire) shouldBe a[UInt] + PriorityEncoder(wire) shouldBe a[UInt] + UIntToOH(wire) shouldBe a[UInt] + PriorityEncoderOH(wire) shouldBe a[UInt] + RegNext(wire) shouldBe a[UInt] + RegInit(wire) shouldBe a[UInt] + RegEnable(wire, Bool(true)) shouldBe a[UInt] + ShiftRegister(wire, 2) shouldBe a[UInt] + Valid(data) shouldBe a[ValidIO[UInt]] + Pipe(Wire(Valid(data)), 2) shouldBe a[ValidIO[UInt]] } ChiselStage.elaborate { new Dummy } } // Verify we can elaborate a design expressed in Chisel2 class Chisel2CompatibleRisc extends Module { val io = new Bundle { - val isWr = Bool(INPUT) + val isWr = Bool(INPUT) val wrAddr = UInt(INPUT, 8) val wrData = Bits(INPUT, 32) - val boot = Bool(INPUT) - val valid = Bool(OUTPUT) - val out = Bits(OUTPUT, 32) + val boot = Bool(INPUT) + val valid = Bool(OUTPUT) + val out = Bits(OUTPUT, 32) } val file = Mem(256, Bits(width = 32)) val code = Mem(256, Bits(width = 32)) - val pc = Reg(init=UInt(0, 8)) + val pc = Reg(init = UInt(0, 8)) val add_op :: imm_op :: Nil = Enum(2) val inst = code(pc) - val op = inst(31,24) - val rci = inst(23,16) - val rai = inst(15, 8) - val rbi = inst( 7, 0) + val op = inst(31, 24) + val rci = inst(23, 16) + val rai = inst(15, 8) + val rbi = inst(7, 0) val ra = Mux(rai === Bits(0), Bits(0), file(rai)) val rb = Mux(rbi === Bits(0), Bits(0), file(rbi)) val rc = Wire(Bits(width = 32)) io.valid := Bool(false) - io.out := Bits(0) - rc := Bits(0) + io.out := Bits(0) + rc := Bits(0) - when (io.isWr) { + when(io.isWr) { code(io.wrAddr) := io.wrData - } .elsewhen (io.boot) { + }.elsewhen(io.boot) { pc := UInt(0) - } .otherwise { + }.otherwise { switch(op) { is(add_op) { rc := ra +% rb } is(imm_op) { rc := (rai << 8) | rbi } } io.out := rc - when (rci === UInt(255)) { + when(rci === UInt(255)) { io.valid := Bool(true) - } .otherwise { + }.otherwise { file(rci) := rc } pc := pc +% UInt(1) @@ -191,7 +192,6 @@ class CompatibiltySpec extends ChiselFlatSpec with ScalaCheckDrivenPropertyCheck }) } - class SmallBundle extends Bundle { val f1 = UInt(width = 4) val f2 = UInt(width = 5) @@ -219,7 +219,7 @@ class CompatibiltySpec extends ChiselFlatSpec with ScalaCheckDrivenPropertyCheck val in = (new SmallBundle).asInput val out = (new BigBundle).asOutput } - val badReg = Reg(UInt(7, width=4)) + val badReg = Reg(UInt(7, width = 4)) } ChiselStage.elaborate { new CreateRegFromBoundTypeModule() } } @@ -302,9 +302,9 @@ class CompatibiltySpec extends ChiselFlatSpec with ScalaCheckDrivenPropertyCheck // Note: This is a regression (see https://github.com/freechipsproject/chisel3/issues/668) it should "fail for Chisel types" in { import Chisel._ - an [chisel3.ExpectedHardwareException] should be thrownBy extractCause[chisel3.ExpectedHardwareException] { + an[chisel3.ExpectedHardwareException] should be thrownBy extractCause[chisel3.ExpectedHardwareException] { ChiselStage.elaborate(new Module { - val io = new Bundle { } + val io = new Bundle {} UInt(INPUT).dir }) } @@ -342,11 +342,11 @@ class CompatibiltySpec extends ChiselFlatSpec with ScalaCheckDrivenPropertyCheck }) } - behavior of "BitPat" + behavior.of("BitPat") it should "support old operators" in { class Foo extends Module { - val io = IO(new Bundle{}) + val io = IO(new Bundle {}) info("Deprecated method DC hasn't been removed") val bp = BitPat.DC(4) @@ -355,34 +355,34 @@ class CompatibiltySpec extends ChiselFlatSpec with ScalaCheckDrivenPropertyCheck ChiselStage.elaborate(new Foo) } - behavior of "Enum" + behavior.of("Enum") it should "support apply[T <: Bits](nodeType: T, n: Int): List[T]" in { class Foo extends Module { - val io = IO(new Bundle{}) + val io = IO(new Bundle {}) info("works for a UInt") - Enum(UInt(), 4) shouldBe a [List[UInt]] + Enum(UInt(), 4) shouldBe a[List[UInt]] info("throw an exception for non-UInt types") - intercept [IllegalArgumentException] { + intercept[IllegalArgumentException] { Enum(SInt(), 4) - }.getMessage should include ("Only UInt supported for enums") + }.getMessage should include("Only UInt supported for enums") info("throw an exception if the bit width is specified") - intercept [IllegalArgumentException] { + intercept[IllegalArgumentException] { Enum(UInt(width = 8), 4) - }.getMessage should include ("Bit width may no longer be specified for enums") + }.getMessage should include("Bit width may no longer be specified for enums") } ChiselStage.elaborate(new Foo) } - behavior of "Queue" + behavior.of("Queue") it should "support deprecated constructors" in { class Foo extends Module { - val io = IO(new Bundle{}) + val io = IO(new Bundle {}) info("reset: Option[Bool] constructor works") val option = Module(new Queue(UInt(), 4, false, false, Some(Bool(true)))) @@ -394,56 +394,56 @@ class CompatibiltySpec extends ChiselFlatSpec with ScalaCheckDrivenPropertyCheck ChiselStage.elaborate(new Foo) } - behavior of "LFSR16" + behavior.of("LFSR16") it should "still exist" in { class Foo extends Module { - val io = IO(new Bundle{}) + val io = IO(new Bundle {}) info("Still exists") val lfsr = LFSR16() info("apply method returns a UInt") - lfsr shouldBe a [UInt] + lfsr shouldBe a[UInt] info("returned UInt has a width of 16") - lfsr.getWidth should be (16) + lfsr.getWidth should be(16) } ChiselStage.elaborate(new Foo) } - behavior of "Mem" + behavior.of("Mem") it should "support deprecated apply methods" in { class Foo extends Module { - val io = IO(new Bundle{}) + val io = IO(new Bundle {}) info("apply[T <: Data](t: T, size: BigInt): Mem[T] works") val memBigInt = Mem(UInt(), 8: BigInt) - memBigInt shouldBe a [Mem[UInt]] + memBigInt shouldBe a[Mem[UInt]] info("apply[T <: Data](t: T, size: Int): Mem[T] works") val memInt = Mem(SInt(), 16: Int) - memInt shouldBe a [Mem[SInt]] + memInt shouldBe a[Mem[SInt]] } ChiselStage.elaborate(new Foo) } - behavior of "SeqMem" + behavior.of("SeqMem") it should "support deprecated apply methods" in { class Foo extends Module { - val io = IO(new Bundle{}) + val io = IO(new Bundle {}) info("apply[T <: Data](t: T, size: BigInt): SeqMem[T] works") val seqMemBigInt = SeqMem(UInt(), 8: BigInt) - seqMemBigInt shouldBe a [SeqMem[UInt]] + seqMemBigInt shouldBe a[SeqMem[UInt]] info("apply[T <: Data](t: T, size: Int): SeqMem[T] works") val seqMemInt = SeqMem(UInt(), 16: Int) - seqMemInt shouldBe a [SeqMem[UInt]] + seqMemInt shouldBe a[SeqMem[UInt]] } ChiselStage.elaborate(new Foo) @@ -461,11 +461,11 @@ class CompatibiltySpec extends ChiselFlatSpec with ScalaCheckDrivenPropertyCheck ChiselStage.elaborate((new Foo)) } - behavior of "debug" + behavior.of("debug") it should "still exist" in { class Foo extends Module { - val io = IO(new Bundle{}) + val io = IO(new Bundle {}) val data = UInt(width = 2) debug(data) @@ -474,35 +474,35 @@ class CompatibiltySpec extends ChiselFlatSpec with ScalaCheckDrivenPropertyCheck ChiselStage.elaborate(new Foo) } - behavior of "Data methods" + behavior.of("Data methods") - behavior of "Wire" + behavior.of("Wire") it should "support legacy methods" in { class Foo extends Module { - val io = IO(new Bundle{}) + val io = IO(new Bundle {}) info("apply[T <: Data](dummy: Int = 0, init: T): T works") - val first = Wire(init=UInt("hdeadbeef")) - first shouldBe a [UInt] + val first = Wire(init = UInt("hdeadbeef")) + first shouldBe a[UInt] info("apply[T <: Data](t: T, init: T): T works") val second = Wire(SInt(), SInt(-100)) - second shouldBe a [SInt] + second shouldBe a[SInt] info("apply[T <: Data](t: T, init: DontCare.type): T works") val third = Wire(UInt(), chisel3.DontCare) - third shouldBe a [UInt] + third shouldBe a[UInt] } ChiselStage.elaborate(new Foo) } - behavior of "Vec" + behavior.of("Vec") it should "support legacy methods" in { class Foo extends BasicTester { - val seq = Seq(Wire(UInt(0, width=4)), Wire(UInt(1, width=4)), Wire(UInt(2, width=4))) + val seq = Seq(Wire(UInt(0, width = 4)), Wire(UInt(1, width = 4)), Wire(UInt(2, width = 4))) val vec = Vec(seq) info("read works") @@ -513,32 +513,32 @@ class CompatibiltySpec extends ChiselFlatSpec with ScalaCheckDrivenPropertyCheck chisel3.assert(vec.read(UInt(1)) === UInt(3)) val (_, done) = Counter(Bool(true), 4) - when (done) { stop } + when(done) { stop } } assertTesterPasses(new Foo) } - behavior of "Bits methods" + behavior.of("Bits methods") it should "support legacy methods" in { class Foo extends Module { - val io = new Bundle{} + val io = new Bundle {} val u = UInt(8) val s = SInt(-4) info("asBits works") - s.asBits shouldBe a [Bits] + s.asBits shouldBe a[Bits] info("toSInt works") - u.toSInt shouldBe a [SInt] + u.toSInt shouldBe a[SInt] info("toUInt works") - s.toUInt shouldBe a [UInt] + s.toUInt shouldBe a[UInt] info("toBools works") - s.toBools shouldBe a [Seq[Bool]] + s.toBools shouldBe a[Seq[Bool]] } ChiselStage.elaborate(new Foo) @@ -547,8 +547,8 @@ class CompatibiltySpec extends ChiselFlatSpec with ScalaCheckDrivenPropertyCheck it should "properly propagate custom compileOptions in Chisel.Module" in { import CompatibilityCustomCompileOptions._ var result: Foo = null - ChiselStage.elaborate({result = new Foo; result}) - result.compileOptions should be theSameInstanceAs (customCompileOptions) + ChiselStage.elaborate({ result = new Foo; result }) + (result.compileOptions should be).theSameInstanceAs(customCompileOptions) } it should "properly set the refs of Records" in { @@ -564,7 +564,7 @@ class CompatibiltySpec extends ChiselFlatSpec with ScalaCheckDrivenPropertyCheck } val verilog = ChiselStage.emitVerilog(new Foo) // Check that the names are correct (and that the FIRRTL is valid) - verilog should include ("assign io_out_0 = io_in_0;") + verilog should include("assign io_out_0 = io_in_0;") } it should "ignore .suggestName on field io" in { @@ -577,8 +577,8 @@ class CompatibiltySpec extends ChiselFlatSpec with ScalaCheckDrivenPropertyCheck io.bar := io.foo } val verilog = ChiselStage.emitVerilog(new MyModule) - verilog should include ("input [7:0] io_foo") - verilog should include ("output [7:0] io_bar") + verilog should include("input [7:0] io_foo") + verilog should include("output [7:0] io_bar") } it should "properly name field io" in { @@ -591,8 +591,8 @@ class CompatibiltySpec extends ChiselFlatSpec with ScalaCheckDrivenPropertyCheck io.bar := wire } val verilog = ChiselStage.emitVerilog(new MyModule) - verilog should include ("input [7:0] io_foo") - verilog should include ("output [7:0] io_bar") + verilog should include("input [7:0] io_foo") + verilog should include("output [7:0] io_bar") } } diff --git a/src/test/scala/chiselTests/CompileOptionsTest.scala b/src/test/scala/chiselTests/CompileOptionsTest.scala index 1ecf97f0..3ec59954 100644 --- a/src/test/scala/chiselTests/CompileOptionsTest.scala +++ b/src/test/scala/chiselTests/CompileOptionsTest.scala @@ -20,7 +20,7 @@ class CompileOptionsSpec extends ChiselFlatSpec with Utils { } "A Module with missing bundle fields when compiled with implicit Strict.CompileOption " should "throw an exception" in { - a [ChiselException] should be thrownBy extractCause[ChiselException] { + a[ChiselException] should be thrownBy extractCause[ChiselException] { import chisel3.ExplicitCompileOptions.Strict class ConnectFieldMismatchModule extends Module { @@ -48,7 +48,7 @@ class CompileOptionsSpec extends ChiselFlatSpec with Utils { } "A Module in which a Reg is created with a bound type when compiled with implicit Strict.CompileOption " should "throw an exception" in { - a [BindingException] should be thrownBy extractCause[BindingException] { + a[BindingException] should be thrownBy extractCause[BindingException] { import chisel3.ExplicitCompileOptions.Strict class CreateRegFromBoundTypeModule extends Module { @@ -89,7 +89,7 @@ class CompileOptionsSpec extends ChiselFlatSpec with Utils { } "A Module with unwrapped IO when compiled with implicit Strict.CompileOption " should "throw an exception" in { - a [BindingException] should be thrownBy extractCause[BindingException] { + a[BindingException] should be thrownBy extractCause[BindingException] { import chisel3.ExplicitCompileOptions.Strict class RequireIOWrapModule extends Module { @@ -106,7 +106,7 @@ class CompileOptionsSpec extends ChiselFlatSpec with Utils { } "A Module connecting output as source to input as sink when compiled with implicit Strict.CompileOption " should "throw an exception" in { - a [ChiselException] should be thrownBy extractCause[ChiselException] { + a[ChiselException] should be thrownBy extractCause[ChiselException] { import chisel3.ExplicitCompileOptions.Strict class SimpleModule extends Module { @@ -140,7 +140,7 @@ class CompileOptionsSpec extends ChiselFlatSpec with Utils { } "A Module with directionless connections when compiled with implicit Strict.CompileOption " should "throw an exception" in { - a [ChiselException] should be thrownBy extractCause[ChiselException] { + a[ChiselException] should be thrownBy extractCause[ChiselException] { // Verify we can suppress the inclusion of default compileOptions import Chisel.{defaultCompileOptions => _} import chisel3.ExplicitCompileOptions.Strict diff --git a/src/test/scala/chiselTests/ComplexAssign.scala b/src/test/scala/chiselTests/ComplexAssign.scala index 222b6373..99313967 100644 --- a/src/test/scala/chiselTests/ComplexAssign.scala +++ b/src/test/scala/chiselTests/ComplexAssign.scala @@ -11,16 +11,16 @@ class Complex[T <: Data](val re: T, val im: T) extends Bundle class ComplexAssign(w: Int) extends Module { val io = IO(new Bundle { - val e = Input(Bool()) - val in = Input(new Complex(UInt(w.W), UInt(w.W))) + val e = Input(Bool()) + val in = Input(new Complex(UInt(w.W), UInt(w.W))) val out = Output(new Complex(UInt(w.W), UInt(w.W))) }) - when (io.e) { + when(io.e) { val tmp = Wire(new Complex(UInt(w.W), UInt(w.W))) tmp := io.in io.out.re := tmp.re io.out.im := tmp.im - } .otherwise { + }.otherwise { io.out.re := 0.U io.out.im := 0.U } @@ -46,7 +46,7 @@ class ComplexAssignSpec extends ChiselPropSpec { implicit val noShrinkListVal = Shrink[List[Boolean]](_ => Stream.empty) implicit val noShrinkInt = Shrink[Int](_ => Stream.empty) forAll(enSequence(2), safeUInts, safeUInts) { (en: List[Boolean], re: Int, im: Int) => - assertTesterPasses{ new ComplexAssignTester(en, re, im) } + assertTesterPasses { new ComplexAssignTester(en, re, im) } } } } diff --git a/src/test/scala/chiselTests/ConnectSpec.scala b/src/test/scala/chiselTests/ConnectSpec.scala index f9ef5946..3a2b6d93 100644 --- a/src/test/scala/chiselTests/ConnectSpec.scala +++ b/src/test/scala/chiselTests/ConnectSpec.scala @@ -10,7 +10,7 @@ import chisel3.stage.ChiselStage import chisel3.testers.BasicTester abstract class CrossCheck extends Bundle { - val in: Data + val in: Data val out: Data } @@ -41,92 +41,120 @@ class CrossConnectTester(inType: Data, outType: Data) extends BasicTester { class ConnectSpec extends ChiselPropSpec with Utils { property("SInt := SInt should succeed") { - assertTesterPasses{ new CrossConnectTester(SInt(16.W), SInt(16.W)) } + assertTesterPasses { new CrossConnectTester(SInt(16.W), SInt(16.W)) } } property("SInt := UInt should fail") { - intercept[ChiselException]{ + intercept[ChiselException] { extractCause[ChiselException] { - ChiselStage.elaborate { new CrossConnectTester(UInt(16.W), SInt(16.W)) } } } + ChiselStage.elaborate { new CrossConnectTester(UInt(16.W), SInt(16.W)) } + } + } } property("SInt := FixedPoint should fail") { - intercept[ChiselException]{ + intercept[ChiselException] { extractCause[ChiselException] { - ChiselStage.elaborate { new CrossConnectTester(FixedPoint(16.W, 8.BP), UInt(16.W)) } } } + ChiselStage.elaborate { new CrossConnectTester(FixedPoint(16.W, 8.BP), UInt(16.W)) } + } + } } property("UInt := UInt should succeed") { - assertTesterPasses{ new CrossConnectTester(UInt(16.W), UInt(16.W)) } + assertTesterPasses { new CrossConnectTester(UInt(16.W), UInt(16.W)) } } property("UInt := SInt should fail") { - intercept[ChiselException]{ + intercept[ChiselException] { extractCause[ChiselException] { - ChiselStage.elaborate { new CrossConnectTester(SInt(16.W), UInt(16.W)) } } } + ChiselStage.elaborate { new CrossConnectTester(SInt(16.W), UInt(16.W)) } + } + } } property("UInt := FixedPoint should fail") { - intercept[ChiselException]{ + intercept[ChiselException] { extractCause[ChiselException] { - ChiselStage.elaborate { new CrossConnectTester(FixedPoint(16.W, 8.BP), UInt(16.W)) } } } + ChiselStage.elaborate { new CrossConnectTester(FixedPoint(16.W, 8.BP), UInt(16.W)) } + } + } } property("Clock := Clock should succeed") { - assertTesterPasses{ new CrossConnectTester(Clock(), Clock()) } + assertTesterPasses { new CrossConnectTester(Clock(), Clock()) } } property("Clock := UInt should fail") { - intercept[ChiselException]{ + intercept[ChiselException] { extractCause[ChiselException] { - ChiselStage.elaborate { new CrossConnectTester(Clock(), UInt(16.W)) } } } + ChiselStage.elaborate { new CrossConnectTester(Clock(), UInt(16.W)) } + } + } } property("FixedPoint := FixedPoint should succeed") { - assertTesterPasses{ new CrossConnectTester(FixedPoint(16.W, 8.BP), FixedPoint(16.W, 8.BP)) } + assertTesterPasses { new CrossConnectTester(FixedPoint(16.W, 8.BP), FixedPoint(16.W, 8.BP)) } } property("FixedPoint := SInt should fail") { - intercept[ChiselException]{ + intercept[ChiselException] { extractCause[ChiselException] { - ChiselStage.elaborate { new CrossConnectTester(SInt(16.W), FixedPoint(16.W, 8.BP)) } } } + ChiselStage.elaborate { new CrossConnectTester(SInt(16.W), FixedPoint(16.W, 8.BP)) } + } + } } property("FixedPoint := UInt should fail") { - intercept[ChiselException]{ + intercept[ChiselException] { extractCause[ChiselException] { - ChiselStage.elaborate { new CrossConnectTester(UInt(16.W), FixedPoint(16.W, 8.BP)) } } } + ChiselStage.elaborate { new CrossConnectTester(UInt(16.W), FixedPoint(16.W, 8.BP)) } + } + } } property("Analog := Analog should fail") { - intercept[ChiselException]{ + intercept[ChiselException] { extractCause[ChiselException] { - ChiselStage.elaborate { new CrossConnectTester(Analog(16.W), Analog(16.W)) } } } + ChiselStage.elaborate { new CrossConnectTester(Analog(16.W), Analog(16.W)) } + } + } } property("Analog := FixedPoint should fail") { - intercept[ChiselException]{ + intercept[ChiselException] { extractCause[ChiselException] { - ChiselStage.elaborate { new CrossConnectTester(Analog(16.W), FixedPoint(16.W, 8.BP)) } } } + ChiselStage.elaborate { new CrossConnectTester(Analog(16.W), FixedPoint(16.W, 8.BP)) } + } + } } property("FixedPoint := Analog should fail") { - intercept[ChiselException]{ + intercept[ChiselException] { extractCause[ChiselException] { - ChiselStage.elaborate { new CrossConnectTester(FixedPoint(16.W, 8.BP), Analog(16.W)) } } } + ChiselStage.elaborate { new CrossConnectTester(FixedPoint(16.W, 8.BP), Analog(16.W)) } + } + } } property("Analog := UInt should fail") { - intercept[ChiselException]{ + intercept[ChiselException] { extractCause[ChiselException] { - ChiselStage.elaborate { new CrossConnectTester(Analog(16.W), UInt(16.W)) } } } + ChiselStage.elaborate { new CrossConnectTester(Analog(16.W), UInt(16.W)) } + } + } } property("Analog := SInt should fail") { - intercept[ChiselException]{ + intercept[ChiselException] { extractCause[ChiselException] { - ChiselStage.elaborate { new CrossConnectTester(Analog(16.W), SInt(16.W)) } } } + ChiselStage.elaborate { new CrossConnectTester(Analog(16.W), SInt(16.W)) } + } + } } property("UInt := Analog should fail") { - intercept[ChiselException]{ + intercept[ChiselException] { extractCause[ChiselException] { - ChiselStage.elaborate { new CrossConnectTester(UInt(16.W), Analog(16.W)) } } } + ChiselStage.elaborate { new CrossConnectTester(UInt(16.W), Analog(16.W)) } + } + } } property("SInt := Analog should fail") { - intercept[ChiselException]{ + intercept[ChiselException] { extractCause[ChiselException] { - ChiselStage.elaborate { new CrossConnectTester(SInt(16.W), Analog(16.W)) } } } + ChiselStage.elaborate { new CrossConnectTester(SInt(16.W), Analog(16.W)) } + } + } } property("Pipe internal connections should succeed") { - ChiselStage.elaborate( new PipeInternalWires) + ChiselStage.elaborate(new PipeInternalWires) } property("Connect error messages should have meaningful information") { @@ -139,9 +167,9 @@ class ConnectSpec extends ChiselPropSpec with Utils { inner.myReg := false.B // ERROR } - val assignError = the [ChiselException] thrownBy {ChiselStage.elaborate { new OuterAssignExample}} + val assignError = the[ChiselException] thrownBy { ChiselStage.elaborate { new OuterAssignExample } } val expectedAssignError = """.*@: myReg in InnerExample cannot be written from module OuterAssignExample.""" - assignError.getMessage should fullyMatch regex expectedAssignError + (assignError.getMessage should fullyMatch).regex(expectedAssignError) class OuterReadExample extends Module { val myReg = RegInit(0.U(8.W)) @@ -149,16 +177,20 @@ class ConnectSpec extends ChiselPropSpec with Utils { myReg := inner.myReg // ERROR } - val readError = the [ChiselException] thrownBy {ChiselStage.elaborate { new OuterReadExample }} + val readError = the[ChiselException] thrownBy { ChiselStage.elaborate { new OuterReadExample } } val expectedReadError = """.*@: myReg in InnerExample cannot be read from module OuterReadExample.""" - readError.getMessage should fullyMatch regex expectedReadError - - val typeMismatchError = the [ChiselException] thrownBy {ChiselStage.elaborate { new RawModule { - val myUInt = Wire(UInt(4.W)) - val mySInt = Wire(SInt(4.W)) - myUInt := mySInt - }}} + (readError.getMessage should fullyMatch).regex(expectedReadError) + + val typeMismatchError = the[ChiselException] thrownBy { + ChiselStage.elaborate { + new RawModule { + val myUInt = Wire(UInt(4.W)) + val mySInt = Wire(SInt(4.W)) + myUInt := mySInt + } + } + } val expectedTypeMismatchError = """.*@: Sink \(UInt<4>\) and Source \(SInt<4>\) have different types.""" - typeMismatchError.getMessage should fullyMatch regex expectedTypeMismatchError + (typeMismatchError.getMessage should fullyMatch).regex(expectedTypeMismatchError) } } diff --git a/src/test/scala/chiselTests/Counter.scala b/src/test/scala/chiselTests/Counter.scala index 121d481a..0e2a339a 100644 --- a/src/test/scala/chiselTests/Counter.scala +++ b/src/test/scala/chiselTests/Counter.scala @@ -34,7 +34,7 @@ class ResetTester(n: Int) extends BasicTester { val wasReset = RegNext(triggerReset) val (value, _) = Counter(0 until 8, reset = triggerReset) - triggerReset := value === (n-1).U + triggerReset := value === (n - 1).U when(wasReset) { assert(value === 0.U) @@ -71,20 +71,20 @@ class CounterSpec extends ChiselPropSpec { } property("Counter can be en/disabled") { - forAll(safeUInts) { (seed: Int) => whenever(seed >= 0) { assertTesterPasses{ new EnableTester(seed) } } } + forAll(safeUInts) { (seed: Int) => whenever(seed >= 0) { assertTesterPasses { new EnableTester(seed) } } } } property("Counter can be reset") { - forAll(smallPosInts) { (seed: Int) => assertTesterPasses{ new ResetTester(seed) } } + forAll(smallPosInts) { (seed: Int) => assertTesterPasses { new ResetTester(seed) } } } property("Counter should wrap") { - forAll(smallPosInts) { (max: Int) => assertTesterPasses{ new WrapTester(max) } } + forAll(smallPosInts) { (max: Int) => assertTesterPasses { new WrapTester(max) } } } property("Counter should handle a range") { forAll(posRange) { (r: Range) => - assertTesterPasses{ new RangeTester(r) } + assertTesterPasses { new RangeTester(r) } } } } diff --git a/src/test/scala/chiselTests/CustomBundle.scala b/src/test/scala/chiselTests/CustomBundle.scala index b04dcc59..ee964d2d 100644 --- a/src/test/scala/chiselTests/CustomBundle.scala +++ b/src/test/scala/chiselTests/CustomBundle.scala @@ -3,7 +3,7 @@ package chiselTests import chisel3._ -import chisel3.experimental.{DataMirror, requireIsChiselType} +import chisel3.experimental.{requireIsChiselType, DataMirror} import scala.collection.immutable.ListMap // An example of how Record might be extended @@ -11,9 +11,10 @@ import scala.collection.immutable.ListMap // it is a possible implementation of a programmatic "Bundle" // (and can by connected to MyBundle below) final class CustomBundle(elts: (String, Data)*) extends Record { - val elements = ListMap(elts map { case (field, elt) => - requireIsChiselType(elt) - field -> elt + val elements = ListMap(elts.map { + case (field, elt) => + requireIsChiselType(elt) + field -> elt }: _*) def apply(elt: String): Data = elements(elt) override def cloneType: this.type = { @@ -21,4 +22,3 @@ final class CustomBundle(elts: (String, Data)*) extends Record { (new CustomBundle(cloned: _*)).asInstanceOf[this.type] } } - diff --git a/src/test/scala/chiselTests/DataPrint.scala b/src/test/scala/chiselTests/DataPrint.scala index 7fb790a8..091722b8 100644 --- a/src/test/scala/chiselTests/DataPrint.scala +++ b/src/test/scala/chiselTests/DataPrint.scala @@ -29,30 +29,32 @@ class DataPrintSpec extends ChiselFlatSpec with Matchers { } "Data types" should "have a meaningful string representation" in { - ChiselStage.elaborate { new RawModule { - UInt().toString should be ("UInt") - UInt(8.W).toString should be ("UInt<8>") - SInt(15.W).toString should be ("SInt<15>") - Bool().toString should be ("Bool") - Clock().toString should be ("Clock") - FixedPoint(5.W, 3.BP).toString should be ("FixedPoint<5><<3>>") - Vec(3, UInt(2.W)).toString should be ("UInt<2>[3]") - EnumTest.Type().toString should be ("EnumTest") - (new BundleTest).toString should be ("BundleTest") - new Bundle { val a = UInt(8.W) }.toString should be ("AnonymousBundle") - new Bundle { val a = UInt(8.W) }.a.toString should be ("UInt<8>") - }} + ChiselStage.elaborate { + new RawModule { + UInt().toString should be("UInt") + UInt(8.W).toString should be("UInt<8>") + SInt(15.W).toString should be("SInt<15>") + Bool().toString should be("Bool") + Clock().toString should be("Clock") + FixedPoint(5.W, 3.BP).toString should be("FixedPoint<5><<3>>") + Vec(3, UInt(2.W)).toString should be("UInt<2>[3]") + EnumTest.Type().toString should be("EnumTest") + (new BundleTest).toString should be("BundleTest") + new Bundle { val a = UInt(8.W) }.toString should be("AnonymousBundle") + new Bundle { val a = UInt(8.W) }.a.toString should be("UInt<8>") + } + } } - class BoundDataModule extends Module { // not in the test to avoid anon naming suffixes + class BoundDataModule extends Module { // not in the test to avoid anon naming suffixes Wire(UInt()).toString should be("BoundDataModule.?: Wire[UInt]") Reg(SInt()).toString should be("BoundDataModule.?: Reg[SInt]") - val io = IO(Output(Bool())) // needs a name so elaboration doesn't fail + val io = IO(Output(Bool())) // needs a name so elaboration doesn't fail io.toString should be("BoundDataModule.io: IO[Bool]") val m = Mem(4, UInt(2.W)) m(2).toString should be("BoundDataModule.?: MemPort[UInt<2>]") (2.U + 2.U).toString should be("BoundDataModule.?: OpResult[UInt<2>]") - Wire(Vec(3, UInt(2.W))).toString should be ("BoundDataModule.?: Wire[UInt<2>[3]]") + Wire(Vec(3, UInt(2.W))).toString should be("BoundDataModule.?: Wire[UInt<2>[3]]") class InnerModule extends Module { val io = IO(Output(new Bundle { @@ -60,8 +62,8 @@ class DataPrintSpec extends ChiselFlatSpec with Matchers { })) } val inner = Module(new InnerModule) - inner.clock.toString should be ("InnerModule.clock: IO[Clock]") - inner.io.a.toString should be ("InnerModule.io.a: IO[UInt<4>]") + inner.clock.toString should be("InnerModule.clock: IO[Clock]") + inner.io.a.toString should be("InnerModule.io.a: IO[UInt<4>]") class FooTypeTest extends Bundle { val foo = Vec(2, UInt(8.W)) @@ -69,7 +71,7 @@ class DataPrintSpec extends ChiselFlatSpec with Matchers { } val tpe = new FooTypeTest val fooio: FooTypeTest = IO(Input(tpe)) - fooio.foo(0).toString should be ("BoundDataModule.fooio.foo[0]: IO[UInt<8>]") + fooio.foo(0).toString should be("BoundDataModule.fooio.foo[0]: IO[UInt<8>]") class NestedBundle extends Bundle { val nestedFoo = UInt(8.W) @@ -81,10 +83,8 @@ class DataPrintSpec extends ChiselFlatSpec with Matchers { val nestedTpe = new NestedType val nestedio = IO(Input(nestedTpe)) - (nestedio.foo.nestedFoo.toString should be - ("BoundDataModule.nestedio.foo.nestedFoo: IO[UInt<8>]")) - (nestedio.foo.nestedFooVec(0).toString should be - ("BoundDataModule.nestedio.foo.nestedFooVec[0]: IO[UInt<8>]")) + (nestedio.foo.nestedFoo.toString should be("BoundDataModule.nestedio.foo.nestedFoo: IO[UInt<8>]")) + (nestedio.foo.nestedFooVec(0).toString should be("BoundDataModule.nestedio.foo.nestedFooVec[0]: IO[UInt<8>]")) } "Bound data types" should "have a meaningful string representation" in { @@ -92,21 +92,25 @@ class DataPrintSpec extends ChiselFlatSpec with Matchers { } "Literals" should "have a meaningful string representation" in { - ChiselStage.elaborate { new RawModule { - 3.U.toString should be ("UInt<2>(3)") - 3.U(5.W).toString should be ("UInt<5>(3)") - -1.S.toString should be ("SInt<1>(-1)") - false.B.toString should be ("Bool(false)") - true.B.toString should be ("Bool(true)") - 2.25.F(6.W, 2.BP).toString should be ("FixedPoint<6><<2>>(2.25)") - -2.25.F(6.W, 2.BP).toString should be ("FixedPoint<6><<2>>(-2.25)") - Vec(3, UInt(4.W)).toString should be ("UInt<4>[3]") - EnumTest.sNone.toString should be ("EnumTest(0=sNone)") - EnumTest.sTwo.toString should be ("EnumTest(2=sTwo)") - EnumTest(1.U).toString should be ("EnumTest(1=sOne)") - (new BundleTest).Lit(_.a -> 2.U, _.b -> false.B).toString should be ("BundleTest(a=UInt<8>(2), b=Bool(false))") - (new PartialBundleTest).Lit().toString should be ("PartialBundleTest(a=UInt<8>(DontCare), b=Bool(DontCare), c=SInt<8>(DontCare), e=FixedPoint<5><<3>>(DontCare), f=EnumTest(DontCare))") - DontCare.toString should be ("DontCare()") - } } + ChiselStage.elaborate { + new RawModule { + 3.U.toString should be("UInt<2>(3)") + 3.U(5.W).toString should be("UInt<5>(3)") + -1.S.toString should be("SInt<1>(-1)") + false.B.toString should be("Bool(false)") + true.B.toString should be("Bool(true)") + 2.25.F(6.W, 2.BP).toString should be("FixedPoint<6><<2>>(2.25)") + -2.25.F(6.W, 2.BP).toString should be("FixedPoint<6><<2>>(-2.25)") + Vec(3, UInt(4.W)).toString should be("UInt<4>[3]") + EnumTest.sNone.toString should be("EnumTest(0=sNone)") + EnumTest.sTwo.toString should be("EnumTest(2=sTwo)") + EnumTest(1.U).toString should be("EnumTest(1=sOne)") + (new BundleTest).Lit(_.a -> 2.U, _.b -> false.B).toString should be("BundleTest(a=UInt<8>(2), b=Bool(false))") + (new PartialBundleTest).Lit().toString should be( + "PartialBundleTest(a=UInt<8>(DontCare), b=Bool(DontCare), c=SInt<8>(DontCare), e=FixedPoint<5><<3>>(DontCare), f=EnumTest(DontCare))" + ) + DontCare.toString should be("DontCare()") + } + } } } diff --git a/src/test/scala/chiselTests/Decoder.scala b/src/test/scala/chiselTests/Decoder.scala index d802c6ce..0c644b49 100644 --- a/src/test/scala/chiselTests/Decoder.scala +++ b/src/test/scala/chiselTests/Decoder.scala @@ -10,10 +10,10 @@ import chisel3.util._ class Decoder(bitpats: List[String]) extends Module { val io = IO(new Bundle { - val inst = Input(UInt(32.W)) + val inst = Input(UInt(32.W)) val matched = Output(Bool()) }) - io.matched := VecInit(bitpats.map(BitPat(_) === io.inst)).reduce(_||_) + io.matched := VecInit(bitpats.map(BitPat(_) === io.inst)).reduce(_ || _) } class DecoderTester(pairs: List[(String, String)]) extends BasicTester { @@ -33,10 +33,10 @@ class DecoderTester(pairs: List[(String, String)]) extends BasicTester { class DecoderSpec extends ChiselPropSpec { // Use a single Int to make both a specific instruction and a BitPat that will match it - val bitpatPair = for(seed <- Arbitrary.arbitrary[Int]) yield { + val bitpatPair = for (seed <- Arbitrary.arbitrary[Int]) yield { val rnd = new scala.util.Random(seed) val bs = seed.toBinaryString - val bp = bs.map(if(rnd.nextBoolean) _ else "?") + val bp = bs.map(if (rnd.nextBoolean) _ else "?") // The following randomly throws in white space and underscores which are legal and ignored. val bpp = bp.map { a => @@ -49,11 +49,11 @@ class DecoderSpec extends ChiselPropSpec { ("b" + bs, "b" + bpp) } - private def nPairs(n: Int) = Gen.containerOfN[List, (String,String)](n,bitpatPair) + private def nPairs(n: Int) = Gen.containerOfN[List, (String, String)](n, bitpatPair) property("BitPat wildcards should be usable in decoding") { - forAll(nPairs(4)){ (pairs: List[(String, String)]) => - assertTesterPasses{ new DecoderTester(pairs) } + forAll(nPairs(4)) { (pairs: List[(String, String)]) => + assertTesterPasses { new DecoderTester(pairs) } } } } diff --git a/src/test/scala/chiselTests/DedupSpec.scala b/src/test/scala/chiselTests/DedupSpec.scala index 61f2995a..f2f2ed45 100644 --- a/src/test/scala/chiselTests/DedupSpec.scala +++ b/src/test/scala/chiselTests/DedupSpec.scala @@ -65,11 +65,10 @@ class SharedConstantValDedupTop extends Module { io.out := inst0.io.out + inst1.io.out } - class DedupSpec extends ChiselFlatSpec { private val ModuleRegex = """\s*module\s+(\w+)\b.*""".r def countModules(verilog: String): Int = - (verilog split "\n" collect { case ModuleRegex(name) => name }).size + (verilog.split("\n").collect { case ModuleRegex(name) => name }).size "Deduplication" should "occur" in { assert(countModules(compile { new DedupQueues(4) }) === 2) @@ -80,7 +79,6 @@ class DedupSpec extends ChiselFlatSpec { } it should "dedup modules that share a literal" in { - assert(countModules(compile { new SharedConstantValDedupTop }) === 2) + assert(countModules(compile { new SharedConstantValDedupTop }) === 2) } } - diff --git a/src/test/scala/chiselTests/Direction.scala b/src/test/scala/chiselTests/Direction.scala index 39ff1f0e..0c657273 100644 --- a/src/test/scala/chiselTests/Direction.scala +++ b/src/test/scala/chiselTests/Direction.scala @@ -16,8 +16,8 @@ class DirectionHaver extends Module { val io = IO(new Bundle { val in = Input(UInt(32.W)) val out = Output(UInt(32.W)) - val inBundle = Input(new DirectionedBundle) // should override elements - val outBundle = Output(new DirectionedBundle) // should override elements + val inBundle = Input(new DirectionedBundle) // should override elements + val outBundle = Output(new DirectionedBundle) // should override elements }) } @@ -51,10 +51,10 @@ class DirectionSpec extends ChiselPropSpec with Matchers with Utils { property("Inputs should not be assignable") { a[Exception] should be thrownBy extractCause[Exception] { - ChiselStage.elaborate(new BadDirection) + ChiselStage.elaborate(new BadDirection) } a[Exception] should be thrownBy extractCause[Exception] { - ChiselStage.elaborate(new BadSubDirection) + ChiselStage.elaborate(new BadSubDirection) } } @@ -84,7 +84,7 @@ class DirectionSpec extends ChiselPropSpec with Matchers with Utils { } property("Empty Vecs with no direction on the sample_element *should* cause direction errors") { - an [Exception] should be thrownBy extractCause[Exception] { + an[Exception] should be thrownBy extractCause[Exception] { ChiselStage.elaborate(new Module { val io = IO(new Bundle { val foo = Input(UInt(8.W)) @@ -118,7 +118,7 @@ class DirectionSpec extends ChiselPropSpec with Matchers with Utils { } property("Explicitly directioned but empty Bundles should cause direction errors") { - an [Exception] should be thrownBy extractCause[Exception] { + an[Exception] should be thrownBy extractCause[Exception] { ChiselStage.elaborate(new Module { val io = IO(new Bundle { val foo = UInt(8.W) @@ -241,18 +241,20 @@ class DirectionSpec extends ChiselPropSpec with Matchers with Utils { } val emitted: String = ChiselStage.emitChirrtl(new MyModule) - val firrtl: String = ChiselStage.convert(new MyModule).serialize + val firrtl: String = ChiselStage.convert(new MyModule).serialize // Check that emitted directions are correct. - Seq(emitted, firrtl).foreach { o => { - // Chisel Emitter formats spacing a little differently than the - // FIRRTL Emitter :-( - val s = o.replace("{flip a", "{ flip a") - assert(s.contains("output regularVec : { flip a : UInt<1>, b : UInt<1>}[2]")) - assert(s.contains("input vecFlipped : { flip a : UInt<1>, b : UInt<1>}[2]")) - assert(s.contains("input flippedVec : { flip a : UInt<1>, b : UInt<1>}[2]")) - assert(s.contains("output flippedVecFlipped : { flip a : UInt<1>, b : UInt<1>}[2]")) - } } + Seq(emitted, firrtl).foreach { o => + { + // Chisel Emitter formats spacing a little differently than the + // FIRRTL Emitter :-( + val s = o.replace("{flip a", "{ flip a") + assert(s.contains("output regularVec : { flip a : UInt<1>, b : UInt<1>}[2]")) + assert(s.contains("input vecFlipped : { flip a : UInt<1>, b : UInt<1>}[2]")) + assert(s.contains("input flippedVec : { flip a : UInt<1>, b : UInt<1>}[2]")) + assert(s.contains("output flippedVecFlipped : { flip a : UInt<1>, b : UInt<1>}[2]")) + } + } } property("Vec with Input/Output should calculate directions properly") { @@ -308,19 +310,21 @@ class DirectionSpec extends ChiselPropSpec with Matchers with Utils { } val emitted: String = ChiselStage.emitChirrtl(new MyModule) - val firrtl: String = ChiselStage.convert(new MyModule).serialize + val firrtl: String = ChiselStage.convert(new MyModule).serialize // Check that emitted directions are correct. - Seq(emitted, firrtl).foreach { o => { - // Chisel Emitter formats spacing a little differently than the - // FIRRTL Emitter :-( - val s = o.replace("{a", "{ a") - assert(s.contains("input inputVec : { a : UInt<1>, b : UInt<1>}[2]")) - assert(s.contains("input vecInput : { a : UInt<1>, b : UInt<1>}[2]")) - assert(s.contains("input vecInputFlipped : { a : UInt<1>, b : UInt<1>}[2]")) - assert(s.contains("output outputVec : { a : UInt<1>, b : UInt<1>}[2]")) - assert(s.contains("output vecOutput : { a : UInt<1>, b : UInt<1>}[2]")) - assert(s.contains("output vecOutputFlipped : { a : UInt<1>, b : UInt<1>}[2]")) - } } + Seq(emitted, firrtl).foreach { o => + { + // Chisel Emitter formats spacing a little differently than the + // FIRRTL Emitter :-( + val s = o.replace("{a", "{ a") + assert(s.contains("input inputVec : { a : UInt<1>, b : UInt<1>}[2]")) + assert(s.contains("input vecInput : { a : UInt<1>, b : UInt<1>}[2]")) + assert(s.contains("input vecInputFlipped : { a : UInt<1>, b : UInt<1>}[2]")) + assert(s.contains("output outputVec : { a : UInt<1>, b : UInt<1>}[2]")) + assert(s.contains("output vecOutput : { a : UInt<1>, b : UInt<1>}[2]")) + assert(s.contains("output vecOutputFlipped : { a : UInt<1>, b : UInt<1>}[2]")) + } + } } } diff --git a/src/test/scala/chiselTests/DontTouchSpec.scala b/src/test/scala/chiselTests/DontTouchSpec.scala index a6e4210c..4b21840e 100644 --- a/src/test/scala/chiselTests/DontTouchSpec.scala +++ b/src/test/scala/chiselTests/DontTouchSpec.scala @@ -32,7 +32,7 @@ class HasDeadCode(withDontTouch: Boolean) extends Module { } } -class DontTouchSpec extends ChiselFlatSpec with Utils{ +class DontTouchSpec extends ChiselFlatSpec with Utils { val deadSignals = List( "io_c_0", "io_c_1", @@ -41,20 +41,20 @@ class DontTouchSpec extends ChiselFlatSpec with Utils{ "Dead code" should "be removed by default" in { val verilog = compile(new HasDeadCode(false)) for (signal <- deadSignals) { - verilog should not include (signal) + (verilog should not).include(signal) } } it should "NOT be removed if marked dontTouch" in { val verilog = compile(new HasDeadCode(true)) for (signal <- deadSignals) { - verilog should include (signal) + verilog should include(signal) } } "Dont touch" should "only work on bound hardware" in { - a [chisel3.BindingException] should be thrownBy extractCause[BindingException] { + a[chisel3.BindingException] should be thrownBy extractCause[BindingException] { ChiselStage.elaborate(new Module { - val io = IO(new Bundle { }) - dontTouch(new Bundle { val a = UInt(32.W) } ) + val io = IO(new Bundle {}) + dontTouch(new Bundle { val a = UInt(32.W) }) }) } } diff --git a/src/test/scala/chiselTests/EnableShiftRegister.scala b/src/test/scala/chiselTests/EnableShiftRegister.scala index 34dcecb0..4d407169 100644 --- a/src/test/scala/chiselTests/EnableShiftRegister.scala +++ b/src/test/scala/chiselTests/EnableShiftRegister.scala @@ -6,9 +6,9 @@ import chisel3.stage.ChiselStage class EnableShiftRegister extends Module { val io = IO(new Bundle { - val in = Input(UInt(4.W)) + val in = Input(UInt(4.W)) val shift = Input(Bool()) - val out = Output(UInt(4.W)) + val out = Output(UInt(4.W)) }) val r0 = RegInit(0.U(4.W)) val r1 = RegInit(0.U(4.W)) @@ -41,7 +41,7 @@ class EnableShiftRegisterTester(c: EnableShiftRegister) extends Tester(c) { expect(c.io.out, reg(3)) } } -*/ + */ class EnableShiftRegisterSpec extends ChiselPropSpec { @@ -49,5 +49,5 @@ class EnableShiftRegisterSpec extends ChiselPropSpec { ChiselStage.elaborate { new EnableShiftRegister } } - ignore("EnableShiftRegisterTester should return the correct result") { } + ignore("EnableShiftRegisterTester should return the correct result") {} } diff --git a/src/test/scala/chiselTests/ExtModule.scala b/src/test/scala/chiselTests/ExtModule.scala index 161b6f5f..1dbd7447 100644 --- a/src/test/scala/chiselTests/ExtModule.scala +++ b/src/test/scala/chiselTests/ExtModule.scala @@ -61,19 +61,16 @@ class MultiExtModuleTester extends BasicTester { class ExtModuleSpec extends ChiselFlatSpec { "A ExtModule inverter" should "work" in { - assertTesterPasses({ new ExtModuleTester }, - Seq("/chisel3/BlackBoxTest.v"), TesterDriver.verilatorOnly) + assertTesterPasses({ new ExtModuleTester }, Seq("/chisel3/BlackBoxTest.v"), TesterDriver.verilatorOnly) } "Multiple ExtModules" should "work" in { - assertTesterPasses({ new MultiExtModuleTester }, - Seq("/chisel3/BlackBoxTest.v"), TesterDriver.verilatorOnly) + assertTesterPasses({ new MultiExtModuleTester }, Seq("/chisel3/BlackBoxTest.v"), TesterDriver.verilatorOnly) } "DataMirror.modulePorts" should "work with ExtModule" in { ChiselStage.elaborate(new Module { - val io = IO(new Bundle { }) + val io = IO(new Bundle {}) val m = Module(new extmoduletests.BlackBoxPassthrough) - assert(DataMirror.modulePorts(m) == Seq( - "in" -> m.in, "out" -> m.out)) + assert(DataMirror.modulePorts(m) == Seq("in" -> m.in, "out" -> m.out)) }) } } diff --git a/src/test/scala/chiselTests/ExtModuleImpl.scala b/src/test/scala/chiselTests/ExtModuleImpl.scala index c6cd4a9f..bb5c07bf 100644 --- a/src/test/scala/chiselTests/ExtModuleImpl.scala +++ b/src/test/scala/chiselTests/ExtModuleImpl.scala @@ -23,14 +23,17 @@ class ExtModuleAdd(n: Int) extends ExtModule with HasExtModuleInline { }) //scalastyle:off regex - setInline("ExtModuleAdd.v", s""" - |module ExtModuleAdd( - | input [15:0] in, - | output [15:0] out - |); - | assign out = in + $n; - |endmodule - """.stripMargin) + setInline( + "ExtModuleAdd.v", + s""" + |module ExtModuleAdd( + | input [15:0] in, + | output [15:0] out + |); + | assign out = in + $n; + |endmodule + """.stripMargin + ) } class UsesExtModuleAddViaInline extends Module { @@ -93,7 +96,7 @@ class UsesExtModuleMinusViaPath extends Module { } class ExtModuleResourceNotFound extends HasExtModuleResource { - val io = IO(new Bundle{}) + val io = IO(new Bundle {}) addResource("/missing.resource") } @@ -113,7 +116,7 @@ class ExtModuleImplSpec extends AnyFreeSpec with Matchers { ) val newAnnotations = (new ChiselStage).transform(annotations) - newAnnotations.exists(_.isInstanceOf[FirrtlCircuitAnnotation]) should be (true) + newAnnotations.exists(_.isInstanceOf[FirrtlCircuitAnnotation]) should be(true) val verilogOutput = new File(targetDir, "ExtModuleAdd.v") verilogOutput.exists() should be(true) verilogOutput.delete() @@ -127,7 +130,7 @@ class ExtModuleImplSpec extends AnyFreeSpec with Matchers { ) val newAnnotations = (new ChiselStage).transform(annotations) - newAnnotations.exists(_.isInstanceOf[FirrtlCircuitAnnotation]) should be (true) + newAnnotations.exists(_.isInstanceOf[FirrtlCircuitAnnotation]) should be(true) val verilogOutput = new File(targetDir, "BlackBoxTest.v") verilogOutput.exists() should be(true) verilogOutput.delete() @@ -141,14 +144,14 @@ class ExtModuleImplSpec extends AnyFreeSpec with Matchers { ) val newAnnotations = (new ChiselStage).transform(annotations) - newAnnotations.exists(_.isInstanceOf[FirrtlCircuitAnnotation]) should be (true) + newAnnotations.exists(_.isInstanceOf[FirrtlCircuitAnnotation]) should be(true) val verilogOutput = new File(targetDir, "BlackBoxTest.v") verilogOutput.exists() should be(true) verilogOutput.delete() } "Resource files that do not exist produce Chisel errors" in { - assertThrows[BlackBoxNotFoundException]{ + assertThrows[BlackBoxNotFoundException] { ChiselStage.emitChirrtl(new UsesMissingExtModuleResource) } } diff --git a/src/test/scala/chiselTests/FixedPointSpec.scala b/src/test/scala/chiselTests/FixedPointSpec.scala index 2530bb13..aedd195e 100644 --- a/src/test/scala/chiselTests/FixedPointSpec.scala +++ b/src/test/scala/chiselTests/FixedPointSpec.scala @@ -12,7 +12,7 @@ import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers class FixedPointLiteralSpec extends AnyFlatSpec with Matchers { - behavior of "fixed point utilities" + behavior.of("fixed point utilities") they should "allow conversion between doubles and the bigints needed to represent them" in { val initialDouble = 0.125 @@ -25,11 +25,11 @@ class FixedPointLiteralSpec extends AnyFlatSpec with Matchers { they should "have their literals support to double and to BigDecimal" in { val d = -7.125 val lit1 = d.F(3.BP) - lit1.litToDouble should be (d) + lit1.litToDouble should be(d) val d2 = BigDecimal("1232123213131123.125") val lit2 = d2.F(3.BP) - lit2.litToBigDecimal should be (d2) + lit2.litToBigDecimal should be(d2) // Numbers that are too big will throw exception intercept[ChiselException] { @@ -43,33 +43,33 @@ class FixedPointFromBitsTester extends BasicTester { val uint = 3.U(4.W) val sint = (-3).S - val fp = FixedPoint.fromDouble(3.0, 4.W, 0.BP) + val fp = FixedPoint.fromDouble(3.0, 4.W, 0.BP) val fp_tpe = FixedPoint(4.W, 1.BP) val uint_result = FixedPoint.fromDouble(1.5, 4.W, 1.BP) val sint_result = FixedPoint.fromDouble(-1.5, 4.W, 1.BP) - val fp_result = FixedPoint.fromDouble(1.5, 4.W, 1.BP) + val fp_result = FixedPoint.fromDouble(1.5, 4.W, 1.BP) val uint2fp = uint.asTypeOf(fp_tpe) val sint2fp = sint.asTypeOf(fp_tpe) - val fp2fp = fp.asTypeOf(fp_tpe) + val fp2fp = fp.asTypeOf(fp_tpe) val uintToFp = uint.asFixedPoint(1.BP) val sintToFp = sint.asFixedPoint(1.BP) - val fpToFp = fp.asFixedPoint(1.BP) + val fpToFp = fp.asFixedPoint(1.BP) val negativefp = (-3.5).F(4.BP) val positivefp = 3.5.F(4.BP) - assert(- positivefp === negativefp) + assert(-positivefp === negativefp) assert(positivefp === -negativefp) assert(uint2fp === uint_result) assert(sint2fp === sint_result) - assert(fp2fp === fp_result) + assert(fp2fp === fp_result) assert(uintToFp === uint_result) assert(sintToFp === sint_result) - assert(fpToFp === fp_result) + assert(fpToFp === fp_result) assert(positivefp.abs() === positivefp) assert(negativefp.abs() === positivefp) @@ -94,7 +94,6 @@ class FixedPointFromBitsTester extends BasicTester { assert(f6bp0shiftright2 === 1.0.F(0.BP)) assert(f6bp2shiftright2 === 1.5.F(2.BP)) - stop() } @@ -115,7 +114,7 @@ class FixedPointMuxTester extends BasicTester { class SBP extends Module { val io = IO(new Bundle { - val in = Input(FixedPoint(6.W, 2.BP)) + val in = Input(FixedPoint(6.W, 2.BP)) val out = Output(FixedPoint(4.W, 0.BP)) }) io.out := io.in.setBinaryPoint(0) @@ -162,7 +161,7 @@ class FixedPointSpec extends ChiselPropSpec with Utils { assertTesterPasses { new FixedPointMuxTester } } property("Negative shift amounts are invalid") { - a [ChiselException] should be thrownBy extractCause[ChiselException] { + a[ChiselException] should be thrownBy extractCause[ChiselException] { ChiselStage.elaborate(new NegativeShift(FixedPoint(1.W, 0.BP))) } } diff --git a/src/test/scala/chiselTests/GCD.scala b/src/test/scala/chiselTests/GCD.scala index 1e40c6f4..f03d4e61 100644 --- a/src/test/scala/chiselTests/GCD.scala +++ b/src/test/scala/chiselTests/GCD.scala @@ -8,17 +8,16 @@ import chisel3.testers.BasicTester class GCD extends Module { val io = IO(new Bundle { - val a = Input(UInt(32.W)) - val b = Input(UInt(32.W)) - val e = Input(Bool()) - val z = Output(UInt(32.W)) - val v = Output(Bool()) + val a = Input(UInt(32.W)) + val b = Input(UInt(32.W)) + val e = Input(Bool()) + val z = Output(UInt(32.W)) + val v = Output(Bool()) }) val x = Reg(UInt(32.W)) val y = Reg(UInt(32.W)) - when (x > y) { x := x -% y } - .otherwise { y := y -% x } - when (io.e) { x := io.a; y := io.b } + when(x > y) { x := x -% y }.otherwise { y := y -% x } + when(io.e) { x := io.a; y := io.b } io.z := x io.v := y === 0.U } @@ -39,21 +38,22 @@ class GCDTester(a: Int, b: Int, z: Int) extends BasicTester { class GCDSpec extends ChiselPropSpec { //TODO: use generators and this function to make z's - def gcd(a: Int, b: Int): Int = if(b == 0) a else gcd(b, a%b) + def gcd(a: Int, b: Int): Int = if (b == 0) a else gcd(b, a % b) val gcds = Table( - ("a", "b", "z"), // First tuple defines column names - ( 64, 48, 16), // Subsequent tuples define the data - ( 12, 9, 3), - ( 48, 64, 16)) + ("a", "b", "z"), // First tuple defines column names + (64, 48, 16), // Subsequent tuples define the data + (12, 9, 3), + (48, 64, 16) + ) property("GCD should elaborate") { ChiselStage.elaborate { new GCD } } property("GCDTester should return the correct result") { - forAll (gcds) { (a: Int, b: Int, z: Int) => - assertTesterPasses{ new GCDTester(a, b, z) } + forAll(gcds) { (a: Int, b: Int, z: Int) => + assertTesterPasses { new GCDTester(a, b, z) } } } } diff --git a/src/test/scala/chiselTests/Harness.scala b/src/test/scala/chiselTests/Harness.scala index 51576566..d4330cd6 100644 --- a/src/test/scala/chiselTests/Harness.scala +++ b/src/test/scala/chiselTests/Harness.scala @@ -15,7 +15,8 @@ module ${prefix}; endmodule """, ".v") _ - def makeFailingVerilog: (File => File) = makeHarness((prefix: String) => s""" + def makeFailingVerilog: (File => File) = makeHarness( + (prefix: String) => s""" module $prefix; initial begin assert (1 == 0) else $$error("My specific, expected error message!"); @@ -23,9 +24,12 @@ module $prefix; $$finish; end endmodule -""", ".v") _ +""", + ".v" + ) _ - def makeCppHarness: (File => File) = makeHarness((prefix: String) => s""" + def makeCppHarness: (File => File) = makeHarness( + (prefix: String) => s""" #include "V$prefix.h" #include "verilated.h" @@ -44,7 +48,9 @@ void vl_finish(const char* filename, int linenum, const char* hier) { Verilated::flushCall(); exit(0); } -""", ".cpp") _ +""", + ".cpp" + ) _ /** Compiles a C++ emulator from Verilog and returns the path to the * executable and the executable filename as a tuple. @@ -77,4 +83,3 @@ void vl_finish(const char* filename, int linenum, const char* hier) { assert(!executeExpectingFailure(target, path, "A string that doesn't match any test output")) } } - diff --git a/src/test/scala/chiselTests/IOCompatibility.scala b/src/test/scala/chiselTests/IOCompatibility.scala index 61789ffa..3e01a7a5 100644 --- a/src/test/scala/chiselTests/IOCompatibility.scala +++ b/src/test/scala/chiselTests/IOCompatibility.scala @@ -8,7 +8,7 @@ import org.scalatest._ import org.scalatest.matchers.should.Matchers class IOCSimpleIO extends Bundle { - val in = Input(UInt(32.W)) + val in = Input(UInt(32.W)) val out = Output(UInt(32.W)) } @@ -19,13 +19,13 @@ class IOCPlusOne extends Module { class IOCModuleVec(val n: Int) extends Module { val io = IO(new Bundle { - val ins = Vec(n, Input(UInt(32.W))) + val ins = Vec(n, Input(UInt(32.W))) val outs = Vec(n, Output(UInt(32.W))) }) - val pluses = VecInit(Seq.fill(n){ Module(new IOCPlusOne).io }) + val pluses = VecInit(Seq.fill(n) { Module(new IOCPlusOne).io }) for (i <- 0 until n) { pluses(i).in := io.ins(i) - io.outs(i) := pluses(i).out + io.outs(i) := pluses(i).out } } @@ -46,14 +46,13 @@ class IOCompatibilitySpec extends ChiselPropSpec with Matchers with Utils { ChiselStage.elaborate { new IOCModuleWire } } - class IOUnwrapped extends Module { val io = new IOCSimpleIO io.out := io.in } property("Unwrapped IO should generate an exception") { - a [BindingException] should be thrownBy extractCause[BindingException] { + a[BindingException] should be thrownBy extractCause[BindingException] { ChiselStage.elaborate(new IOUnwrapped) } } diff --git a/src/test/scala/chiselTests/IllegalRefSpec.scala b/src/test/scala/chiselTests/IllegalRefSpec.scala index 1bafc780..219df5af 100644 --- a/src/test/scala/chiselTests/IllegalRefSpec.scala +++ b/src/test/scala/chiselTests/IllegalRefSpec.scala @@ -39,7 +39,7 @@ object IllegalRefSpec { val o = Output(Bool()) }) private var tmp: Option[Bool] = None - when (io.i) { + when(io.i) { val x = io.i & io.i tmp = Some(x) } @@ -60,13 +60,13 @@ class IllegalRefSpec extends ChiselFlatSpec with Utils { variants.foreach { case (k, v) => s"Illegal cross-module references in ${k}" should "fail" in { - a [ChiselException] should be thrownBy extractCause[ChiselException] { + a[ChiselException] should be thrownBy extractCause[ChiselException] { ChiselStage.elaborate { new IllegalRefOuter(v) } } } s"Using a signal that has escaped its enclosing when scope in ${k}" should "fail" in { - a [ChiselException] should be thrownBy extractCause[ChiselException] { + a[ChiselException] should be thrownBy extractCause[ChiselException] { ChiselStage.elaborate { new CrossWhenConnect(v) } } } diff --git a/src/test/scala/chiselTests/ImplicitConversionsSpec.scala b/src/test/scala/chiselTests/ImplicitConversionsSpec.scala index f73b23b4..4bccf636 100644 --- a/src/test/scala/chiselTests/ImplicitConversionsSpec.scala +++ b/src/test/scala/chiselTests/ImplicitConversionsSpec.scala @@ -41,7 +41,7 @@ class ImplicitConversionsSpec extends ChiselFlatSpec { } "X.B for X not in [0,1]" should "throw an exception, even outside hardware context" in { - a [ChiselException] should be thrownBy { + a[ChiselException] should be thrownBy { 65.B } } diff --git a/src/test/scala/chiselTests/InlineSpec.scala b/src/test/scala/chiselTests/InlineSpec.scala index 59a1e984..09a92e45 100644 --- a/src/test/scala/chiselTests/InlineSpec.scala +++ b/src/test/scala/chiselTests/InlineSpec.scala @@ -4,7 +4,7 @@ package chiselTests import chisel3._ import chisel3.stage.{ChiselGeneratorAnnotation, ChiselStage} -import chisel3.util.experimental.{InlineInstance, FlattenInstance} +import chisel3.util.experimental.{FlattenInstance, InlineInstance} import firrtl.passes.InlineAnnotation import firrtl.stage.{FirrtlCircuitAnnotation, FirrtlStage} import firrtl.transforms.FlattenAnnotation @@ -16,7 +16,7 @@ import org.scalatest.matchers.should.Matchers class InlineSpec extends AnyFreeSpec with ChiselRunners with Matchers { trait Internals { this: Module => - val io = IO(new Bundle{ val a = Input(Bool()) }) + val io = IO(new Bundle { val a = Input(Bool()) }) } class Sub extends Module with Internals trait HasSub { this: Module with Internals => @@ -29,9 +29,9 @@ class InlineSpec extends AnyFreeSpec with ChiselRunners with Matchers { class Baz extends Module with Internals with HasSub class Qux extends Module with Internals with HasSub - def collectInstances(c: fir.Circuit, top: Option[String] = None): Seq[String] = new InstanceGraph(c) - .fullHierarchy.values.flatten.toSeq - .map( v => (top.getOrElse(v.head.name) +: v.tail.map(_.name)).mkString(".") ) + def collectInstances(c: fir.Circuit, top: Option[String] = None): Seq[String] = + new InstanceGraph(c).fullHierarchy.values.flatten.toSeq + .map(v => (top.getOrElse(v.head.name) +: v.tail.map(_.name)).mkString(".")) val chiselStage = new ChiselStage val firrtlStage = new FirrtlStage @@ -46,17 +46,20 @@ class InlineSpec extends AnyFreeSpec with ChiselRunners with Matchers { "should compile to low FIRRTL" - { val chiselAnnotations = chiselStage - .execute(Array("--no-run-firrtl", "--target-dir", "test_run_dir"), - Seq(ChiselGeneratorAnnotation(() => new Top))) + .execute( + Array("--no-run-firrtl", "--target-dir", "test_run_dir"), + Seq(ChiselGeneratorAnnotation(() => new Top)) + ) - chiselAnnotations.collect{ case a: InlineAnnotation => a } should have length (2) + (chiselAnnotations.collect { case a: InlineAnnotation => a } should have).length(2) val instanceNames = firrtlStage .execute(Array("-X", "low"), chiselAnnotations) .collectFirst { case FirrtlCircuitAnnotation(circuit) => circuit - }.map(collectInstances(_, Some("Top"))) + } + .map(collectInstances(_, Some("Top"))) .getOrElse(fail) instanceNames should contain theSameElementsAs Set("Top", "Top.x_sub", "Top.y_sub", "Top.z", "Top.z.sub") @@ -71,17 +74,20 @@ class InlineSpec extends AnyFreeSpec with ChiselRunners with Matchers { "should compile to low FIRRTL" - { val chiselAnnotations = chiselStage - .execute(Array("--no-run-firrtl", "--target-dir", "test_run_dir"), - Seq(ChiselGeneratorAnnotation(() => new Top))) + .execute( + Array("--no-run-firrtl", "--target-dir", "test_run_dir"), + Seq(ChiselGeneratorAnnotation(() => new Top)) + ) - chiselAnnotations.collect{ case a: FlattenAnnotation => a} should have length(1) + (chiselAnnotations.collect { case a: FlattenAnnotation => a } should have).length(1) val instanceNames = firrtlStage .execute(Array("-X", "low"), chiselAnnotations) .collectFirst { case FirrtlCircuitAnnotation(circuit) => circuit - }.map(collectInstances(_, Some("Top"))) + } + .map(collectInstances(_, Some("Top"))) .getOrElse(fail) instanceNames should contain theSameElementsAs Set("Top", "Top.x") diff --git a/src/test/scala/chiselTests/InstanceNameSpec.scala b/src/test/scala/chiselTests/InstanceNameSpec.scala index 7e3186f7..7eaf3106 100644 --- a/src/test/scala/chiselTests/InstanceNameSpec.scala +++ b/src/test/scala/chiselTests/InstanceNameSpec.scala @@ -23,7 +23,7 @@ class InstanceNameModule extends Module { } class InstanceNameSpec extends ChiselFlatSpec { - behavior of "instanceName" + behavior.of("instanceName") val moduleName = "InstanceNameModule" var m: InstanceNameModule = _ ChiselStage.elaborate { m = new InstanceNameModule; m } diff --git a/src/test/scala/chiselTests/IntegerMathSpec.scala b/src/test/scala/chiselTests/IntegerMathSpec.scala index 03b2b208..166e47bd 100644 --- a/src/test/scala/chiselTests/IntegerMathSpec.scala +++ b/src/test/scala/chiselTests/IntegerMathSpec.scala @@ -27,6 +27,6 @@ class IntegerMathTester extends BasicTester { class IntegerMathSpec extends ChiselPropSpec { property("All integer ops should return the correct result") { - assertTesterPasses{ new IntegerMathTester } + assertTesterPasses { new IntegerMathTester } } } diff --git a/src/test/scala/chiselTests/IntervalRangeSpec.scala b/src/test/scala/chiselTests/IntervalRangeSpec.scala index f17f1624..777e08d6 100644 --- a/src/test/scala/chiselTests/IntervalRangeSpec.scala +++ b/src/test/scala/chiselTests/IntervalRangeSpec.scala @@ -186,7 +186,6 @@ class IntervalRangeSpec extends AnyFreeSpec with Matchers { checkRange(range"[-8,7].2", C(-8), C(7), 2.BP) checkRange(range"[-8,7].2" >> 3, C(-1), C(0.75), 2.BP) - checkRange(range"(0,7).0", O(0), O(7), 0.BP) checkRange(range"(0,7).0" >> 1, O(0), O(3), 0.BP) @@ -219,19 +218,19 @@ class IntervalRangeSpec extends AnyFreeSpec with Matchers { "get possible values should return all values from high to low" in { var range = range"[0,4]" - range.getLowestPossibleValue should be (Some(0)) - range.getHighestPossibleValue should be (Some(4)) - range.getPossibleValues should be (Seq(0, 1, 2, 3, 4)) + range.getLowestPossibleValue should be(Some(0)) + range.getHighestPossibleValue should be(Some(4)) + range.getPossibleValues should be(Seq(0, 1, 2, 3, 4)) range = range"(0,4)" - range.getLowestPossibleValue should be (Some(1)) - range.getHighestPossibleValue should be (Some(3)) - range.getPossibleValues should be (Seq(1, 2, 3)) + range.getLowestPossibleValue should be(Some(1)) + range.getHighestPossibleValue should be(Some(3)) + range.getPossibleValues should be(Seq(1, 2, 3)) range = range"(-1,4).1" - range.getLowestPossibleValue should be (Some(-0.5)) - range.getHighestPossibleValue should be (Some(3.5)) - range.getPossibleValues should be (Seq(-0.5, 0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5)) + range.getLowestPossibleValue should be(Some(-0.5)) + range.getHighestPossibleValue should be(Some(3.5)) + range.getPossibleValues should be(Seq(-0.5, 0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5)) } } diff --git a/src/test/scala/chiselTests/IntervalSpec.scala b/src/test/scala/chiselTests/IntervalSpec.scala index c223260d..c0338f6d 100644 --- a/src/test/scala/chiselTests/IntervalSpec.scala +++ b/src/test/scala/chiselTests/IntervalSpec.scala @@ -15,7 +15,15 @@ import firrtl.passes.CheckTypes.InvalidConnect import firrtl.passes.CheckWidths.{DisjointSqueeze, InvalidRange} import firrtl.passes.{PassExceptions, WrapWithRemainder} import firrtl.stage.{CompilerAnnotation, FirrtlCircuitAnnotation} -import firrtl.{HighFirrtlCompiler, LowFirrtlCompiler, MiddleFirrtlCompiler, MinimumVerilogCompiler, NoneCompiler, SystemVerilogCompiler, VerilogCompiler} +import firrtl.{ + HighFirrtlCompiler, + LowFirrtlCompiler, + MiddleFirrtlCompiler, + MinimumVerilogCompiler, + NoneCompiler, + SystemVerilogCompiler, + VerilogCompiler +} import org.scalatest.freespec.AnyFreeSpec import org.scalatest.matchers.should.Matchers @@ -31,16 +39,17 @@ object IntervalTestHelper { */ def makeFirrtl[T <: RawModule](compilerName: String)(gen: () => T): String = { (new ChiselStage) - .execute(Array("--compiler", compilerName, - "--target-dir", "test_run_dir/IntervalSpec"), - Seq(ChiselGeneratorAnnotation(gen))) + .execute( + Array("--compiler", compilerName, "--target-dir", "test_run_dir/IntervalSpec"), + Seq(ChiselGeneratorAnnotation(gen)) + ) .collectFirst { case FirrtlCircuitAnnotation(source) => source } match { - case Some(circuit) => circuit.serialize - case _ => - throw new Exception( - s"makeFirrtl($compilerName) failed to generate firrtl circuit" - ) - } + case Some(circuit) => circuit.serialize + case _ => + throw new Exception( + s"makeFirrtl($compilerName) failed to generate firrtl circuit" + ) + } } } @@ -174,11 +183,12 @@ class MoreIntervalShiftTester extends BasicTester { * @param endNum end here * @param incNum increment by this */ -class ClipSqueezeWrapDemo(range: IntervalRange, - targetRange: IntervalRange, - startNum: Double, - endNum: Double, - incNum: Double) +class ClipSqueezeWrapDemo( + range: IntervalRange, + targetRange: IntervalRange, + startNum: Double, + endNum: Double, + incNum: Double) extends BasicTester { val binaryPointAsInt = range.binaryPoint.asInstanceOf[KnownBinaryPoint].value @@ -214,10 +224,7 @@ class ClipSqueezeWrapDemo(range: IntervalRange, ) } -class SqueezeFunctionalityTester(range: IntervalRange, - startNum: BigDecimal, - endNum: BigDecimal, - increment: BigDecimal) +class SqueezeFunctionalityTester(range: IntervalRange, startNum: BigDecimal, endNum: BigDecimal, increment: BigDecimal) extends BasicTester { val counter = RegInit(0.U(10.W)) @@ -436,20 +443,18 @@ class IntervalSpec extends AnyFreeSpec with Matchers with ChiselRunners { "Interval literals that don't fit in explicit ranges are caught by chisel" - { "case 1: does not fit in specified width" in { intercept[ChiselException] { - ChiselGeneratorAnnotation( - () => - new BasicTester { - val x = 5.I(3.W, 0.BP) + ChiselGeneratorAnnotation(() => + new BasicTester { + val x = 5.I(3.W, 0.BP) } ).elaborate } } "case 2: doesn't fit in specified range" in { intercept[ChiselException] { - ChiselGeneratorAnnotation( - () => - new BasicTester { - val x = 5.I(range"[0,4]") + ChiselGeneratorAnnotation(() => + new BasicTester { + val x = 5.I(range"[0,4]") } ).elaborate } @@ -459,11 +464,11 @@ class IntervalSpec extends AnyFreeSpec with Matchers with ChiselRunners { "Interval literals support to double and to BigDecimal" in { val d = -7.125 val lit1 = d.I(3.BP) - lit1.litToDouble should be (d) + lit1.litToDouble should be(d) val d2 = BigDecimal("1232123213131123.125") val lit2 = d2.I(3.BP) - lit2.litToBigDecimal should be (d2) + lit2.litToBigDecimal should be(d2) // Numbers that are too big will throw exception intercept[ChiselException] { @@ -476,8 +481,8 @@ class IntervalSpec extends AnyFreeSpec with Matchers with ChiselRunners { val inputRange = range"[-6, 6].2" val in1 = (-6.0).I(inputRange) val in2 = 6.0.I(inputRange) - BigDecimal(in1.litValue()) / (1 << inputRange.binaryPoint.get) should be (-6) - BigDecimal(in2.litValue()) / (1 << inputRange.binaryPoint.get) should be (6) + BigDecimal(in1.litValue()) / (1 << inputRange.binaryPoint.get) should be(-6) + BigDecimal(in2.litValue()) / (1 << inputRange.binaryPoint.get) should be(6) intercept[ChiselException] { (-6.25).I(inputRange) } @@ -489,8 +494,8 @@ class IntervalSpec extends AnyFreeSpec with Matchers with ChiselRunners { val inputRange = range"(-6, 6).2" val in1 = (-5.75).I(inputRange) val in2 = 5.75.I(inputRange) - BigDecimal(in1.litValue()) / (1 << inputRange.binaryPoint.get) should be (-5.75) - BigDecimal(in2.litValue()) / (1 << inputRange.binaryPoint.get) should be (5.75) + BigDecimal(in1.litValue()) / (1 << inputRange.binaryPoint.get) should be(-5.75) + BigDecimal(in2.litValue()) / (1 << inputRange.binaryPoint.get) should be(5.75) intercept[ChiselException] { (-6.0).I(inputRange) } @@ -502,8 +507,8 @@ class IntervalSpec extends AnyFreeSpec with Matchers with ChiselRunners { val inputRange = range"(-6, 6).2" val in1 = (-5.95).I(inputRange) val in2 = 5.95.I(inputRange) - BigDecimal(in1.litValue()) / (1 << inputRange.binaryPoint.get) should be (-5.75) - BigDecimal(in2.litValue()) / (1 << inputRange.binaryPoint.get) should be (5.75) + BigDecimal(in1.litValue()) / (1 << inputRange.binaryPoint.get) should be(-5.75) + BigDecimal(in2.litValue()) / (1 << inputRange.binaryPoint.get) should be(5.75) intercept[ChiselException] { (-6.1).I(inputRange) } @@ -614,28 +619,26 @@ class IntervalSpec extends AnyFreeSpec with Matchers with ChiselRunners { } } - def makeCircuit(operation: String, - sourceRange: IntervalRange, - targetRange: IntervalRange): () => RawModule = { () => - new Module { - val io = IO(new Bundle { val out = Output(Interval()) }) - val base = Wire(Interval(sourceRange)) - base := 6.I + def makeCircuit(operation: String, sourceRange: IntervalRange, targetRange: IntervalRange): () => RawModule = { + () => + new Module { + val io = IO(new Bundle { val out = Output(Interval()) }) + val base = Wire(Interval(sourceRange)) + base := 6.I - val disjointLeft = WireInit(Interval(targetRange), 8.I) - val w5 = operation match { - case "clip" => base.clip(disjointLeft) - case "wrap" => base.wrap(disjointLeft) - case "squeeze" => base.squeeze(disjointLeft) + val disjointLeft = WireInit(Interval(targetRange), 8.I) + val w5 = operation match { + case "clip" => base.clip(disjointLeft) + case "wrap" => base.wrap(disjointLeft) + case "squeeze" => base.squeeze(disjointLeft) + } + io.out := w5 } - io.out := w5 - } } "disjoint ranges should error when used with clip, wrap and squeeze" - { - def mustGetException(disjointLeft: Boolean, - operation: String): Boolean = { + def mustGetException(disjointLeft: Boolean, operation: String): Boolean = { val (rangeA, rangeB) = if (disjointLeft) { (range"[-4, 6]", range"[7,10]") } else { @@ -675,57 +678,37 @@ class IntervalSpec extends AnyFreeSpec with Matchers with ChiselRunners { "Errors are sometimes inconsistent or incorrectly labelled as Firrtl Internal Error" - { "squeeze disjoint is not internal error when defined in BasicTester" in { intercept[DisjointSqueeze] { - makeFirrtl("low")( - () => - new BasicTester { - val base = Wire(Interval(range"[-4, 6]")) - val base2 = Wire(Interval(range"[-4, 6]")) - base := 6.I - base2 := 5.I - val disjointLeft = WireInit(Interval(range"[7,10]"), 8.I) - val w5 = base.squeeze(disjointLeft) - stop() + makeFirrtl("low")(() => + new BasicTester { + val base = Wire(Interval(range"[-4, 6]")) + val base2 = Wire(Interval(range"[-4, 6]")) + base := 6.I + base2 := 5.I + val disjointLeft = WireInit(Interval(range"[7,10]"), 8.I) + val w5 = base.squeeze(disjointLeft) + stop() } ) } } "wrap disjoint is not internal error when defined in BasicTester" in { intercept[DisjointSqueeze] { - makeFirrtl("low")( - () => - new BasicTester { - val base = Wire(Interval(range"[-4, 6]")) - val base2 = Wire(Interval(range"[-4, 6]")) - base := 6.I - base2 := 5.I - val disjointLeft = WireInit(Interval(range"[7,10]"), 8.I) - val w5 = base.squeeze(disjointLeft) - stop() + makeFirrtl("low")(() => + new BasicTester { + val base = Wire(Interval(range"[-4, 6]")) + val base2 = Wire(Interval(range"[-4, 6]")) + base := 6.I + base2 := 5.I + val disjointLeft = WireInit(Interval(range"[7,10]"), 8.I) + val w5 = base.squeeze(disjointLeft) + stop() } ) } } "squeeze disjoint from Module gives exception" in { intercept[DisjointSqueeze] { - makeFirrtl("low")( - () => - new Module { - val io = IO(new Bundle { - val out = Output(Interval()) - }) - val base = Wire(Interval(range"[-4, 6]")) - base := 6.I - - val disjointLeft = WireInit(Interval(range"[7,10]"), 8.I) - val w5 = base.squeeze(disjointLeft) - io.out := w5 - } - ) - } - } - "clip disjoint from Module gives no error" in { - makeFirrtl("low")( - () => + makeFirrtl("low")(() => new Module { val io = IO(new Bundle { val out = Output(Interval()) @@ -734,25 +717,40 @@ class IntervalSpec extends AnyFreeSpec with Matchers with ChiselRunners { base := 6.I val disjointLeft = WireInit(Interval(range"[7,10]"), 8.I) - val w5 = base.clip(disjointLeft) + val w5 = base.squeeze(disjointLeft) io.out := w5 + } + ) + } + } + "clip disjoint from Module gives no error" in { + makeFirrtl("low")(() => + new Module { + val io = IO(new Bundle { + val out = Output(Interval()) + }) + val base = Wire(Interval(range"[-4, 6]")) + base := 6.I + + val disjointLeft = WireInit(Interval(range"[7,10]"), 8.I) + val w5 = base.clip(disjointLeft) + io.out := w5 } ) } "wrap disjoint from Module wrap with remainder" in { intercept[WrapWithRemainder] { - makeFirrtl("low")( - () => - new Module { - val io = IO(new Bundle { - val out = Output(Interval()) - }) - val base = Wire(Interval(range"[-4, 6]")) - base := 6.I - - val disjointLeft = WireInit(Interval(range"[7,10]"), 8.I) - val w5 = base.wrap(disjointLeft) - io.out := w5 + makeFirrtl("low")(() => + new Module { + val io = IO(new Bundle { + val out = Output(Interval()) + }) + val base = Wire(Interval(range"[-4, 6]")) + base := 6.I + + val disjointLeft = WireInit(Interval(range"[7,10]"), 8.I) + val w5 = base.wrap(disjointLeft) + io.out := w5 } ) } @@ -772,26 +770,24 @@ class IntervalSpec extends AnyFreeSpec with Matchers with ChiselRunners { "Intervals should catch assignment of literals outside of range" - { "when literal is too small" in { intercept[InvalidConnect] { - makeFirrtl("low")( - () => - new Module { - val io = IO(new Bundle { val out = Output(Interval()) }) - val base = Wire(Interval(range"[-4, 6]")) - base := (-7).I - io.out := base + makeFirrtl("low")(() => + new Module { + val io = IO(new Bundle { val out = Output(Interval()) }) + val base = Wire(Interval(range"[-4, 6]")) + base := (-7).I + io.out := base } ) } } "when literal is too big" in { intercept[InvalidConnect] { - makeFirrtl("low")( - () => - new Module { - val io = IO(new Bundle { val out = Output(Interval()) }) - val base = Wire(Interval(range"[-4, 6]")) - base := 9.I - io.out := base + makeFirrtl("low")(() => + new Module { + val io = IO(new Bundle { val out = Output(Interval()) }) + val base = Wire(Interval(range"[-4, 6]")) + base := 9.I + io.out := base } ) } @@ -834,18 +830,17 @@ class IntervalSpec extends AnyFreeSpec with Matchers with ChiselRunners { assertTesterPasses { new IntervalChainedAddTester } } "Intervals should produce canonically smaller ranges via inference" in { - val loFirrtl = makeFirrtl("low")( - () => - new Module { - val io = IO(new Bundle { - val in = Input(Interval(range"[0,1]")) - val out = Output(Interval()) - }) + val loFirrtl = makeFirrtl("low")(() => + new Module { + val io = IO(new Bundle { + val in = Input(Interval(range"[0,1]")) + val out = Output(Interval()) + }) - val intervalResult = Wire(Interval()) + val intervalResult = Wire(Interval()) - intervalResult := 1.I + 1.I + 1.I + 1.I + 1.I + 1.I + 1.I - io.out := intervalResult + intervalResult := 1.I + 1.I + 1.I + 1.I + 1.I + 1.I + 1.I + io.out := intervalResult } ) loFirrtl.contains("output io_out : SInt<4>") should be(true) diff --git a/src/test/scala/chiselTests/InvalidateAPISpec.scala b/src/test/scala/chiselTests/InvalidateAPISpec.scala index 52ad02b4..2c51e5d2 100644 --- a/src/test/scala/chiselTests/InvalidateAPISpec.scala +++ b/src/test/scala/chiselTests/InvalidateAPISpec.scala @@ -16,11 +16,13 @@ class InvalidateAPISpec extends ChiselPropSpec with Matchers with BackendCompila def compileFirrtl(t: => Module): Unit = { val testDir = createTestDirectory(this.getClass.getSimpleName) - (new ChiselStage).execute(Array[String]("-td", testDir.getAbsolutePath, "--compiler", "verilog"), - Seq(ChiselGeneratorAnnotation(() => t))) + (new ChiselStage).execute( + Array[String]("-td", testDir.getAbsolutePath, "--compiler", "verilog"), + Seq(ChiselGeneratorAnnotation(() => t)) + ) } class TrivialInterface extends Bundle { - val in = Input(Bool()) + val in = Input(Bool()) val out = Output(Bool()) } @@ -42,7 +44,7 @@ class InvalidateAPISpec extends ChiselPropSpec with Matchers with BackendCompila io.out := io.in } val firrtlOutput = myGenerateFirrtl(new ModuleWithoutDontCare) - firrtlOutput should not include("is invalid") + (firrtlOutput should not).include("is invalid") } property("an output without a DontCare should emit a Firrtl \"is invalid\" with NotStrict CompileOptions") { @@ -77,7 +79,7 @@ class InvalidateAPISpec extends ChiselPropSpec with Matchers with BackendCompila } val firrtlOutput = myGenerateFirrtl(new ModuleWithoutDontCare) for (i <- 0 until nElements) - firrtlOutput should include(s"io.outs[$i] is invalid") + firrtlOutput should include(s"io.outs[$i] is invalid") } property("a Vec with a DontCare should emit a Firrtl \"is invalid\" with Strict CompileOptions and mono connect") { @@ -129,7 +131,7 @@ class InvalidateAPISpec extends ChiselPropSpec with Matchers with BackendCompila val out = Output(Bool()) }) val counter = Counter(8) - when (counter.inc()) { + when(counter.inc()) { io.out := true.B } } @@ -137,9 +139,11 @@ class InvalidateAPISpec extends ChiselPropSpec with Matchers with BackendCompila compileFirrtl(new ModuleWithIncompleteAssignment) } exception.getMessage should include("is not fully initialized") - } + } - property("FIRRTL should not complain about partial initialization with Strict CompileOptions and conditional connect after unconditional connect") { + property( + "FIRRTL should not complain about partial initialization with Strict CompileOptions and conditional connect after unconditional connect" + ) { import chisel3.ExplicitCompileOptions.Strict class ModuleWithUnconditionalAssignment extends Module { val io = IO(new Bundle { @@ -147,23 +151,25 @@ class InvalidateAPISpec extends ChiselPropSpec with Matchers with BackendCompila }) val counter = Counter(8) io.out := false.B - when (counter.inc()) { + when(counter.inc()) { io.out := true.B } } compileFirrtl(new ModuleWithUnconditionalAssignment) } - property("FIRRTL should not complain about partial initialization with Strict CompileOptions and conditional connect with otherwise clause") { + property( + "FIRRTL should not complain about partial initialization with Strict CompileOptions and conditional connect with otherwise clause" + ) { import chisel3.ExplicitCompileOptions.Strict class ModuleWithConditionalAndOtherwiseAssignment extends Module { val io = IO(new Bundle { val out = Output(Bool()) }) val counter = Counter(8) - when (counter.inc()) { + when(counter.inc()) { io.out := true.B - } otherwise { + }.otherwise { io.out := false.B } } @@ -171,7 +177,9 @@ class InvalidateAPISpec extends ChiselPropSpec with Matchers with BackendCompila compileFirrtl(new ModuleWithConditionalAndOtherwiseAssignment) } - property("an output without a DontCare should NOT emit a Firrtl \"is invalid\" with overriden NotStrict CompileOptions") { + property( + "an output without a DontCare should NOT emit a Firrtl \"is invalid\" with overriden NotStrict CompileOptions" + ) { import chisel3.ExplicitCompileOptions.NotStrict class ModuleWithoutDontCare extends Module { override val compileOptions = chisel3.ExplicitCompileOptions.NotStrict.copy(explicitInvalidate = true) @@ -179,18 +187,21 @@ class InvalidateAPISpec extends ChiselPropSpec with Matchers with BackendCompila io.out := io.in } val firrtlOutput = myGenerateFirrtl(new ModuleWithoutDontCare) - firrtlOutput should not include("is invalid") + (firrtlOutput should not).include("is invalid") } - property("an output without a DontCare should NOT emit a Firrtl \"is invalid\" with overriden NotStrict CompileOptions module definition") { + property( + "an output without a DontCare should NOT emit a Firrtl \"is invalid\" with overriden NotStrict CompileOptions module definition" + ) { import chisel3.ExplicitCompileOptions.NotStrict - abstract class ExplicitInvalidateModule extends Module()(chisel3.ExplicitCompileOptions.NotStrict.copy(explicitInvalidate = true)) + abstract class ExplicitInvalidateModule + extends Module()(chisel3.ExplicitCompileOptions.NotStrict.copy(explicitInvalidate = true)) class ModuleWithoutDontCare extends ExplicitInvalidateModule { val io = IO(new TrivialInterface) io.out := io.in } val firrtlOutput = myGenerateFirrtl(new ModuleWithoutDontCare) - firrtlOutput should not include("is invalid") + (firrtlOutput should not).include("is invalid") } property("an output without a DontCare should emit a Firrtl \"is invalid\" with overriden Strict CompileOptions") { @@ -204,9 +215,12 @@ class InvalidateAPISpec extends ChiselPropSpec with Matchers with BackendCompila firrtlOutput should include("is invalid") } - property("an output without a DontCare should emit a Firrtl \"is invalid\" with overriden Strict CompileOptions module definition") { + property( + "an output without a DontCare should emit a Firrtl \"is invalid\" with overriden Strict CompileOptions module definition" + ) { import chisel3.ExplicitCompileOptions.Strict - abstract class ImplicitInvalidateModule extends Module()(chisel3.ExplicitCompileOptions.NotStrict.copy(explicitInvalidate = false)) + abstract class ImplicitInvalidateModule + extends Module()(chisel3.ExplicitCompileOptions.NotStrict.copy(explicitInvalidate = false)) class ModuleWithoutDontCare extends ImplicitInvalidateModule { val io = IO(new TrivialInterface) io.out := io.in diff --git a/src/test/scala/chiselTests/LiteralExtractorSpec.scala b/src/test/scala/chiselTests/LiteralExtractorSpec.scala index bc0c67b8..3906057f 100644 --- a/src/test/scala/chiselTests/LiteralExtractorSpec.scala +++ b/src/test/scala/chiselTests/LiteralExtractorSpec.scala @@ -51,19 +51,21 @@ class LiteralExtractorSpec extends ChiselFlatSpec { } "litOption" should "return None for non-literal hardware" in { - ChiselStage.elaborate { new RawModule { - val a = Wire(UInt()) - assert(a.litOption == None) - }} + ChiselStage.elaborate { + new RawModule { + val a = Wire(UInt()) + assert(a.litOption == None) + } + } } "doubles and big decimals" should "round trip properly" in { intercept[ChiselException] { - Num.toBigDecimal(BigInt("1" * 109, 2), 0.BP) // this only works if number takes less than 109 bits + Num.toBigDecimal(BigInt("1" * 109, 2), 0.BP) // this only works if number takes less than 109 bits } intercept[ChiselException] { - Num.toDouble(BigInt("1" * 54, 2), 0.BP) // this only works if number takes less than 54 bits + Num.toDouble(BigInt("1" * 54, 2), 0.BP) // this only works if number takes less than 54 bits } val bigInt108 = BigInt("1" * 108, 2) @@ -71,22 +73,22 @@ class LiteralExtractorSpec extends ChiselFlatSpec { val bigIntFromBigDecimal = Num.toBigInt(bigDecimal, 2) - bigIntFromBigDecimal should be (bigInt108) + bigIntFromBigDecimal should be(bigInt108) val bigInt53 = BigInt("1" * 53, 2) - val double = Num.toDouble(bigInt53, 2) + val double = Num.toDouble(bigInt53, 2) val bigIntFromDouble = Num.toBigInt(double, 2) - bigIntFromDouble should be (bigInt53) + bigIntFromDouble should be(bigInt53) } "encoding and decoding of Intervals" should "round trip" in { val rangeMin = BigDecimal(-31.5) val rangeMax = BigDecimal(32.5) val range = range"($rangeMin, $rangeMax).2" - for(value <- (rangeMin - 4) to (rangeMax + 4) by 2.25) { + for (value <- (rangeMin - 4) to (rangeMax + 4) by 2.25) { if (value < rangeMin || value > rangeMax) { intercept[ChiselException] { val literal = value.I(range) @@ -125,11 +127,10 @@ class LiteralExtractorSpec extends ChiselFlatSpec { } val outsideLiteral = (new InsideBundle).Lit(_.x -> 7.S, _.y -> 6.125.F(4.BP)) - assertTesterPasses{ new LitInsideOutsideTester(outsideLiteral) } + assertTesterPasses { new LitInsideOutsideTester(outsideLiteral) } } - "bundle literals" should "do the right thing" in { class MyBundle extends Bundle { val a = UInt(8.W) @@ -142,7 +143,7 @@ class LiteralExtractorSpec extends ChiselFlatSpec { } "record literals" should "do the right thing" in { - class MyRecord extends Record{ + class MyRecord extends Record { override val elements = ListMap( "a" -> UInt(8.W), "b" -> Bool() diff --git a/src/test/scala/chiselTests/LiteralToTargetSpec.scala b/src/test/scala/chiselTests/LiteralToTargetSpec.scala index 3c404f2d..b1caecfa 100644 --- a/src/test/scala/chiselTests/LiteralToTargetSpec.scala +++ b/src/test/scala/chiselTests/LiteralToTargetSpec.scala @@ -9,12 +9,11 @@ import org.scalatest._ import org.scalatest.freespec.AnyFreeSpec import org.scalatest.matchers.should.Matchers - class LiteralToTargetSpec extends AnyFreeSpec with Matchers { "Literal Data should fail to be converted to ReferenceTarget" in { - the [chisel3.internal.ChiselException] thrownBy { + (the[chisel3.internal.ChiselException] thrownBy { class Bar extends RawModule { val a = 1.U @@ -26,6 +25,6 @@ class LiteralToTargetSpec extends AnyFreeSpec with Matchers { } ChiselStage.elaborate(new Foo) - } should have message "Illegal component name: UInt<1>(\"h01\") (note: literals are illegal)" + } should have).message("Illegal component name: UInt<1>(\"h01\") (note: literals are illegal)") } } diff --git a/src/test/scala/chiselTests/LoadMemoryFromFileSpec.scala b/src/test/scala/chiselTests/LoadMemoryFromFileSpec.scala index 74e587bc..8e5e48b4 100644 --- a/src/test/scala/chiselTests/LoadMemoryFromFileSpec.scala +++ b/src/test/scala/chiselTests/LoadMemoryFromFileSpec.scala @@ -6,7 +6,7 @@ import java.io.File import chisel3._ import chisel3.stage.{ChiselGeneratorAnnotation, ChiselStage} -import chisel3.util.experimental.{loadMemoryFromFile,loadMemoryFromFileInline} +import chisel3.util.experimental.{loadMemoryFromFile, loadMemoryFromFileInline} import chisel3.util.log2Ceil import firrtl.annotations.MemoryLoadFileType import org.scalatest.freespec.AnyFreeSpec @@ -15,9 +15,9 @@ import org.scalatest.matchers.should.Matchers class UsesThreeMems(memoryDepth: Int, memoryType: Data) extends Module { val io = IO(new Bundle { val address = Input(UInt(memoryType.getWidth.W)) - val value1 = Output(memoryType) - val value2 = Output(memoryType) - val value3 = Output(memoryType) + val value1 = Output(memoryType) + val value2 = Output(memoryType) + val value3 = Output(memoryType) }) val memory1 = Mem(memoryDepth, memoryType) @@ -32,12 +32,17 @@ class UsesThreeMems(memoryDepth: Int, memoryType: Data) extends Module { io.value3 := memory3(io.address) } -class UsesThreeMemsInline(memoryDepth: Int, memoryType: Data, memoryFile: String, hexOrBinary: MemoryLoadFileType.FileType) extends Module { +class UsesThreeMemsInline( + memoryDepth: Int, + memoryType: Data, + memoryFile: String, + hexOrBinary: MemoryLoadFileType.FileType) + extends Module { val io = IO(new Bundle { val address = Input(UInt(memoryType.getWidth.W)) - val value1 = Output(memoryType) - val value2 = Output(memoryType) - val value3 = Output(memoryType) + val value1 = Output(memoryType) + val value2 = Output(memoryType) + val value3 = Output(memoryType) }) val memory1 = Mem(memoryDepth, memoryType) @@ -55,9 +60,9 @@ class UsesThreeMemsInline(memoryDepth: Int, memoryType: Data, memoryFile: String class UsesMem(memoryDepth: Int, memoryType: Data) extends Module { val io = IO(new Bundle { val address = Input(UInt(memoryType.getWidth.W)) - val value = Output(memoryType) - val value1 = Output(memoryType) - val value2 = Output(memoryType) + val value = Output(memoryType) + val value1 = Output(memoryType) + val value2 = Output(memoryType) }) val memory = Mem(memoryDepth, memoryType) @@ -77,7 +82,7 @@ class UsesMem(memoryDepth: Int, memoryType: Data) extends Module { class UsesMemLow(memoryDepth: Int, memoryType: Data) extends Module { val io = IO(new Bundle { val address = Input(UInt(memoryType.getWidth.W)) - val value = Output(memoryType) + val value = Output(memoryType) }) val memory = Mem(memoryDepth, memoryType) @@ -90,8 +95,8 @@ class UsesMemLow(memoryDepth: Int, memoryType: Data) extends Module { class FileHasSuffix(memoryDepth: Int, memoryType: Data) extends Module { val io = IO(new Bundle { val address = Input(UInt(memoryType.getWidth.W)) - val value = Output(memoryType) - val value2 = Output(memoryType) + val value = Output(memoryType) + val value2 = Output(memoryType) }) val memory = Mem(memoryDepth, memoryType) @@ -115,7 +120,7 @@ class MemoryShape extends Bundle { class HasComplexMemory(memoryDepth: Int) extends Module { val io = IO(new Bundle { val address = Input(UInt(log2Ceil(memoryDepth).W)) - val value = Output(new MemoryShape) + val value = Output(new MemoryShape) }) val memory = Mem(memoryDepth, new MemoryShape) @@ -128,7 +133,7 @@ class HasComplexMemory(memoryDepth: Int) extends Module { class HasBinarySupport(memoryDepth: Int, memoryType: Data) extends Module { val io = IO(new Bundle { val address = Input(UInt(memoryType.getWidth.W)) - val value = Output(memoryType) + val value = Output(memoryType) }) val memory = Mem(memoryDepth, memoryType) @@ -138,7 +143,6 @@ class HasBinarySupport(memoryDepth: Int, memoryType: Data) extends Module { io.value := memory(io.address) } - /** * The following tests are a bit incomplete and check that the output verilog is properly constructed * For more complete working examples @@ -147,12 +151,12 @@ class HasBinarySupport(memoryDepth: Int, memoryType: Data) extends Module { class LoadMemoryFromFileSpec extends AnyFreeSpec with Matchers { def fileExistsWithMem(file: File, mem: Option[String] = None): Unit = { info(s"$file exists") - file.exists() should be (true) - mem.foreach( m => { + file.exists() should be(true) + mem.foreach(m => { info(s"Memory $m is referenced in $file") val found = io.Source.fromFile(file).getLines.exists { _.contains(s"""readmemh("$m"""") } - found should be (true) - } ) + found should be(true) + }) file.delete() } @@ -180,10 +184,10 @@ class LoadMemoryFromFileSpec extends AnyFreeSpec with Matchers { ) val dir = new File(testDirName) - fileExistsWithMem( new File(dir, "UsesThreeMems.UsesThreeMems.memory1.v"), Some("./mem1")) - fileExistsWithMem( new File(dir, "UsesThreeMems.UsesThreeMems.memory2.v"), Some("./mem1")) - fileExistsWithMem( new File(dir, "UsesThreeMems.UsesThreeMems.memory3.v"), Some("./mem1")) - fileExistsWithMem( new File(dir, "firrtl_black_box_resource_files.f")) + fileExistsWithMem(new File(dir, "UsesThreeMems.UsesThreeMems.memory1.v"), Some("./mem1")) + fileExistsWithMem(new File(dir, "UsesThreeMems.UsesThreeMems.memory2.v"), Some("./mem1")) + fileExistsWithMem(new File(dir, "UsesThreeMems.UsesThreeMems.memory3.v"), Some("./mem1")) + fileExistsWithMem(new File(dir, "firrtl_black_box_resource_files.f")) } @@ -200,9 +204,9 @@ class LoadMemoryFromFileSpec extends AnyFreeSpec with Matchers { memoryElements.foreach { element => val file = new File(dir, s"HasComplexMemory.HasComplexMemory.memory_$element.v") - file.exists() should be (true) + file.exists() should be(true) val fileText = io.Source.fromFile(file).getLines().mkString("\n") - fileText should include (s"""$$readmemh("./mem_$element", HasComplexMemory.memory_$element);""") + fileText should include(s"""$$readmemh("./mem_$element", HasComplexMemory.memory_$element);""") file.delete() } @@ -218,9 +222,9 @@ class LoadMemoryFromFileSpec extends AnyFreeSpec with Matchers { val dir = new File(testDirName) val file = new File(dir, s"HasBinarySupport.HasBinarySupport.memory.v") - file.exists() should be (true) + file.exists() should be(true) val fileText = io.Source.fromFile(file).getLines().mkString("\n") - fileText should include (s"""$$readmemb("./mem", HasBinarySupport.memory);""") + fileText should include(s"""$$readmemb("./mem", HasBinarySupport.memory);""") file.delete() } @@ -229,15 +233,19 @@ class LoadMemoryFromFileSpec extends AnyFreeSpec with Matchers { val result = (new ChiselStage).execute( args = Array("-X", "verilog", "--target-dir", testDirName), - annotations = Seq(ChiselGeneratorAnnotation(() => new UsesThreeMemsInline(memoryDepth = 8, memoryType = UInt(16.W), "./testmem.h", MemoryLoadFileType.Hex))) + annotations = Seq( + ChiselGeneratorAnnotation(() => + new UsesThreeMemsInline(memoryDepth = 8, memoryType = UInt(16.W), "./testmem.h", MemoryLoadFileType.Hex) + ) + ) ) val dir = new File(testDirName) val file = new File(dir, s"UsesThreeMemsInline.v") - file.exists() should be (true) + file.exists() should be(true) val fileText = io.Source.fromFile(file).getLines().mkString("\n") - fileText should include (s"""$$readmemh("./testmem.h", memory1);""") - fileText should include (s"""$$readmemh("./testmem.h", memory2);""") - fileText should include (s"""$$readmemh("./testmem.h", memory3);""") + fileText should include(s"""$$readmemh("./testmem.h", memory1);""") + fileText should include(s"""$$readmemh("./testmem.h", memory2);""") + fileText should include(s"""$$readmemh("./testmem.h", memory3);""") } "Module with more than one bin memory inline should work" in { @@ -245,14 +253,18 @@ class LoadMemoryFromFileSpec extends AnyFreeSpec with Matchers { val result = (new ChiselStage).execute( args = Array("-X", "verilog", "--target-dir", testDirName), - annotations = Seq(ChiselGeneratorAnnotation(() => new UsesThreeMemsInline(memoryDepth = 8, memoryType = UInt(16.W), "testmem.bin", MemoryLoadFileType.Binary))) + annotations = Seq( + ChiselGeneratorAnnotation(() => + new UsesThreeMemsInline(memoryDepth = 8, memoryType = UInt(16.W), "testmem.bin", MemoryLoadFileType.Binary) + ) + ) ) val dir = new File(testDirName) val file = new File(dir, s"UsesThreeMemsInline.v") - file.exists() should be (true) + file.exists() should be(true) val fileText = io.Source.fromFile(file).getLines().mkString("\n") - fileText should include (s"""$$readmemb("testmem.bin", memory1);""") - fileText should include (s"""$$readmemb("testmem.bin", memory2);""") - fileText should include (s"""$$readmemb("testmem.bin", memory3);""") + fileText should include(s"""$$readmemb("testmem.bin", memory1);""") + fileText should include(s"""$$readmemb("testmem.bin", memory2);""") + fileText should include(s"""$$readmemb("testmem.bin", memory3);""") } } diff --git a/src/test/scala/chiselTests/Math.scala b/src/test/scala/chiselTests/Math.scala index 9091b0b4..42eff6ad 100644 --- a/src/test/scala/chiselTests/Math.scala +++ b/src/test/scala/chiselTests/Math.scala @@ -10,41 +10,43 @@ class Math extends ChiselPropSpec { implicit val noShrinkListVal = Shrink[List[Int]](_ => Stream.empty) implicit val noShrinkInt = Shrink[Int](_ => Stream.empty) - property ("unsignedBitLength is computed correctly") { - forAll(safeUIntWidth) { case (width: Int) => - for ( offset <- List(-1, 0, 1)) { - val n = (1 << width) + offset - if (n >= 0) { - val d = unsignedBitLength(n) - val t = if (n == 0) 0 else if (offset < 0) width else width + 1 - d shouldEqual (t) + property("unsignedBitLength is computed correctly") { + forAll(safeUIntWidth) { + case (width: Int) => + for (offset <- List(-1, 0, 1)) { + val n = (1 << width) + offset + if (n >= 0) { + val d = unsignedBitLength(n) + val t = if (n == 0) 0 else if (offset < 0) width else width + 1 + d shouldEqual (t) + } } - } } } - property ("signedBitLength is computed correctly") { - forAll(safeUIntWidth) { case (width: Int) => - for ( offset <- List(-1, 0, 1)) { - for ( mult <- List(-1, +1)) { - val n = ((1 << (width - 1)) + offset) * mult - val d = signedBitLength(n) - val t = n match { - case -2 => 2 - case -1 => 1 - case 0 => 0 - case 1 => 2 - case 2 => 3 - case _ => - if (n > 0) { - if (offset < 0) width else width + 1 - } else { - if (offset > 0) width + 1 else width - } + property("signedBitLength is computed correctly") { + forAll(safeUIntWidth) { + case (width: Int) => + for (offset <- List(-1, 0, 1)) { + for (mult <- List(-1, +1)) { + val n = ((1 << (width - 1)) + offset) * mult + val d = signedBitLength(n) + val t = n match { + case -2 => 2 + case -1 => 1 + case 0 => 0 + case 1 => 2 + case 2 => 3 + case _ => + if (n > 0) { + if (offset < 0) width else width + 1 + } else { + if (offset > 0) width + 1 else width + } + } + d shouldEqual (t) } - d shouldEqual (t) } - } } } } diff --git a/src/test/scala/chiselTests/Mem.scala b/src/test/scala/chiselTests/Mem.scala index 8bcd3aac..4dcb1ad4 100644 --- a/src/test/scala/chiselTests/Mem.scala +++ b/src/test/scala/chiselTests/Mem.scala @@ -13,7 +13,7 @@ class MemVecTester extends BasicTester { val (cnt, wrap) = Counter(true.B, 2) mem(0)(0) := 1.U - when (cnt === 1.U) { + when(cnt === 1.U) { assert(mem.read(0.U)(0) === 1.U) stop() } @@ -24,12 +24,12 @@ class SyncReadMemTester extends BasicTester { val mem = SyncReadMem(2, UInt(2.W)) val rdata = mem.read(cnt - 1.U, cnt =/= 0.U) - switch (cnt) { - is (0.U) { mem.write(cnt, 3.U) } - is (1.U) { mem.write(cnt, 2.U) } - is (2.U) { assert(rdata === 3.U) } - is (3.U) { assert(rdata === 2.U) } - is (4.U) { stop() } + switch(cnt) { + is(0.U) { mem.write(cnt, 3.U) } + is(1.U) { mem.write(cnt, 2.U) } + is(2.U) { assert(rdata === 3.U) } + is(3.U) { assert(rdata === 2.U) } + is(4.U) { stop() } } } @@ -47,24 +47,24 @@ class SyncReadMemWriteCollisionTester extends BasicTester { m1.write(cnt, cnt) // Read data from address 0 - when (cnt === 3.U) { + when(cnt === 3.U) { assert(rd0 === 2.U) assert(rd1 === 0.U) } - when (cnt === 4.U) { + when(cnt === 4.U) { stop() } } class SyncReadMemWithZeroWidthTester extends BasicTester { val (cnt, _) = Counter(true.B, 3) - val mem = SyncReadMem(2, UInt(0.W)) - val rdata = mem.read(0.U, true.B) + val mem = SyncReadMem(2, UInt(0.W)) + val rdata = mem.read(0.U, true.B) - switch (cnt) { - is (1.U) { assert(rdata === 0.U) } - is (2.U) { stop() } + switch(cnt) { + is(1.U) { assert(rdata === 0.U) } + is(2.U) { stop() } } } @@ -74,12 +74,12 @@ class HugeSMemTester(size: BigInt) extends BasicTester { val mem = SyncReadMem(size, UInt(8.W)) val rdata = mem.read(cnt - 1.U, cnt =/= 0.U) - switch (cnt) { - is (0.U) { mem.write(cnt, 3.U) } - is (1.U) { mem.write(cnt, 2.U) } - is (2.U) { assert(rdata === 3.U) } - is (3.U) { assert(rdata === 2.U) } - is (4.U) { stop() } + switch(cnt) { + is(0.U) { mem.write(cnt, 3.U) } + is(1.U) { mem.write(cnt, 2.U) } + is(2.U) { assert(rdata === 3.U) } + is(3.U) { assert(rdata === 2.U) } + is(4.U) { stop() } } } class HugeCMemTester(size: BigInt) extends BasicTester { @@ -87,12 +87,12 @@ class HugeCMemTester(size: BigInt) extends BasicTester { val mem = Mem(size, UInt(8.W)) val rdata = mem.read(cnt) - switch (cnt) { - is (0.U) { mem.write(cnt, 3.U) } - is (1.U) { mem.write(cnt, 2.U) } - is (2.U) { assert(rdata === 3.U) } - is (3.U) { assert(rdata === 2.U) } - is (4.U) { stop() } + switch(cnt) { + is(0.U) { mem.write(cnt, 3.U) } + is(1.U) { mem.write(cnt, 2.U) } + is(2.U) { assert(rdata === 3.U) } + is(3.U) { assert(rdata === 2.U) } + is(4.U) { stop() } } } @@ -104,20 +104,20 @@ class SyncReadMemBundleTester extends BasicTester { val mem = SyncReadMem(2, tpe) val rdata = mem.read(cnt - 1.U, cnt =/= 0.U) - switch (cnt) { - is (0.U) { + switch(cnt) { + is(0.U) { val w = Wire(tpe) w.foo := 3.U mem.write(cnt, w) } - is (1.U) { + is(1.U) { val w = Wire(tpe) w.foo := 2.U mem.write(cnt, w) } - is (2.U) { assert(rdata.foo === 3.U) } - is (3.U) { assert(rdata.foo === 2.U) } - is (4.U) { stop() } + is(2.U) { assert(rdata.foo === 3.U) } + is(3.U) { assert(rdata.foo === 2.U) } + is(4.U) { stop() } } } @@ -135,7 +135,7 @@ class MemBundleTester extends BasicTester { w } - when (cnt === 1.U) { + when(cnt === 1.U) { assert(mem.read(0.U).foo === 1.U) stop() } @@ -170,20 +170,20 @@ class MemorySpec extends ChiselPropSpec { val addrWidth = 65 val size = BigInt(1) << addrWidth val smem = compile(new HugeSMemTester(size)) - smem should include (s"reg /* sparse */ [7:0] mem [0:$addrWidth'd${size-1}];") + smem should include(s"reg /* sparse */ [7:0] mem [0:$addrWidth'd${size - 1}];") val cmem = compile(new HugeCMemTester(size)) - cmem should include (s"reg /* sparse */ [7:0] mem [0:$addrWidth'd${size-1}];") + cmem should include(s"reg /* sparse */ [7:0] mem [0:$addrWidth'd${size - 1}];") } property("Implicit conversions with Mem indices should work") { """ - |import chisel3._ - |import chisel3.util.ImplicitConversions._ - |class MyModule extends Module { - | val io = IO(new Bundle {}) - | val mem = Mem(32, UInt(8.W)) - | mem(0) := 0.U - |} - |""".stripMargin should compile + |import chisel3._ + |import chisel3.util.ImplicitConversions._ + |class MyModule extends Module { + | val io = IO(new Bundle {}) + | val mem = Mem(32, UInt(8.W)) + | mem(0) := 0.U + |} + |""".stripMargin should compile } } diff --git a/src/test/scala/chiselTests/MemorySearch.scala b/src/test/scala/chiselTests/MemorySearch.scala index ebfdace1..df1c6b32 100644 --- a/src/test/scala/chiselTests/MemorySearch.scala +++ b/src/test/scala/chiselTests/MemorySearch.scala @@ -7,23 +7,23 @@ import chisel3.stage.ChiselStage class MemorySearch extends Module { val io = IO(new Bundle { - val target = Input(UInt(4.W)) - val en = Input(Bool()) - val done = Output(Bool()) + val target = Input(UInt(4.W)) + val en = Input(Bool()) + val done = Output(Bool()) val address = Output(UInt(3.W)) }) - val vals = Array(0, 4, 15, 14, 2, 5, 13) + val vals = Array(0, 4, 15, 14, 2, 5, 13) val index = RegInit(0.U(3.W)) - val elts = VecInit(vals.map(_.asUInt(4.W))) + val elts = VecInit(vals.map(_.asUInt(4.W))) // val elts = Mem(UInt(32.W), 8) TODO ???? - val elt = elts(index) - val end = !io.en && ((elt === io.target) || (index === 7.U)) - when (io.en) { + val elt = elts(index) + val end = !io.en && ((elt === io.target) || (index === 7.U)) + when(io.en) { index := 0.U - } .elsewhen (!end) { + }.elsewhen(!end) { index := index +% 1.U } - io.done := end + io.done := end io.address := index } @@ -46,7 +46,7 @@ class MemorySearchTester(c: MemorySearch) extends Tester(c) { "LOOKING FOR " + target + " FOUND " + addr) } } -*/ + */ class MemorySearchSpec extends ChiselPropSpec { @@ -54,5 +54,5 @@ class MemorySearchSpec extends ChiselPropSpec { ChiselStage.elaborate { new EnableShiftRegister } } - ignore("MemorySearch should return the correct result") { } + ignore("MemorySearch should return the correct result") {} } diff --git a/src/test/scala/chiselTests/MixedVecSpec.scala b/src/test/scala/chiselTests/MixedVecSpec.scala index 369ed68a..16efafd4 100644 --- a/src/test/scala/chiselTests/MixedVecSpec.scala +++ b/src/test/scala/chiselTests/MixedVecSpec.scala @@ -87,7 +87,7 @@ class MixedVecUIntDynamicIndexTester extends BasicTester { val (cycle, done) = Counter(true.B, n) assert(vecWire(cycle) === cycle) - when (done) { stop() } + when(done) { stop() } } class MixedVecTestBundle extends Bundle { @@ -143,10 +143,10 @@ class MixedVecOneBitTester extends BasicTester { val flag = RegInit(false.B) val oneBit = Reg(MixedVec(Seq(UInt(1.W)))) - when (!flag) { + when(!flag) { oneBit(0) := 1.U(1.W) flag := true.B - } .otherwise { + }.otherwise { assert(oneBit(0) === 1.U) assert(oneBit.asUInt === 1.U) stop() @@ -179,26 +179,29 @@ class MixedVecSpec extends ChiselPropSpec with Utils { } property("MixedVecs should be assignable") { - forAll(safeUIntN(8)) { case (w: Int, v: List[Int]) => - assertTesterPasses { - new MixedVecAssignTester(w, v) - } + forAll(safeUIntN(8)) { + case (w: Int, v: List[Int]) => + assertTesterPasses { + new MixedVecAssignTester(w, v) + } } } property("MixedVecs should be usable as the type for Reg()") { - forAll(safeUIntN(8)) { case (w: Int, v: List[Int]) => - assertTesterPasses { - new MixedVecRegTester(w, v) - } + forAll(safeUIntN(8)) { + case (w: Int, v: List[Int]) => + assertTesterPasses { + new MixedVecRegTester(w, v) + } } } property("MixedVecs should be passed through IO") { - forAll(safeUIntN(8)) { case (w: Int, v: List[Int]) => - assertTesterPasses { - new MixedVecIOTester(v.map(i => i.U(w.W))) - } + forAll(safeUIntN(8)) { + case (w: Int, v: List[Int]) => + assertTesterPasses { + new MixedVecIOTester(v.map(i => i.U(w.W))) + } } } @@ -209,21 +212,21 @@ class MixedVecSpec extends ChiselPropSpec with Utils { } property("MixedVecs should not be able to take hardware types") { - a [ExpectedChiselTypeException] should be thrownBy extractCause[ExpectedChiselTypeException] { + a[ExpectedChiselTypeException] should be thrownBy extractCause[ExpectedChiselTypeException] { ChiselStage.elaborate(new Module { val io = IO(new Bundle {}) val hw = Wire(MixedVec(Seq(UInt(8.W), Bool()))) val illegal = MixedVec(hw) }) } - a [ExpectedChiselTypeException] should be thrownBy extractCause[ExpectedChiselTypeException] { + a[ExpectedChiselTypeException] should be thrownBy extractCause[ExpectedChiselTypeException] { ChiselStage.elaborate(new Module { val io = IO(new Bundle {}) val hw = Reg(MixedVec(Seq(UInt(8.W), Bool()))) val illegal = MixedVec(hw) }) } - a [ExpectedChiselTypeException] should be thrownBy extractCause[ExpectedChiselTypeException] { + a[ExpectedChiselTypeException] should be thrownBy extractCause[ExpectedChiselTypeException] { ChiselStage.elaborate(new Module { val io = IO(new Bundle { val v = Input(MixedVec(Seq(UInt(8.W), Bool()))) @@ -238,19 +241,19 @@ class MixedVecSpec extends ChiselPropSpec with Utils { } property("MixedVecs of UInts should be dynamically indexable (via VecInit)") { - assertTesterPasses{ new MixedVecUIntDynamicIndexTester } + assertTesterPasses { new MixedVecUIntDynamicIndexTester } } property("MixedVecs should be creatable from Vecs") { - assertTesterPasses{ new MixedVecFromVecTester } + assertTesterPasses { new MixedVecFromVecTester } } property("It should be possible to bulk connect a MixedVec and a Vec") { - assertTesterPasses{ new MixedVecConnectWithVecTester } + assertTesterPasses { new MixedVecConnectWithVecTester } } property("It should be possible to bulk connect a MixedVec and a Seq") { - assertTesterPasses{ new MixedVecConnectWithSeqTester } + assertTesterPasses { new MixedVecConnectWithSeqTester } } property("MixedVecs of a single 1 bit element should compile and work") { @@ -258,7 +261,7 @@ class MixedVecSpec extends ChiselPropSpec with Utils { } property("Connecting a MixedVec and something of different size should report a ChiselException") { - an [IllegalArgumentException] should be thrownBy extractCause[IllegalArgumentException] { + an[IllegalArgumentException] should be thrownBy extractCause[IllegalArgumentException] { ChiselStage.elaborate(new Module { val io = IO(new Bundle { val out = Output(MixedVec(Seq(UInt(8.W), Bool()))) @@ -267,7 +270,7 @@ class MixedVecSpec extends ChiselPropSpec with Utils { io.out := seq }) } - an [IllegalArgumentException] should be thrownBy extractCause[IllegalArgumentException] { + an[IllegalArgumentException] should be thrownBy extractCause[IllegalArgumentException] { ChiselStage.elaborate(new Module { val io = IO(new Bundle { val out = Output(MixedVec(Seq(UInt(8.W), Bool()))) diff --git a/src/test/scala/chiselTests/Module.scala b/src/test/scala/chiselTests/Module.scala index f0d6dbe7..13dbe1e9 100644 --- a/src/test/scala/chiselTests/Module.scala +++ b/src/test/scala/chiselTests/Module.scala @@ -12,7 +12,7 @@ import scala.io.Source import scala.annotation.nowarn class SimpleIO extends Bundle { - val in = Input(UInt(32.W)) + val in = Input(UInt(32.W)) val out = Output(UInt(32.W)) } @@ -23,13 +23,13 @@ class PlusOne extends Module { class ModuleVec(val n: Int) extends Module { val io = IO(new Bundle { - val ins = Input(Vec(n, UInt(32.W))) + val ins = Input(Vec(n, UInt(32.W))) val outs = Output(Vec(n, UInt(32.W))) }) - val pluses = VecInit(Seq.fill(n){ Module(new PlusOne).io }) + val pluses = VecInit(Seq.fill(n) { Module(new PlusOne).io }) for (i <- 0 until n) { pluses(i).in := io.ins(i) - io.outs(i) := pluses(i).out + io.outs(i) := pluses(i).out } } @@ -49,7 +49,7 @@ class ModuleWhen extends Module { val inc = Module(new PlusOne).io inc.in := io.s.in io.s.out := inc.out - } otherwise { io.s.out := io.s.in } + }.otherwise { io.s.out := io.s.in } } class ModuleForgetWrapper extends Module { @@ -69,13 +69,13 @@ class ModuleRewrap extends Module { } class ModuleWrapper(gen: => Module) extends Module { - val io = IO(new Bundle{}) + val io = IO(new Bundle {}) val child = Module(gen) override val desiredName = s"${child.desiredName}Wrapper" } class NullModuleWrapper extends Module { - val io = IO(new Bundle{}) + val io = IO(new Bundle {}) override lazy val desiredName = s"${child.desiredName}Wrapper" println(s"My name is ${name}") val child = Module(new ModuleWire) @@ -87,34 +87,34 @@ class ModuleSpec extends ChiselPropSpec with Utils { ChiselStage.elaborate { new ModuleVec(2) } } - ignore("ModuleVecTester should return the correct result") { } + ignore("ModuleVecTester should return the correct result") {} property("ModuleWire should elaborate") { ChiselStage.elaborate { new ModuleWire } } - ignore("ModuleWireTester should return the correct result") { } + ignore("ModuleWireTester should return the correct result") {} property("ModuleWhen should elaborate") { ChiselStage.elaborate { new ModuleWhen } } - ignore("ModuleWhenTester should return the correct result") { } + ignore("ModuleWhenTester should return the correct result") {} property("Forgetting a Module() wrapper should result in an error") { - (the [ChiselException] thrownBy extractCause[ChiselException] { + (the[ChiselException] thrownBy extractCause[ChiselException] { ChiselStage.elaborate { new ModuleForgetWrapper } }).getMessage should include("attempted to instantiate a Module without wrapping it") } property("Double wrapping a Module should result in an error") { - (the [ChiselException] thrownBy extractCause[ChiselException] { + (the[ChiselException] thrownBy extractCause[ChiselException] { ChiselStage.elaborate { new ModuleDoubleWrap } }).getMessage should include("Called Module() twice without instantiating a Module") } property("Rewrapping an already instantiated Module should result in an error") { - (the [ChiselException] thrownBy extractCause[ChiselException] { + (the[ChiselException] thrownBy extractCause[ChiselException] { ChiselStage.elaborate { new ModuleRewrap } }).getMessage should include("This is probably due to rewrapping a Module instance") } @@ -140,7 +140,7 @@ class ModuleSpec extends ChiselPropSpec with Utils { property("object Module.currentModule should return an Option reference to the current Module") { def checkModule(mod: Module): Boolean = Module.currentModule.map(_ eq mod).getOrElse(false) ChiselStage.elaborate(new Module { - val io = IO(new Bundle { }) + val io = IO(new Bundle {}) assert(Module.currentModule.get eq this) assert(checkModule(this)) }) @@ -148,24 +148,27 @@ class ModuleSpec extends ChiselPropSpec with Utils { property("object chisel3.util.experimental.getAnnotations should return current annotations.") { case class DummyAnnotation() extends NoTargetAnnotation with Unserializable - (new ChiselStage).transform(Seq( - ChiselGeneratorAnnotation(() => new RawModule { - assert(chisel3.util.experimental.getAnnotations().contains(DummyAnnotation())) - }), - DummyAnnotation(), - NoRunFirrtlCompilerAnnotation)) + (new ChiselStage).transform( + Seq( + ChiselGeneratorAnnotation(() => + new RawModule { + assert(chisel3.util.experimental.getAnnotations().contains(DummyAnnotation())) + } + ), + DummyAnnotation(), + NoRunFirrtlCompilerAnnotation + ) + ) } property("DataMirror.modulePorts should work") { ChiselStage.elaborate(new Module { - val io = IO(new Bundle { }) + val io = IO(new Bundle {}) val m = Module(new chisel3.Module { val a = IO(UInt(8.W)) val b = IO(Bool()) }) - assert(DataMirror.modulePorts(m) == Seq( - "clock" -> m.clock, "reset" -> m.reset, - "a" -> m.a, "b" -> m.b)) + assert(DataMirror.modulePorts(m) == Seq("clock" -> m.clock, "reset" -> m.reset, "a" -> m.a, "b" -> m.b)) }) } @@ -186,21 +189,25 @@ class ModuleSpec extends ChiselPropSpec with Utils { mod } // Note that this is just top-level ports, Aggregates are not flattened - DataMirror.modulePorts(mod) should contain theSameElementsInOrderAs Seq( - "clock" -> mod.clock, - "reset" -> mod.reset, - "io" -> mod.io, - "extra" -> mod.extra + (DataMirror.modulePorts(mod) should contain).theSameElementsInOrderAs( + Seq( + "clock" -> mod.clock, + "reset" -> mod.reset, + "io" -> mod.io, + "extra" -> mod.extra + ) ) // Delete this when the deprecated API is deleted // Note this also uses deprecated Port import chisel3.internal.firrtl.Port import SpecifiedDirection.{Input => IN, Unspecified} - mod.getPorts should contain theSameElementsInOrderAs Seq( - Port(mod.clock, IN), - Port(mod.reset, IN), - Port(mod.io, Unspecified), - Port(mod.extra, IN) + (mod.getPorts should contain).theSameElementsInOrderAs( + Seq( + Port(mod.clock, IN), + Port(mod.reset, IN), + Port(mod.io, Unspecified), + Port(mod.extra, IN) + ) ): @nowarn // delete when Port and getPorts become private } @@ -230,15 +237,16 @@ class ModuleSpec extends ChiselPropSpec with Utils { "io_in" -> mod.io.in, "extra" -> mod.extra ) - DataMirror.fullModulePorts(mod) should contain theSameElementsInOrderAs expected + (DataMirror.fullModulePorts(mod) should contain).theSameElementsInOrderAs(expected) } property("A desiredName parameterized by a submodule should work") { - ChiselStage.elaborate(new ModuleWrapper(new ModuleWire)).name should be ("ModuleWireWrapper") + ChiselStage.elaborate(new ModuleWrapper(new ModuleWire)).name should be("ModuleWireWrapper") } property("A name generating a null pointer exception should provide a good error message") { - (the [ChiselException] thrownBy extractCause[ChiselException] (ChiselStage.elaborate(new NullModuleWrapper))) - .getMessage should include ("desiredName of chiselTests.NullModuleWrapper is null") + (the[ChiselException] thrownBy extractCause[ChiselException]( + ChiselStage.elaborate(new NullModuleWrapper) + )).getMessage should include("desiredName of chiselTests.NullModuleWrapper is null") } property("The name of a module in a function should be sane") { def foo = { @@ -262,7 +270,7 @@ class ModuleSpec extends ChiselPropSpec with Utils { } property("emitVerilog((new PlusOne()..) shall produce a valid Verilog file in a subfolder") { - emitVerilog(new PlusOne(), Array("--target-dir", "generated")) + emitVerilog(new PlusOne(), Array("--target-dir", "generated")) val s = Source.fromFile("generated/PlusOne.v").mkString("") assert(s.contains("assign io_out = io_in + 32'h1")) } diff --git a/src/test/scala/chiselTests/ModuleExplicitResetSpec.scala b/src/test/scala/chiselTests/ModuleExplicitResetSpec.scala index c55276ce..1a55fb3f 100644 --- a/src/test/scala/chiselTests/ModuleExplicitResetSpec.scala +++ b/src/test/scala/chiselTests/ModuleExplicitResetSpec.scala @@ -4,7 +4,7 @@ package chiselTests import chisel3.stage.ChiselStage -class ModuleExplicitResetSpec extends ChiselFlatSpec { +class ModuleExplicitResetSpec extends ChiselFlatSpec { "A Module with an explicit reset in compatibility mode" should "elaborate" in { import Chisel._ diff --git a/src/test/scala/chiselTests/MulLookup.scala b/src/test/scala/chiselTests/MulLookup.scala index dd539b2a..0f67ea34 100644 --- a/src/test/scala/chiselTests/MulLookup.scala +++ b/src/test/scala/chiselTests/MulLookup.scala @@ -7,9 +7,9 @@ import chisel3.testers.BasicTester class MulLookup(val w: Int) extends Module { val io = IO(new Bundle { - val x = Input(UInt(w.W)) - val y = Input(UInt(w.W)) - val z = Output(UInt((2 * w).W)) + val x = Input(UInt(w.W)) + val y = Input(UInt(w.W)) + val z = Output(UInt((2 * w).W)) }) val tbl = VecInit( for { @@ -32,7 +32,7 @@ class MulLookupSpec extends ChiselPropSpec { property("Mul lookup table should return the correct result") { forAll(smallPosInts, smallPosInts) { (x: Int, y: Int) => - assertTesterPasses{ new MulLookupTester(3, x, y) } + assertTesterPasses { new MulLookupTester(3, x, y) } } } } diff --git a/src/test/scala/chiselTests/MultiAssign.scala b/src/test/scala/chiselTests/MultiAssign.scala index fb5d6986..4cb51feb 100644 --- a/src/test/scala/chiselTests/MultiAssign.scala +++ b/src/test/scala/chiselTests/MultiAssign.scala @@ -9,16 +9,16 @@ import chisel3.util._ class LastAssignTester() extends BasicTester { val countOnClockCycles = true.B - val (cnt, wrap) = Counter(countOnClockCycles,2) + val (cnt, wrap) = Counter(countOnClockCycles, 2) val test = Wire(UInt(4.W)) - assert(test === 7.U) // allow read references before assign references + assert(test === 7.U) // allow read references before assign references test := 13.U - assert(test === 7.U) // output value should be position-independent + assert(test === 7.U) // output value should be position-independent test := 7.U - assert(test === 7.U) // this obviously should work + assert(test === 7.U) // this obviously should work when(cnt === 1.U) { stop() @@ -27,7 +27,7 @@ class LastAssignTester() extends BasicTester { class MultiAssignSpec extends ChiselFlatSpec { "The last assignment" should "be used when multiple assignments happen" in { - assertTesterPasses{ new LastAssignTester } + assertTesterPasses { new LastAssignTester } } } @@ -35,7 +35,7 @@ class IllegalAssignSpec extends ChiselFlatSpec with Utils { "Reassignments to literals" should "be disallowed" in { intercept[chisel3.internal.ChiselException] { extractCause[ChiselException] { - ChiselStage.elaborate{ + ChiselStage.elaborate { new BasicTester { 15.U := 7.U } @@ -47,7 +47,7 @@ class IllegalAssignSpec extends ChiselFlatSpec with Utils { "Reassignments to ops" should "be disallowed" in { intercept[chisel3.internal.ChiselException] { extractCause[ChiselException] { - ChiselStage.elaborate{ + ChiselStage.elaborate { new BasicTester { (15.U + 1.U) := 7.U } @@ -59,7 +59,7 @@ class IllegalAssignSpec extends ChiselFlatSpec with Utils { "Reassignments to bit slices" should "be disallowed" in { intercept[chisel3.internal.ChiselException] { extractCause[ChiselException] { - ChiselStage.elaborate{ + ChiselStage.elaborate { new BasicTester { (15.U)(1, 0) := 7.U } @@ -71,7 +71,7 @@ class IllegalAssignSpec extends ChiselFlatSpec with Utils { "Bulk-connecting two read-only nodes" should "be disallowed" in { intercept[chisel3.internal.ChiselException] { extractCause[ChiselException] { - ChiselStage.elaborate{ + ChiselStage.elaborate { new BasicTester { (15.U + 1.U) <> 7.U } diff --git a/src/test/scala/chiselTests/MultiClockSpec.scala b/src/test/scala/chiselTests/MultiClockSpec.scala index 3b52e5b9..2553f3b3 100644 --- a/src/test/scala/chiselTests/MultiClockSpec.scala +++ b/src/test/scala/chiselTests/MultiClockSpec.scala @@ -18,11 +18,11 @@ class ClockDividerTest extends BasicTester { val reg2 = withClock(clock2) { RegInit(0.U(8.W)) } reg2 := reg2 + 1.U - when (reg1 < 10.U) { + when(reg1 < 10.U) { assert(reg2 === reg1 / 2.U) // 1:2 clock relationship } - when (reg1 === 10.U) { + when(reg1 === 10.U) { stop() } } @@ -45,7 +45,7 @@ class MultiClockSubModuleTest extends BasicTester { val inst = withClockAndReset(otherClock, otherReset) { Module(new SubModule) } - when (done) { + when(done) { // The counter in inst should come out of reset later and increment at half speed assert(inst.io.out === 3.U) stop() @@ -59,14 +59,14 @@ class WithResetTest extends BasicTester { reg := reg + 1.U val (cycle, done) = Counter(true.B, 10) - when (cycle < 7.U) { + when(cycle < 7.U) { assert(reg === cycle) - } .elsewhen (cycle === 7.U) { + }.elsewhen(cycle === 7.U) { reset2 := true.B - } .elsewhen (cycle === 8.U) { + }.elsewhen(cycle === 8.U) { assert(reg === 0.U) } - when (done) { stop() } + when(done) { stop() } } /** Test Mem ports with different clocks */ @@ -82,7 +82,7 @@ class MultiClockMemTest extends BasicTester { // Write port 1 walks through writing 123 val waddr = RegInit(0.U(3.W)) waddr := waddr + 1.U - when (cycle < 8.U) { + when(cycle < 8.U) { mem(waddr) := 123.U } @@ -90,27 +90,27 @@ class MultiClockMemTest extends BasicTester { val rdata = mem(raddr) // Check each write from write port 1 - when (cycle > 0.U && cycle < 9.U) { + when(cycle > 0.U && cycle < 9.U) { assert(rdata === 123.U) } // Write port 2 walks through writing 456 on 2nd time through withClock(clock2) { - when (cycle >= 8.U && cycle < 16.U) { + when(cycle >= 8.U && cycle < 16.U) { mem(waddr) := 456.U // write 456 to different address } } // Check that every even address gets 456 - when (cycle > 8.U && cycle < 17.U) { - when (raddr % 2.U === 0.U) { + when(cycle > 8.U && cycle < 17.U) { + when(raddr % 2.U === 0.U) { assert(rdata === 456.U) - } .otherwise { + }.otherwise { assert(rdata === 123.U) } } - when (done) { stop() } + when(done) { stop() } } class MultiClockSpec extends ChiselFlatSpec { @@ -151,7 +151,7 @@ class MultiClockSpec extends ChiselFlatSpec { // The reg is always in reset so will never decrement chisel3.assert(reg === 6.U) val (_, done) = Counter(true.B, 4) - when (done) { stop() } + when(done) { stop() } }) } @@ -168,7 +168,7 @@ class MultiClockSpec extends ChiselFlatSpec { chisel3.assert(0.U === 1.U) } val (_, done) = Counter(true.B, 2) - when (done) { stop() } + when(done) { stop() } }) // Check that reset will block assertTesterPasses(new BasicTester { @@ -176,7 +176,7 @@ class MultiClockSpec extends ChiselFlatSpec { chisel3.assert(0.U === 1.U) } val (_, done) = Counter(true.B, 2) - when (done) { stop() } + when(done) { stop() } }) // Check that no rising edge will block assertTesterPasses(new BasicTester { @@ -184,7 +184,7 @@ class MultiClockSpec extends ChiselFlatSpec { chisel3.assert(0.U === 1.U) } val (_, done) = Counter(true.B, 2) - when (done) { stop() } + when(done) { stop() } }) } } diff --git a/src/test/scala/chiselTests/MultiIOModule.scala b/src/test/scala/chiselTests/MultiIOModule.scala index 9abf324b..c65d8fc4 100644 --- a/src/test/scala/chiselTests/MultiIOModule.scala +++ b/src/test/scala/chiselTests/MultiIOModule.scala @@ -6,7 +6,7 @@ import chisel3._ import chisel3.testers.BasicTester class MultiIOPlusOne extends Module { - val in = IO(Input(UInt(32.W))) + val in = IO(Input(UInt(32.W))) val out = IO(Output(UInt(32.W))) out := in + 1.asUInt @@ -33,8 +33,7 @@ trait MultiIOTrait extends Module { // Composition of the two above traits, example of IO composition directly using multiple top-level // IOs rather than indirectly by constraining the type of the single .io field. -class ComposedMultiIOModule extends Module - with LiteralOutputTrait with MultiIOTrait { +class ComposedMultiIOModule extends Module with LiteralOutputTrait with MultiIOTrait { val topModuleIO = IO(Input(UInt(32.W))) myTraitIO := topModuleIO } diff --git a/src/test/scala/chiselTests/MuxSpec.scala b/src/test/scala/chiselTests/MuxSpec.scala index 33024f0b..03505f2d 100644 --- a/src/test/scala/chiselTests/MuxSpec.scala +++ b/src/test/scala/chiselTests/MuxSpec.scala @@ -4,21 +4,21 @@ package chiselTests import chisel3._ import chisel3.stage.ChiselStage -import chisel3.util.{MuxLookup, log2Ceil} +import chisel3.util.{log2Ceil, MuxLookup} import chisel3.testers.BasicTester class MuxTester extends BasicTester { assert(Mux(0.B, 1.U, 2.U) === 2.U) assert(Mux(1.B, 1.U, 2.U) === 1.U) val dontCareMux1 = Wire(UInt()) - dontCareMux1 := Mux(0.B, DontCare, 4.U) // note: Mux output of type Element + dontCareMux1 := Mux(0.B, DontCare, 4.U) // note: Mux output of type Element assert(dontCareMux1 === 4.U) val dontCareMux2 = Wire(UInt()) - dontCareMux2 := Mux(1.B, 3.U, DontCare) // note: Mux output of type Element + dontCareMux2 := Mux(1.B, 3.U, DontCare) // note: Mux output of type Element assert(dontCareMux2 === 3.U) - Mux(0.B, 3.U, DontCare) // just to make sure nothing crashes, any result is valid + Mux(0.B, 3.U, DontCare) // just to make sure nothing crashes, any result is valid stop() } @@ -45,27 +45,28 @@ class MuxLookupExhaustiveSpec extends ChiselPropSpec { val incomplete = () => Seq(0.U -> 1.U, 1.U -> 2.U, 2.U -> 3.U) property("The default value should not be optimized away for an incomplete MuxLookup") { - ChiselStage.emitChirrtl(new MuxLookupWrapper(keyWidth, default, incomplete)) should include (firrtlLit) + ChiselStage.emitChirrtl(new MuxLookupWrapper(keyWidth, default, incomplete)) should include(firrtlLit) } val exhaustive = () => (3.U -> 0.U) +: incomplete() property("The default value should be optimized away for an exhaustive MuxLookup") { - ChiselStage.emitChirrtl(new MuxLookupWrapper(keyWidth, default, exhaustive)) should not include (firrtlLit) + (ChiselStage.emitChirrtl(new MuxLookupWrapper(keyWidth, default, exhaustive)) should not).include(firrtlLit) } val overlap = () => (4096.U -> 0.U) +: incomplete() property("The default value should not be optimized away for a MuxLookup with 2^{keyWidth} non-distinct mappings") { - ChiselStage.emitChirrtl(new MuxLookupWrapper(keyWidth, default, overlap)) should include (firrtlLit) + ChiselStage.emitChirrtl(new MuxLookupWrapper(keyWidth, default, overlap)) should include(firrtlLit) } val nonLiteral = () => { val foo = Wire(UInt()); (foo -> 1.U) +: incomplete() } property("The default value should not be optimized away for a MuxLookup with a non-literal") { - ChiselStage.emitChirrtl(new MuxLookupWrapper(keyWidth, default, nonLiteral)) should include (firrtlLit) + ChiselStage.emitChirrtl(new MuxLookupWrapper(keyWidth, default, nonLiteral)) should include(firrtlLit) } val nonLiteralStillFull = () => { val foo = Wire(UInt()); (foo -> 1.U) +: exhaustive() } property("The default value should be optimized away for a MuxLookup with a non-literal that is still full") { - ChiselStage.emitChirrtl(new MuxLookupWrapper(keyWidth, default, nonLiteralStillFull)) should not include (firrtlLit) + (ChiselStage.emitChirrtl(new MuxLookupWrapper(keyWidth, default, nonLiteralStillFull)) should not) + .include(firrtlLit) } } diff --git a/src/test/scala/chiselTests/NamingAnnotationTest.scala b/src/test/scala/chiselTests/NamingAnnotationTest.scala index 2226a48a..ded321cd 100644 --- a/src/test/scala/chiselTests/NamingAnnotationTest.scala +++ b/src/test/scala/chiselTests/NamingAnnotationTest.scala @@ -70,7 +70,7 @@ class NamedModule extends NamedModuleTester { def FunctionMockupInner(): UInt = { val my2A = 1.U val my2B = expectName(my2A +& 2.U, "test_myNested_my2B") - val my2C = my2B +& 3.U // should get named at enclosing scope + val my2C = my2B +& 3.U // should get named at enclosing scope my2C } @@ -85,14 +85,14 @@ class NamedModule extends NamedModuleTester { for ((d, i) <- myD.zipWithIndex) expectName(d, s"test_myD_$i") - myC +& 4.U // named at enclosing scope + myC +& 4.U // named at enclosing scope } // chiselName "implicitly" applied def ImplicitlyNamed(): UInt = { val implicitA = expectName(1.U + 2.U, "test3_implicitA") val implicitB = expectName(implicitA + 3.U, "test3_implicitB") - implicitB + 2.U // named at enclosing scope + implicitB + 2.U // named at enclosing scope } // Ensure this applies a partial name if there is no return value @@ -115,8 +115,9 @@ class NamedModule extends NamedModuleTester { } // Test that contents of anonymous functions are named - Seq((0, "anonInner"), (1, "anonInner_1"), (2, "anonInner_2")).foreach { case (in, name) => - val anonInner = expectName(test3 + in.U, name) + Seq((0, "anonInner"), (1, "anonInner_1"), (2, "anonInner_2")).foreach { + case (in, name) => + val anonInner = expectName(test3 + in.U, name) } NoReturnFunction() @@ -126,8 +127,8 @@ class NamedModule extends NamedModuleTester { class NameCollisionModule extends NamedModuleTester { @chiselName def repeatedCalls(id: Int): UInt = { - val test = expectName(1.U + 3.U, s"test_$id") // should disambiguate by invocation order - test + 2.U + val test = expectName(1.U + 3.U, s"test_$id") // should disambiguate by invocation order + test + 2.U } // chiselName applied by default to this @@ -167,7 +168,7 @@ object NonNamedHelper { myVal } - def NonNamedFunction() : UInt = { + def NonNamedFunction(): UInt = { val myVal = NamedFunction() myVal } @@ -230,7 +231,6 @@ class NoChiselNamePrefixTester extends NamedModuleTester { expectName(fizz.c, "fizz_c") } - /** A simple test that checks the recursive function val naming annotation both compiles and * generates the expected names. */ @@ -265,7 +265,7 @@ class NamingAnnotationSpec extends ChiselPropSpec { } property("NonBuilderFunction should run outside a Builder context") { - NonNamedHelper.NonBuilderFunction() should be (2) + NonNamedHelper.NonBuilderFunction() should be(2) } property("NoChiselNamePrefix should prevent prefixing when using @chiselName") { diff --git a/src/test/scala/chiselTests/OneHotMuxSpec.scala b/src/test/scala/chiselTests/OneHotMuxSpec.scala index 7608a3e7..b069b219 100644 --- a/src/test/scala/chiselTests/OneHotMuxSpec.scala +++ b/src/test/scala/chiselTests/OneHotMuxSpec.scala @@ -11,7 +11,6 @@ import org.scalatest._ import org.scalatest.freespec.AnyFreeSpec import org.scalatest.matchers.should.Matchers - class OneHotMuxSpec extends AnyFreeSpec with Matchers with ChiselRunners { "simple one hot mux with uint should work" in { assertTesterPasses(new SimpleOneHotTester) @@ -32,7 +31,7 @@ class OneHotMuxSpec extends AnyFreeSpec with Matchers with ChiselRunners { assertTesterPasses(new ParameterizedAggregateOneHotTester) } "simple one hot mux with all aggregates containing inferred width fixed values should NOT work" in { - intercept [ChiselException] { + intercept[ChiselException] { assertTesterPasses(new InferredWidthAggregateOneHotTester) } } @@ -56,12 +55,14 @@ class OneHotMuxSpec extends AnyFreeSpec with Matchers with ChiselRunners { class SimpleOneHotTester extends BasicTester { val out = Wire(UInt()) - out := Mux1H(Seq( - false.B -> 2.U, - false.B -> 4.U, - true.B -> 8.U, - false.B -> 11.U - )) + out := Mux1H( + Seq( + false.B -> 2.U, + false.B -> 4.U, + true.B -> 8.U, + false.B -> 11.U + ) + ) assert(out === 8.U) @@ -70,12 +71,14 @@ class SimpleOneHotTester extends BasicTester { class SIntOneHotTester extends BasicTester { val out = Wire(SInt()) - out := Mux1H(Seq( - false.B -> (-3).S, - true.B -> (-5).S, - false.B -> (-7).S, - false.B -> (-11).S - )) + out := Mux1H( + Seq( + false.B -> (-3).S, + true.B -> (-5).S, + false.B -> (-7).S, + false.B -> (-11).S + ) + ) assert(out === (-5).S) @@ -85,12 +88,14 @@ class SIntOneHotTester extends BasicTester { class FixedPointOneHotTester extends BasicTester { val out = Wire(FixedPoint(8.W, 4.BP)) - out := Mux1H(Seq( - false.B -> (-1.5).F(1.BP), - true.B -> (-2.25).F(2.BP), - false.B -> (-4.125).F(3.BP), - false.B -> (-11.625).F(3.BP) - )) + out := Mux1H( + Seq( + false.B -> (-1.5).F(1.BP), + true.B -> (-2.25).F(2.BP), + false.B -> (-4.125).F(3.BP), + false.B -> (-11.625).F(3.BP) + ) + ) assert(out === (-2.25).F(4.BP)) @@ -100,12 +105,14 @@ class FixedPointOneHotTester extends BasicTester { class AllSameFixedPointOneHotTester extends BasicTester { val out = Wire(FixedPoint(12.W, 3.BP)) - out := Mux1H(Seq( - false.B -> (-1.5).F(12.W, 3.BP), - true.B -> (-2.25).F(12.W, 3.BP), - false.B -> (-4.125).F(12.W, 3.BP), - false.B -> (-11.625).F(12.W, 3.BP) - )) + out := Mux1H( + Seq( + false.B -> (-1.5).F(12.W, 3.BP), + true.B -> (-2.25).F(12.W, 3.BP), + false.B -> (-4.125).F(12.W, 3.BP), + false.B -> (-11.625).F(12.W, 3.BP) + ) + ) assert(out === (-2.25).F(14.W, 4.BP)) @@ -199,7 +206,6 @@ class ParameterizedAggregateOneHot[T <: Data](valGen: HasMakeLit[T], outGen: T) val out = Output(outGen) }) - val values = (0 until 4).map { n => valGen.makeLit(n) } val terms = io.selectors.zip(values) io.out := Mux1H(terms) @@ -229,22 +235,26 @@ class InferredWidthAggregateOneHotTester extends BasicTester { b3.a := -0.0078125.F(7.BP) b3.b.c := -0.00390625.F(8.BP) - val o1 = Mux1H(Seq( - false.B -> b0, - false.B -> b1, - true.B -> b2, - false.B -> b3 - )) + val o1 = Mux1H( + Seq( + false.B -> b0, + false.B -> b1, + true.B -> b2, + false.B -> b3 + ) + ) assert(o1.a === -0.015625.F(5.BP)) assert(o1.b.c === -0.0078125.F(6.BP)) - val o2 = Mux1H(Seq( - false.B -> b0, - true.B -> b1, - false.B -> b2, - false.B -> b3 - )) + val o2 = Mux1H( + Seq( + false.B -> b0, + true.B -> b1, + false.B -> b2, + false.B -> b3 + ) + ) assert(o2.a === -0.0625.F(3.BP)) assert(o2.b.c === -0.03125.F(4.BP)) @@ -283,12 +293,14 @@ class DifferentBundleOneHotTester extends BasicTester { b3.a := -0.0078125.F(7.BP) b3.b.c := -0.00390625.F(8.BP) - val o1 = Mux1H(Seq( - false.B -> b0, - false.B -> b1, - true.B -> b2, - false.B -> b3 - )) + val o1 = Mux1H( + Seq( + false.B -> b0, + false.B -> b1, + true.B -> b2, + false.B -> b3 + ) + ) stop() } diff --git a/src/test/scala/chiselTests/OptionBundle.scala b/src/test/scala/chiselTests/OptionBundle.scala index 0f3502a4..628e117d 100644 --- a/src/test/scala/chiselTests/OptionBundle.scala +++ b/src/test/scala/chiselTests/OptionBundle.scala @@ -55,7 +55,7 @@ class OptionBundleSpec extends ChiselFlatSpec with Utils { } "A Bundle with an Option field" should "assert out accessing a None Option field" in { - a [Exception] should be thrownBy extractCause[Exception] { + a[Exception] should be thrownBy extractCause[Exception] { ChiselStage.elaborate { new InvalidOptionBundleTester() } } } diff --git a/src/test/scala/chiselTests/Padding.scala b/src/test/scala/chiselTests/Padding.scala index cb1da0b0..7950c203 100644 --- a/src/test/scala/chiselTests/Padding.scala +++ b/src/test/scala/chiselTests/Padding.scala @@ -7,7 +7,7 @@ import chisel3.stage.ChiselStage class Padder extends Module { val io = IO(new Bundle { - val a = Input(UInt(4.W)) + val a = Input(UInt(4.W)) val asp = Output(SInt(8.W)) val aup = Output(UInt(8.W)) }) @@ -31,7 +31,7 @@ class PadsTester(c: Pads) extends Tester(c) { expect(c.io.aup, test_a) } } -*/ + */ class PadderSpec extends ChiselPropSpec { @@ -39,5 +39,5 @@ class PadderSpec extends ChiselPropSpec { ChiselStage.elaborate { new Padder } } - ignore("PadderTester should return the correct result") { } + ignore("PadderTester should return the correct result") {} } diff --git a/src/test/scala/chiselTests/ParameterizedModule.scala b/src/test/scala/chiselTests/ParameterizedModule.scala index 3016728d..3ad054f8 100644 --- a/src/test/scala/chiselTests/ParameterizedModule.scala +++ b/src/test/scala/chiselTests/ParameterizedModule.scala @@ -7,7 +7,7 @@ import chisel3.testers.BasicTester class ParameterizedModule(invert: Boolean) extends Module { val io = IO(new Bundle { - val in = Input(Bool()) + val in = Input(Bool()) val out = Output(Bool()) }) if (invert) { diff --git a/src/test/scala/chiselTests/PopCount.scala b/src/test/scala/chiselTests/PopCount.scala index 42609dff..eaea7a2c 100644 --- a/src/test/scala/chiselTests/PopCount.scala +++ b/src/test/scala/chiselTests/PopCount.scala @@ -9,7 +9,7 @@ import chisel3.testers.BasicTester class PopCountTester(n: Int) extends BasicTester { val x = RegInit(0.U(n.W)) x := x + 1.U - when (RegNext(x === ~0.U(n.W))) { stop() } + when(RegNext(x === ~0.U(n.W))) { stop() } val result = PopCount(x.asBools) val expected = x.asBools.foldLeft(0.U)(_ +& _) @@ -20,6 +20,6 @@ class PopCountTester(n: Int) extends BasicTester { class PopCountSpec extends ChiselPropSpec { property("Mul lookup table should return the correct result") { - forAll(smallPosInts) { (n: Int) => assertTesterPasses { new PopCountTester(n) } } + forAll(smallPosInts) { (n: Int) => assertTesterPasses { new PopCountTester(n) } } } } diff --git a/src/test/scala/chiselTests/PrintableSpec.scala b/src/test/scala/chiselTests/PrintableSpec.scala index c7e819ec..7d584cea 100644 --- a/src/test/scala/chiselTests/PrintableSpec.scala +++ b/src/test/scala/chiselTests/PrintableSpec.scala @@ -20,6 +20,7 @@ case class PrintfAnnotation(target: ReferenceTarget) extends SingleTargetAnnotat } object PrintfAnnotation { + /** Create annotation for a given [[printf]]. * @param c component to be annotated */ @@ -38,7 +39,7 @@ class PrintableSpec extends AnyFlatSpec with Matchers { private case class Printf(str: String, args: Seq[String]) private def getPrintfs(firrtl: String): Seq[Printf] = { def processArgs(str: String): Seq[String] = - str split "," map (_.trim) filter (_.nonEmpty) + str.split(",").map(_.trim).filter(_.nonEmpty) def processBody(str: String): (String, Seq[String]) = { str match { case StringRegex(_, fmt, args) => @@ -47,14 +48,14 @@ class PrintableSpec extends AnyFlatSpec with Matchers { } } - firrtl split "\n" collect { + firrtl.split("\n").collect { case PrintfRegex(matched) => val (str, args) = processBody(matched) Printf(str, args) } } - behavior of "Printable & Custom Interpolator" + behavior.of("Printable & Custom Interpolator") it should "pass exact strings through" in { class MyModule extends BasicTester { @@ -63,7 +64,7 @@ class PrintableSpec extends AnyFlatSpec with Matchers { val firrtl = ChiselStage.emitChirrtl(new MyModule) getPrintfs(firrtl) match { case Seq(Printf("An exact string", Seq())) => - case e => fail() + case e => fail() } } it should "handle Printable and String concatination" in { @@ -73,7 +74,7 @@ class PrintableSpec extends AnyFlatSpec with Matchers { val firrtl = ChiselStage.emitChirrtl(new MyModule) getPrintfs(firrtl) match { case Seq(Printf("First Second Third", Seq())) => - case e => fail() + case e => fail() } } it should "call toString on non-Printable objects" in { @@ -84,7 +85,7 @@ class PrintableSpec extends AnyFlatSpec with Matchers { val firrtl = ChiselStage.emitChirrtl(new MyModule) getPrintfs(firrtl) match { case Seq(Printf("myInt = 1234", Seq())) => - case e => fail() + case e => fail() } } it should "generate proper printf for simple Decimal printing" in { @@ -95,7 +96,7 @@ class PrintableSpec extends AnyFlatSpec with Matchers { val firrtl = ChiselStage.emitChirrtl(new MyModule) getPrintfs(firrtl) match { case Seq(Printf("myWire = %d", Seq("myWire"))) => - case e => fail() + case e => fail() } } it should "handle printing literals" in { @@ -116,7 +117,7 @@ class PrintableSpec extends AnyFlatSpec with Matchers { val firrtl = ChiselStage.emitChirrtl(new MyModule) getPrintfs(firrtl) match { case Seq(Printf("%%", Seq())) => - case e => fail() + case e => fail() } } it should "correctly emit tab" in { @@ -126,7 +127,7 @@ class PrintableSpec extends AnyFlatSpec with Matchers { val firrtl = ChiselStage.emitChirrtl(new MyModule) getPrintfs(firrtl) match { case Seq(Printf("\\t", Seq())) => - case e => fail() + case e => fail() } } it should "support names of circuit elements including submodule IO" in { @@ -150,10 +151,8 @@ class PrintableSpec extends AnyFlatSpec with Matchers { } val firrtl = ChiselStage.emitChirrtl(new MyModule) getPrintfs(firrtl) match { - case Seq(Printf("foo", Seq()), - Printf("myWire.foo", Seq()), - Printf("myInst.io.fizz", Seq())) => - case e => fail() + case Seq(Printf("foo", Seq()), Printf("myWire.foo", Seq()), Printf("myInst.io.fizz", Seq())) => + case e => fail() } } it should "handle printing ports of submodules" in { @@ -169,7 +168,7 @@ class PrintableSpec extends AnyFlatSpec with Matchers { val firrtl = ChiselStage.emitChirrtl(new MyModule) getPrintfs(firrtl) match { case Seq(Printf("%d", Seq("myInst.io.fizz"))) => - case e => fail() + case e => fail() } } it should "print UInts and SInts as Decimal by default" in { @@ -181,20 +180,19 @@ class PrintableSpec extends AnyFlatSpec with Matchers { val firrtl = ChiselStage.emitChirrtl(new MyModule) getPrintfs(firrtl) match { case Seq(Printf("%d & %d", Seq("myUInt", "mySInt"))) => - case e => fail() + case e => fail() } } it should "print Vecs like Scala Seqs by default" in { class MyModule extends BasicTester { val myVec = Wire(Vec(4, UInt(32.W))) - myVec foreach (_ := 0.U) + myVec.foreach(_ := 0.U) printf(p"$myVec") } val firrtl = ChiselStage.emitChirrtl(new MyModule) getPrintfs(firrtl) match { - case Seq(Printf("Vec(%d, %d, %d, %d)", - Seq("myVec[0]", "myVec[1]", "myVec[2]", "myVec[3]"))) => - case e => fail() + case Seq(Printf("Vec(%d, %d, %d, %d)", Seq("myVec[0]", "myVec[1]", "myVec[2]", "myVec[3]"))) => + case e => fail() } } it should "print Bundles like Scala Maps by default" in { @@ -209,9 +207,8 @@ class PrintableSpec extends AnyFlatSpec with Matchers { } val firrtl = ChiselStage.emitChirrtl(new MyModule) getPrintfs(firrtl) match { - case Seq(Printf("AnonymousBundle(foo -> %d, bar -> %d)", - Seq("myBun.foo", "myBun.bar"))) => - case e => fail() + case Seq(Printf("AnonymousBundle(foo -> %d, bar -> %d)", Seq("myBun.foo", "myBun.bar"))) => + case e => fail() } } it should "get emitted with a name and annotated" in { @@ -243,10 +240,10 @@ class PrintableSpec extends AnyFlatSpec with Matchers { val annoLines = scala.io.Source.fromFile(annoFile).getLines.toList // check for expected annotations - exactly(3, annoLines) should include ("chiselTests.PrintfAnnotation") - exactly(1, annoLines) should include ("~PrintfAnnotationTest|PrintfAnnotationTest>farewell") - exactly(1, annoLines) should include ("~PrintfAnnotationTest|PrintfAnnotationTest>printf") - exactly(1, annoLines) should include ("~PrintfAnnotationTest|PrintfAnnotationTest>howdy") + exactly(3, annoLines) should include("chiselTests.PrintfAnnotation") + exactly(1, annoLines) should include("~PrintfAnnotationTest|PrintfAnnotationTest>farewell") + exactly(1, annoLines) should include("~PrintfAnnotationTest|PrintfAnnotationTest>printf") + exactly(1, annoLines) should include("~PrintfAnnotationTest|PrintfAnnotationTest>howdy") // read in FIRRTL file val firFile = new File(testDir, "PrintfAnnotationTest.fir") @@ -254,8 +251,14 @@ class PrintableSpec extends AnyFlatSpec with Matchers { val firLines = scala.io.Source.fromFile(firFile).getLines.toList // check that verification components have expected names - exactly(1, firLines) should include ("""printf(clock, UInt<1>("h1"), "hello AnonymousBundle(foo -> %d, bar -> %d)", myBun.foo, myBun.bar) : howdy""") - exactly(1, firLines) should include ("""printf(clock, UInt<1>("h1"), "goodbye AnonymousBundle(foo -> %d, bar -> %d)", myBun.foo, myBun.bar) : printf""") - exactly(1, firLines) should include ("""printf(clock, UInt<1>("h1"), "adieu AnonymousBundle(foo -> %d, bar -> %d)", myBun.foo, myBun.bar) : farewell""") + exactly(1, firLines) should include( + """printf(clock, UInt<1>("h1"), "hello AnonymousBundle(foo -> %d, bar -> %d)", myBun.foo, myBun.bar) : howdy""" + ) + exactly(1, firLines) should include( + """printf(clock, UInt<1>("h1"), "goodbye AnonymousBundle(foo -> %d, bar -> %d)", myBun.foo, myBun.bar) : printf""" + ) + exactly(1, firLines) should include( + """printf(clock, UInt<1>("h1"), "adieu AnonymousBundle(foo -> %d, bar -> %d)", myBun.foo, myBun.bar) : farewell""" + ) } } diff --git a/src/test/scala/chiselTests/Printf.scala b/src/test/scala/chiselTests/Printf.scala index 24b5e090..4171f97f 100644 --- a/src/test/scala/chiselTests/Printf.scala +++ b/src/test/scala/chiselTests/Printf.scala @@ -24,7 +24,7 @@ class MultiPrintfTester() extends BasicTester { } class ASCIIPrintableTester extends BasicTester { - printf(PString((0x20 to 0x7e) map (_.toChar) mkString "")) + printf(PString((0x20 to 0x7e).map(_.toChar).mkString(""))) stop() } diff --git a/src/test/scala/chiselTests/QueueFlushSpec.scala b/src/test/scala/chiselTests/QueueFlushSpec.scala index 9e0c6bb4..d70f9605 100644 --- a/src/test/scala/chiselTests/QueueFlushSpec.scala +++ b/src/test/scala/chiselTests/QueueFlushSpec.scala @@ -9,24 +9,36 @@ import chisel3.util.random.LFSR import treadle.WriteVcdAnnotation /** Test elements can be enqueued and dequeued when flush is tied to false - * + * * @param elements The sequence of elements used in the queue * @param queueDepth The max number of entries in the queue * @param bitWidth Integer size of the data type used in the queue * @param tap Integer tap('seed') for the LFSR * @param useSyncReadMem True uses SyncReadMem instead of Mem as an internal memory element */ -class ThingsPassThroughFlushQueueTester(elements: Seq[Int], queueDepth: Int, bitWidth: Int, tap: Int, useSyncReadMem: Boolean) extends ThingsPassThroughTester(elements, queueDepth, bitWidth, tap, useSyncReadMem, hasFlush = true) +class ThingsPassThroughFlushQueueTester( + elements: Seq[Int], + queueDepth: Int, + bitWidth: Int, + tap: Int, + useSyncReadMem: Boolean) + extends ThingsPassThroughTester(elements, queueDepth, bitWidth, tap, useSyncReadMem, hasFlush = true) /** Generic flush queue tester base class - * + * * @param elements The sequence of elements used in the queue * @param queueDepth The max number of entries in the queue * @param bitWidth Integer size of the data type used in the queue * @param tap Integer tap('seed') for the LFSR * @param useSyncReadMem True uses SyncReadMem instead of Mem as an internal memory element */ -abstract class FlushQueueTesterBase(elements: Seq[Int], queueDepth: Int, bitWidth: Int, tap: Int, useSyncReadMem: Boolean) extends BasicTester { +abstract class FlushQueueTesterBase( + elements: Seq[Int], + queueDepth: Int, + bitWidth: Int, + tap: Int, + useSyncReadMem: Boolean) + extends BasicTester { val q = Module(new Queue(UInt(bitWidth.W), queueDepth, hasFlush = true)) val elems = VecInit(elements.map(_.U)) val inCnt = Counter(elements.length + 1) @@ -51,31 +63,35 @@ abstract class FlushQueueTesterBase(elements: Seq[Int], queueDepth: Int, bitWidt //check that queue gets flushed when queue is full assert(q.io.count === 0.U) assert(!q.io.deq.valid, "Expected to not be able to dequeue when flush is asserted the previous cycle") - assert(q.io.enq.ready, "Expected enqueue to be ready when flush was asserted the previous cycle because queue should be empty") - } + assert( + q.io.enq.ready, + "Expected enqueue to be ready when flush was asserted the previous cycle because queue should be empty" + ) + } when(inCnt.value === elements.length.U) { //stop when all entries are enqueued stop() } } /** Test queue can flush at random times - * + * * @param elements The sequence of elements used in the queue * @param queueDepth The max number of entries in the queue * @param bitWidth Integer size of the data type used in the queue * @param tap Integer tap('seed') for the LFSR * @param useSyncReadMem True uses SyncReadMem instead of Mem as an internal memory element */ -class QueueGetsFlushedTester(elements: Seq[Int], queueDepth: Int, bitWidth: Int, tap: Int, useSyncReadMem: Boolean) extends FlushQueueTesterBase(elements, queueDepth, bitWidth, tap, useSyncReadMem) { - flush := LFSR(16)((tap + 3) % 16) //testing a flush when flush is called randomly - val halfCnt = (queueDepth + 1)/2 +class QueueGetsFlushedTester(elements: Seq[Int], queueDepth: Int, bitWidth: Int, tap: Int, useSyncReadMem: Boolean) + extends FlushQueueTesterBase(elements, queueDepth, bitWidth, tap, useSyncReadMem) { + flush := LFSR(16)((tap + 3) % 16) //testing a flush when flush is called randomly + val halfCnt = (queueDepth + 1) / 2 when(q.io.deq.fire) { //ensure that what comes out is what comes in assert(currQCnt <= queueDepth.U) assert(elems(outCnt) === q.io.deq.bits) outCnt := outCnt + 1.U - when (currQCnt > 0.U) { + when(currQCnt > 0.U) { currQCnt := Mux(q.io.enq.fire, currQCnt, (currQCnt - 1.U)) } } @@ -87,19 +103,20 @@ class QueueGetsFlushedTester(elements: Seq[Int], queueDepth: Int, bitWidth: Int, } /** Test queue can flush when empty - * + * * @param elements The sequence of elements used in the queue * @param queueDepth The max number of entries in the queue * @param bitWidth Integer size of the data type used in the queue * @param tap Integer tap('seed') for the LFSR * @param useSyncReadMem True uses SyncReadMem instead of Mem as an internal memory element */ -class EmptyFlushEdgecaseTester (elements: Seq[Int], queueDepth: Int, bitWidth: Int, tap: Int, useSyncReadMem: Boolean) extends FlushQueueTesterBase(elements, queueDepth, bitWidth, tap, useSyncReadMem) { +class EmptyFlushEdgecaseTester(elements: Seq[Int], queueDepth: Int, bitWidth: Int, tap: Int, useSyncReadMem: Boolean) + extends FlushQueueTesterBase(elements, queueDepth, bitWidth, tap, useSyncReadMem) { val cycleCounter = Counter(elements.length + 1) cycleCounter.inc() //counts every cycle //testing a flush when queue is empty - flush := (cycleCounter.value === 0.U && inCnt.value === 0.U) //flushed only before anything is enqueued + flush := (cycleCounter.value === 0.U && inCnt.value === 0.U) //flushed only before anything is enqueued q.io.enq.valid := (inCnt.value < elements.length.U) && !flush when(q.io.deq.fire) { @@ -109,23 +126,29 @@ class EmptyFlushEdgecaseTester (elements: Seq[Int], queueDepth: Int, bitWidth: I } /** Test queue can enqueue during a flush - * + * * @param elements The sequence of elements used in the queue * @param queueDepth The max number of entries in the queue * @param bitWidth Integer size of the data type used in the queue * @param tap Integer tap('seed') for the LFSR * @param useSyncReadMem True uses SyncReadMem instead of Mem as an internal memory element */ -class EnqueueEmptyFlushEdgecaseTester (elements: Seq[Int], queueDepth: Int, bitWidth: Int, tap: Int, useSyncReadMem: Boolean) extends FlushQueueTesterBase(elements, queueDepth, bitWidth, tap, useSyncReadMem) { +class EnqueueEmptyFlushEdgecaseTester( + elements: Seq[Int], + queueDepth: Int, + bitWidth: Int, + tap: Int, + useSyncReadMem: Boolean) + extends FlushQueueTesterBase(elements, queueDepth, bitWidth, tap, useSyncReadMem) { val cycleCounter = Counter(elements.length + 1) val outCounter = Counter(elements.length + 1) //testing an enqueue during a flush - flush := (cycleCounter.value === 0.U && inCnt.value === 0.U) //flushed only before anything is enqueued + flush := (cycleCounter.value === 0.U && inCnt.value === 0.U) //flushed only before anything is enqueued cycleCounter.inc() //counts every cycle when(q.io.deq.fire) { - //flush and enqueue were both active on the first cycle, + //flush and enqueue were both active on the first cycle, //so that element is flushed immediately which makes outCnt off by one assert(elems(outCounter.value + 1.U) === q.io.deq.bits) //ensure that what comes out is what comes in outCounter.inc() @@ -133,14 +156,20 @@ class EnqueueEmptyFlushEdgecaseTester (elements: Seq[Int], queueDepth: Int, bitW } /** Test queue can flush when full - * + * * @param elements The sequence of elements used in the queue * @param queueDepth The max number of entries in the queue * @param bitWidth Integer size of the data type used in the queue * @param tap Integer tap('seed') for the LFSR * @param useSyncReadMem True uses SyncReadMem instead of Mem as an internal memory element */ -class FullQueueFlushEdgecaseTester (elements: Seq[Int], queueDepth: Int, bitWidth: Int, tap: Int, useSyncReadMem: Boolean) extends FlushQueueTesterBase(elements, queueDepth, bitWidth, tap, useSyncReadMem) { +class FullQueueFlushEdgecaseTester( + elements: Seq[Int], + queueDepth: Int, + bitWidth: Int, + tap: Int, + useSyncReadMem: Boolean) + extends FlushQueueTesterBase(elements, queueDepth, bitWidth, tap, useSyncReadMem) { //testing a flush when queue is full flush := (currQCnt === queueDepth.U) @@ -150,7 +179,7 @@ class FullQueueFlushEdgecaseTester (elements: Seq[Int], queueDepth: Int, bitWidt assert(currQCnt <= queueDepth.U) assert(elems(outCnt) === q.io.deq.bits) outCnt := outCnt + 1.U - when (currQCnt > 0.U) { + when(currQCnt > 0.U) { currQCnt := currQCnt - 1.U } } @@ -162,18 +191,24 @@ class FullQueueFlushEdgecaseTester (elements: Seq[Int], queueDepth: Int, bitWidt } /** Test queue can dequeue on the same cycle as a flush - * + * * @param elements The sequence of elements used in the queue * @param queueDepth The max number of entries in the queue * @param bitWidth Integer size of the data type used in the queue * @param tap Integer tap('seed') for the LFSR * @param useSyncReadMem True uses SyncReadMem instead of Mem as an internal memory element */ -class DequeueFullQueueEdgecaseTester (elements: Seq[Int], queueDepth: Int, bitWidth: Int, tap: Int, useSyncReadMem: Boolean) extends FlushQueueTesterBase(elements, queueDepth, bitWidth, tap, useSyncReadMem) { +class DequeueFullQueueEdgecaseTester( + elements: Seq[Int], + queueDepth: Int, + bitWidth: Int, + tap: Int, + useSyncReadMem: Boolean) + extends FlushQueueTesterBase(elements, queueDepth, bitWidth, tap, useSyncReadMem) { //Queue should be able to dequeue when queue is not empty and flush is high //testing a flush when dequeue is called - flush := currQCnt === (queueDepth/2).U + flush := currQCnt === (queueDepth / 2).U q.io.enq.valid := !flushRegister q.io.deq.ready := flush @@ -185,14 +220,14 @@ class DequeueFullQueueEdgecaseTester (elements: Seq[Int], queueDepth: Int, bitWi } when(flush) { //The outcount register is one count behind because the dequeue happens at the same time as the flush - outCnt := outCnt + currQCnt + 1.U + outCnt := outCnt + currQCnt + 1.U currQCnt := 0.U //resets the number of items currently inside queue assert(currQCnt === 0.U || q.io.deq.valid) } when(flushRegister) { //check that queue gets flushed when queue is full assert(q.io.deq.fire === false.B) - } + } } @@ -200,7 +235,7 @@ class QueueFlushSpec extends ChiselPropSpec { // Disable shrinking on error. implicit val noShrinkListVal = Shrink[List[Int]](_ => Stream.empty) implicit val noShrinkInt = Shrink[Int](_ => Stream.empty) - + property("Queue should have things pass through") { forAll(vecSizes, safeUIntN(20), Gen.choose(0, 15), Gen.oneOf(true, false)) { (depth, se, tap, isSync) => whenever(se._1 >= 1 && depth >= 1 && se._2.nonEmpty) { @@ -249,7 +284,7 @@ class QueueFlushSpec extends ChiselPropSpec { property("Queue should be able to dequeue when flush is high") { forAll(Gen.choose(3, 5), safeUIntN(20), Gen.choose(0, 15), Gen.oneOf(true, false)) { (depth, se, tap, isSync) => whenever(se._1 >= 1 && depth >= 1 && se._2.nonEmpty) { - assertTesterPasses ( + assertTesterPasses( new DequeueFullQueueEdgecaseTester(se._2, depth, se._1, tap, isSync), annotations = Seq(WriteVcdAnnotation) ) diff --git a/src/test/scala/chiselTests/QueueSpec.scala b/src/test/scala/chiselTests/QueueSpec.scala index 9eb6c20c..eaeb7f01 100644 --- a/src/test/scala/chiselTests/QueueSpec.scala +++ b/src/test/scala/chiselTests/QueueSpec.scala @@ -9,7 +9,14 @@ import chisel3.testers.BasicTester import chisel3.util._ import chisel3.util.random.LFSR -class ThingsPassThroughTester(elements: Seq[Int], queueDepth: Int, bitWidth: Int, tap: Int, useSyncReadMem: Boolean, hasFlush: Boolean) extends BasicTester { +class ThingsPassThroughTester( + elements: Seq[Int], + queueDepth: Int, + bitWidth: Int, + tap: Int, + useSyncReadMem: Boolean, + hasFlush: Boolean) + extends BasicTester { val q = Module(new Queue(UInt(bitWidth.W), queueDepth, useSyncReadMem = useSyncReadMem, hasFlush = hasFlush)) val elems = VecInit(elements.map { _.asUInt() @@ -34,7 +41,8 @@ class ThingsPassThroughTester(elements: Seq[Int], queueDepth: Int, bitWidth: Int } } -class QueueReasonableReadyValid(elements: Seq[Int], queueDepth: Int, bitWidth: Int, tap: Int, useSyncReadMem: Boolean) extends BasicTester { +class QueueReasonableReadyValid(elements: Seq[Int], queueDepth: Int, bitWidth: Int, tap: Int, useSyncReadMem: Boolean) + extends BasicTester { val q = Module(new Queue(UInt(bitWidth.W), queueDepth, useSyncReadMem = useSyncReadMem)) val elems = VecInit(elements.map { _.asUInt() @@ -62,7 +70,8 @@ class QueueReasonableReadyValid(elements: Seq[Int], queueDepth: Int, bitWidth: I } } -class CountIsCorrectTester(elements: Seq[Int], queueDepth: Int, bitWidth: Int, tap: Int, useSyncReadMem: Boolean) extends BasicTester { +class CountIsCorrectTester(elements: Seq[Int], queueDepth: Int, bitWidth: Int, tap: Int, useSyncReadMem: Boolean) + extends BasicTester { val q = Module(new Queue(UInt(bitWidth.W), queueDepth, useSyncReadMem = useSyncReadMem)) val elems = VecInit(elements.map { _.asUInt(bitWidth.W) @@ -115,7 +124,8 @@ class QueueSinglePipeTester(elements: Seq[Int], bitWidth: Int, tap: Int, useSync } } -class QueuePipeTester(elements: Seq[Int], queueDepth: Int, bitWidth: Int, tap: Int, useSyncReadMem: Boolean) extends BasicTester { +class QueuePipeTester(elements: Seq[Int], queueDepth: Int, bitWidth: Int, tap: Int, useSyncReadMem: Boolean) + extends BasicTester { val q = Module(new Queue(UInt(bitWidth.W), queueDepth, pipe = true, useSyncReadMem = useSyncReadMem)) val elems = VecInit(elements.map { _.asUInt(bitWidth.W) @@ -141,8 +151,9 @@ class QueuePipeTester(elements: Seq[Int], queueDepth: Int, bitWidth: Int, tap: I } } -class QueueFlowTester(elements: Seq[Int], queueDepth: Int, bitWidth: Int, tap: Int, useSyncReadMem: Boolean) extends BasicTester { - val q = Module(new Queue(UInt(bitWidth.W), queueDepth, flow = true, useSyncReadMem = useSyncReadMem)) +class QueueFlowTester(elements: Seq[Int], queueDepth: Int, bitWidth: Int, tap: Int, useSyncReadMem: Boolean) + extends BasicTester { + val q = Module(new Queue(UInt(bitWidth.W), queueDepth, flow = true, useSyncReadMem = useSyncReadMem)) val elems = VecInit(elements.map { _.asUInt() }) @@ -169,7 +180,8 @@ class QueueFlowTester(elements: Seq[Int], queueDepth: Int, bitWidth: Int, tap: I } } -class QueueFactoryTester(elements: Seq[Int], queueDepth: Int, bitWidth: Int, tap: Int, useSyncReadMem: Boolean) extends BasicTester { +class QueueFactoryTester(elements: Seq[Int], queueDepth: Int, bitWidth: Int, tap: Int, useSyncReadMem: Boolean) + extends BasicTester { val enq = Wire(Decoupled(UInt(bitWidth.W))) val deq = Queue(enq, queueDepth, useSyncReadMem = useSyncReadMem) @@ -276,6 +288,7 @@ class QueueSpec extends ChiselPropSpec { val in = Wire(Decoupled(Bool())) val iQueue = Queue.irrevocable(in, 1) } - (new chisel3.stage.phases.Elaborate).transform(Seq(chisel3.stage.ChiselGeneratorAnnotation(() => new IrrevocableQueue))) + (new chisel3.stage.phases.Elaborate) + .transform(Seq(chisel3.stage.ChiselGeneratorAnnotation(() => new IrrevocableQueue))) } } diff --git a/src/test/scala/chiselTests/RangeSpec.scala b/src/test/scala/chiselTests/RangeSpec.scala index 0b888ab6..bc723bf6 100644 --- a/src/test/scala/chiselTests/RangeSpec.scala +++ b/src/test/scala/chiselTests/RangeSpec.scala @@ -9,5 +9,4 @@ import firrtl.ir.{Closed, Open} import org.scalatest.freespec.AnyFreeSpec import org.scalatest.matchers.should.Matchers -class RangeSpec extends AnyFreeSpec with Matchers { -} +class RangeSpec extends AnyFreeSpec with Matchers {} diff --git a/src/test/scala/chiselTests/RawModuleSpec.scala b/src/test/scala/chiselTests/RawModuleSpec.scala index 3d678d1f..95687e82 100644 --- a/src/test/scala/chiselTests/RawModuleSpec.scala +++ b/src/test/scala/chiselTests/RawModuleSpec.scala @@ -7,7 +7,7 @@ import chisel3.stage.ChiselStage import chisel3.testers.BasicTester class UnclockedPlusOne extends RawModule { - val in = IO(Input(UInt(32.W))) + val in = IO(Input(UInt(32.W))) val out = IO(Output(UInt(32.W))) out := in + 1.asUInt @@ -22,14 +22,14 @@ class RawModuleTester extends BasicTester { class PlusOneModule extends Module { val io = IO(new Bundle { - val in = Input(UInt(32.W)) + val in = Input(UInt(32.W)) val out = Output(UInt(32.W)) }) io.out := io.in + 1.asUInt } class RawModuleWithImplicitModule extends RawModule { - val in = IO(Input(UInt(32.W))) + val in = IO(Input(UInt(32.W))) val out = IO(Output(UInt(32.W))) val clk = IO(Input(Clock())) val rst = IO(Input(Bool())) @@ -72,7 +72,6 @@ class RawModuleSpec extends ChiselFlatSpec with Utils { assertTesterPasses({ new ImplicitModuleInRawModuleTester }) } - "ImplicitModule directly in a RawModule" should "fail" in { intercept[chisel3.internal.ChiselException] { extractCause[ChiselException] { diff --git a/src/test/scala/chiselTests/RebindingSpec.scala b/src/test/scala/chiselTests/RebindingSpec.scala index 808b1137..5dc0589e 100644 --- a/src/test/scala/chiselTests/RebindingSpec.scala +++ b/src/test/scala/chiselTests/RebindingSpec.scala @@ -7,22 +7,26 @@ import chisel3.stage.ChiselStage class RebindingSpec extends ChiselFlatSpec with Utils { "Rebinding a literal" should "fail" in { - a [BindingException] should be thrownBy extractCause[BindingException] { - ChiselStage.elaborate { new Module { - val io = IO(new Bundle { - val a = 4.U - }) - } } + a[BindingException] should be thrownBy extractCause[BindingException] { + ChiselStage.elaborate { + new Module { + val io = IO(new Bundle { + val a = 4.U + }) + } + } } } "Rebinding a hardware type" should "fail" in { - a [BindingException] should be thrownBy extractCause[BindingException] { - ChiselStage.elaborate { new Module { - val io = IO(new Bundle { - val a = Reg(UInt(32.W)) - }) - } } + a[BindingException] should be thrownBy extractCause[BindingException] { + ChiselStage.elaborate { + new Module { + val io = IO(new Bundle { + val a = Reg(UInt(32.W)) + }) + } + } } } } diff --git a/src/test/scala/chiselTests/RecordSpec.scala b/src/test/scala/chiselTests/RecordSpec.scala index e6986efb..da3840dd 100644 --- a/src/test/scala/chiselTests/RecordSpec.scala +++ b/src/test/scala/chiselTests/RecordSpec.scala @@ -50,18 +50,18 @@ trait RecordSpecUtils { queue.io.enq.valid := false.B val (cycle, done) = Counter(true.B, 4) - when (cycle === 0.U) { + when(cycle === 0.U) { queue.io.enq.bits("foo") := 1234.U queue.io.enq.bits("bar") := 5678.U queue.io.enq.valid := true.B } - when (cycle === 1.U) { + when(cycle === 1.U) { queue.io.deq.ready := true.B assert(queue.io.deq.valid === true.B) assert(queue.io.deq.bits("foo").asUInt === 1234.U) assert(queue.io.deq.bits("bar").asUInt === 5678.U) } - when (done) { + when(done) { stop() } } @@ -91,16 +91,16 @@ trait RecordSpecUtils { } class RecordTypeTester extends BasicTester { - val wire0 = Wire(new CustomBundle("0"-> UInt(32.W))) - val wire1 = Reg(new CustomBundle("0"-> UInt(32.W))) - val wire2 = Wire(new CustomBundle("1"-> UInt(32.W))) + val wire0 = Wire(new CustomBundle("0" -> UInt(32.W))) + val wire1 = Reg(new CustomBundle("0" -> UInt(32.W))) + val wire2 = Wire(new CustomBundle("1" -> UInt(32.W))) require(DataMirror.checkTypeEquivalence(wire0, wire1)) require(!DataMirror.checkTypeEquivalence(wire1, wire2)) } } class RecordSpec extends ChiselFlatSpec with RecordSpecUtils with Utils { - behavior of "Records" + behavior.of("Records") they should "bulk connect similarly to Bundles" in { ChiselStage.elaborate { new MyModule(fooBarType, fooBarType) } @@ -124,7 +124,7 @@ class RecordSpec extends ChiselFlatSpec with RecordSpecUtils with Utils { } } } - e.getMessage should include ("contains aliased fields named (bar,foo)") + e.getMessage should include("contains aliased fields named (bar,foo)") } they should "follow UInt serialization/deserialization API" in { @@ -144,13 +144,13 @@ class RecordSpec extends ChiselFlatSpec with RecordSpecUtils with Utils { } "Bulk connect on Record" should "check that the fields match" in { - (the [ChiselException] thrownBy extractCause[ChiselException] { + (the[ChiselException] thrownBy extractCause[ChiselException] { ChiselStage.elaborate { new MyModule(fooBarType, new CustomBundle("bar" -> UInt(32.W))) } - }).getMessage should include ("Right Record missing field") + }).getMessage should include("Right Record missing field") - (the [ChiselException] thrownBy extractCause[ChiselException] { + (the[ChiselException] thrownBy extractCause[ChiselException] { ChiselStage.elaborate { new MyModule(new CustomBundle("bar" -> UInt(32.W)), fooBarType) } - }).getMessage should include ("Left Record missing field") + }).getMessage should include("Left Record missing field") } "CustomBundle" should "work like built-in aggregates" in { diff --git a/src/test/scala/chiselTests/Reg.scala b/src/test/scala/chiselTests/Reg.scala index a02e6fa5..c814a030 100644 --- a/src/test/scala/chiselTests/Reg.scala +++ b/src/test/scala/chiselTests/Reg.scala @@ -13,19 +13,19 @@ class RegSpec extends ChiselFlatSpec { "Reg" should "be of the same type and width as t" in { class RegOutTypeWidthTester extends BasicTester { val reg = Reg(UInt(2.W)) - DataMirror.widthOf(reg) should be (2.W) + DataMirror.widthOf(reg) should be(2.W) } - ChiselStage.elaborate{ new RegOutTypeWidthTester } + ChiselStage.elaborate { new RegOutTypeWidthTester } } "RegNext" should "be of unknown width" in { class RegUnknownWidthTester extends BasicTester { val reg1 = RegNext(2.U(3.W)) - DataMirror.widthOf(reg1).known should be (false) + DataMirror.widthOf(reg1).known should be(false) val reg2 = RegNext(2.U(3.W), 4.U) - DataMirror.widthOf(reg2).known should be (false) + DataMirror.widthOf(reg2).known should be(false) val reg3 = RegNext(2.U(3.W), 4.U(5.W)) - DataMirror.widthOf(reg3).known should be (false) + DataMirror.widthOf(reg3).known should be(false) } ChiselStage.elaborate { new RegUnknownWidthTester } } @@ -33,11 +33,11 @@ class RegSpec extends ChiselFlatSpec { "RegInit" should "have width only if specified in the literal" in { class RegForcedWidthTester extends BasicTester { val reg1 = RegInit(20.U) - DataMirror.widthOf(reg1).known should be (false) + DataMirror.widthOf(reg1).known should be(false) val reg2 = RegInit(20.U(7.W)) - DataMirror.widthOf(reg2) should be (7.W) + DataMirror.widthOf(reg2) should be(7.W) } - ChiselStage.elaborate{ new RegForcedWidthTester } + ChiselStage.elaborate { new RegForcedWidthTester } } } @@ -52,22 +52,22 @@ class ShiftTester(n: Int) extends BasicTester { } class ShiftResetTester(n: Int) extends BasicTester { - val (cntVal, done) = Counter(true.B, n-1) + val (cntVal, done) = Counter(true.B, n - 1) val start = 23.U val sr = ShiftRegister(cntVal + 23.U, n, 1.U, true.B) when(done) { - assert(sr === (if(n == 0) cntVal + 23.U else 1.U)) + assert(sr === (if (n == 0) cntVal + 23.U else 1.U)) stop() } } class ShiftRegisterSpec extends ChiselPropSpec { property("ShiftRegister should shift") { - forAll(Gen.choose(0, 4)) { (shift: Int) => assertTesterPasses{ new ShiftTester(shift) } } + forAll(Gen.choose(0, 4)) { (shift: Int) => assertTesterPasses { new ShiftTester(shift) } } } property("ShiftRegister should reset all values inside") { - forAll(Gen.choose(0, 4)) { (shift: Int) => assertTesterPasses{ new ShiftResetTester(shift) } } + forAll(Gen.choose(0, 4)) { (shift: Int) => assertTesterPasses { new ShiftResetTester(shift) } } } } @@ -76,8 +76,9 @@ class ShiftsTester(n: Int) extends BasicTester { val start = 23.U val srs = ShiftRegisters(cntVal + start, n) when(RegNext(done)) { - srs.zipWithIndex.foreach{ case (data, index) => - assert(data === (23 + n - 1 - index).U) + srs.zipWithIndex.foreach { + case (data, index) => + assert(data === (23 + n - 1 - index).U) } stop() } @@ -85,6 +86,6 @@ class ShiftsTester(n: Int) extends BasicTester { class ShiftRegistersSpec extends ChiselPropSpec { property("ShiftRegisters should shift") { - forAll(Gen.choose(0, 4)) { (shift: Int) => assertTesterPasses{ new ShiftsTester(shift) } } + forAll(Gen.choose(0, 4)) { (shift: Int) => assertTesterPasses { new ShiftsTester(shift) } } } } diff --git a/src/test/scala/chiselTests/ResetSpec.scala b/src/test/scala/chiselTests/ResetSpec.scala index 7a5d444d..fe0273b3 100644 --- a/src/test/scala/chiselTests/ResetSpec.scala +++ b/src/test/scala/chiselTests/ResetSpec.scala @@ -35,10 +35,9 @@ class AbstractResetDontCareModule extends RawModule { bulkAggPort <> DontCare } - class ResetSpec extends ChiselFlatSpec with Utils { - behavior of "Reset" + behavior.of("Reset") it should "be able to be connected to DontCare" in { ChiselStage.elaborate(new AbstractResetDontCareModule) @@ -75,7 +74,7 @@ class ResetSpec extends ChiselFlatSpec with Utils { assert(inst.rst.isInstanceOf[chisel3.ResetType]) io.out := inst.out }) - sync should include ("always @(posedge clk)") + sync should include("always @(posedge clk)") val async = compile(new Module { val io = IO(new Bundle { @@ -87,27 +86,27 @@ class ResetSpec extends ChiselFlatSpec with Utils { assert(inst.rst.isInstanceOf[chisel3.ResetType]) io.out := inst.out }) - async should include ("always @(posedge clk or posedge rst)") + async should include("always @(posedge clk or posedge rst)") } - behavior of "Users" + behavior.of("Users") they should "be able to force implicit reset to be synchronous" in { val fir = ChiselStage.emitChirrtl(new Module with RequireSyncReset { - reset shouldBe a [Bool] + reset shouldBe a[Bool] }) - fir should include ("input reset : UInt<1>") + fir should include("input reset : UInt<1>") } they should "be able to force implicit reset to be asynchronous" in { val fir = ChiselStage.emitChirrtl(new Module with RequireAsyncReset { - reset shouldBe an [AsyncReset] + reset shouldBe an[AsyncReset] }) - fir should include ("input reset : AsyncReset") + fir should include("input reset : AsyncReset") } "Chisel" should "error if sync and async modules are nested" in { - a [ChiselException] should be thrownBy extractCause[ChiselException] { + a[ChiselException] should be thrownBy extractCause[ChiselException] { ChiselStage.elaborate(new Module with RequireAsyncReset { val mod = Module(new Module with RequireSyncReset) }) diff --git a/src/test/scala/chiselTests/Risc.scala b/src/test/scala/chiselTests/Risc.scala index 74c55a12..e0eacb90 100644 --- a/src/test/scala/chiselTests/Risc.scala +++ b/src/test/scala/chiselTests/Risc.scala @@ -8,47 +8,47 @@ import chisel3.util._ class Risc extends Module { val io = IO(new Bundle { - val isWr = Input(Bool()) + val isWr = Input(Bool()) val wrAddr = Input(UInt(8.W)) val wrData = Input(Bits(32.W)) - val boot = Input(Bool()) - val valid = Output(Bool()) - val out = Output(Bits(32.W)) + val boot = Input(Bool()) + val valid = Output(Bool()) + val out = Output(Bits(32.W)) }) val memSize = 256 val file = Mem(memSize, Bits(32.W)) val code = Mem(memSize, Bits(32.W)) - val pc = RegInit(0.U(8.W)) + val pc = RegInit(0.U(8.W)) val add_op :: imm_op :: Nil = Enum(2) val inst = code(pc) - val op = inst(31,24) - val rci = inst(23,16) - val rai = inst(15, 8) - val rbi = inst( 7, 0) + val op = inst(31, 24) + val rci = inst(23, 16) + val rai = inst(15, 8) + val rbi = inst(7, 0) val ra = Mux(rai === 0.U, 0.U, file(rai)) val rb = Mux(rbi === 0.U, 0.U, file(rbi)) val rc = Wire(Bits(32.W)) io.valid := false.B - io.out := 0.U - rc := 0.U + io.out := 0.U + rc := 0.U - when (io.isWr) { + when(io.isWr) { code(io.wrAddr) := io.wrData - } .elsewhen (io.boot) { + }.elsewhen(io.boot) { pc := 0.U - } .otherwise { + }.otherwise { switch(op) { is(add_op) { rc := ra +% rb } is(imm_op) { rc := (rai << 8) | rbi } } io.out := rc - when (rci === 255.U) { + when(rci === 255.U) { io.valid := true.B - } .otherwise { + }.otherwise { file(rci) := rc } pc := pc +% 1.U @@ -111,7 +111,7 @@ class RiscTester(c: Risc) extends Tester(c) { expect(k <= 10, "TIME LIMIT") expect(c.io.out, 4) } -*/ + */ class RiscSpec extends ChiselPropSpec { @@ -119,5 +119,5 @@ class RiscSpec extends ChiselPropSpec { ChiselStage.elaborate { new Risc } } - ignore("RiscTester should return the correct result") { } + ignore("RiscTester should return the correct result") {} } diff --git a/src/test/scala/chiselTests/SIntOps.scala b/src/test/scala/chiselTests/SIntOps.scala index 222d0ba7..55b4c915 100644 --- a/src/test/scala/chiselTests/SIntOps.scala +++ b/src/test/scala/chiselTests/SIntOps.scala @@ -82,7 +82,7 @@ class SIntOpsTester(c: SIntOps) extends Tester(c) { expect(c.io.greateqout, int(test_a >= test_b)) } } -*/ + */ class SIntLitExtractTester extends BasicTester { assert(-5.S(1) === true.B) @@ -105,12 +105,12 @@ class SIntOpsSpec extends ChiselPropSpec with Utils { } property("Negative shift amounts are invalid") { - a [ChiselException] should be thrownBy extractCause[ChiselException] { + a[ChiselException] should be thrownBy extractCause[ChiselException] { ChiselStage.elaborate(new NegativeShift(SInt())) } } - ignore("SIntOpsTester should return the correct result") { } + ignore("SIntOpsTester should return the correct result") {} property("Bit extraction on literals should work for all non-negative indices") { assertTesterPasses(new SIntLitExtractTester) diff --git a/src/test/scala/chiselTests/ScalaIntervalSimulatorTest.scala b/src/test/scala/chiselTests/ScalaIntervalSimulatorTest.scala index 540cc456..94f5ccc7 100644 --- a/src/test/scala/chiselTests/ScalaIntervalSimulatorTest.scala +++ b/src/test/scala/chiselTests/ScalaIntervalSimulatorTest.scala @@ -11,87 +11,87 @@ class ScalaIntervalSimulatorSpec extends AnyFreeSpec with Matchers { "clip tests" - { "Should work for closed ranges" in { val sim = ScalaIntervalSimulator(range"[2,4]") - sim.clip(BigDecimal(1.0)) should be (2.0) - sim.clip(BigDecimal(2.0)) should be (2.0) - sim.clip(BigDecimal(3.0)) should be (3.0) - sim.clip(BigDecimal(4.0)) should be (4.0) - sim.clip(BigDecimal(5.0)) should be (4.0) + sim.clip(BigDecimal(1.0)) should be(2.0) + sim.clip(BigDecimal(2.0)) should be(2.0) + sim.clip(BigDecimal(3.0)) should be(3.0) + sim.clip(BigDecimal(4.0)) should be(4.0) + sim.clip(BigDecimal(5.0)) should be(4.0) } "Should work for closed ranges with binary point" in { val sim = ScalaIntervalSimulator(range"[2,6].2") - sim.clip(BigDecimal(1.75)) should be (2.0) - sim.clip(BigDecimal(2.0)) should be (2.0) - sim.clip(BigDecimal(2.25)) should be (2.25) - sim.clip(BigDecimal(2.5)) should be (2.5) - sim.clip(BigDecimal(5.75)) should be (5.75) - sim.clip(BigDecimal(6.0)) should be (6.0) - sim.clip(BigDecimal(6.25)) should be (6.0) - sim.clip(BigDecimal(6.5)) should be (6.0) - sim.clip(BigDecimal(8.5)) should be (6.0) + sim.clip(BigDecimal(1.75)) should be(2.0) + sim.clip(BigDecimal(2.0)) should be(2.0) + sim.clip(BigDecimal(2.25)) should be(2.25) + sim.clip(BigDecimal(2.5)) should be(2.5) + sim.clip(BigDecimal(5.75)) should be(5.75) + sim.clip(BigDecimal(6.0)) should be(6.0) + sim.clip(BigDecimal(6.25)) should be(6.0) + sim.clip(BigDecimal(6.5)) should be(6.0) + sim.clip(BigDecimal(8.5)) should be(6.0) } "Should work for open ranges" in { val sim = ScalaIntervalSimulator(range"(2,4)") - sim.clip(BigDecimal(1.0)) should be (3.0) - sim.clip(BigDecimal(2.0)) should be (3.0) - sim.clip(BigDecimal(3.0)) should be (3.0) - sim.clip(BigDecimal(4.0)) should be (3.0) - sim.clip(BigDecimal(5.0)) should be (3.0) + sim.clip(BigDecimal(1.0)) should be(3.0) + sim.clip(BigDecimal(2.0)) should be(3.0) + sim.clip(BigDecimal(3.0)) should be(3.0) + sim.clip(BigDecimal(4.0)) should be(3.0) + sim.clip(BigDecimal(5.0)) should be(3.0) } "Should work for open ranges with binary point" in { val sim = ScalaIntervalSimulator(range"(2,6).2") - sim.clip(BigDecimal(1.75)) should be (2.25) - sim.clip(BigDecimal(2.0)) should be (2.25) - sim.clip(BigDecimal(2.25)) should be (2.25) - sim.clip(BigDecimal(2.5)) should be (2.5) - sim.clip(BigDecimal(5.75)) should be (5.75) - sim.clip(BigDecimal(6.0)) should be (5.75) - sim.clip(BigDecimal(6.25)) should be (5.75) - sim.clip(BigDecimal(6.5)) should be (5.75) - sim.clip(BigDecimal(8.5)) should be (5.75) + sim.clip(BigDecimal(1.75)) should be(2.25) + sim.clip(BigDecimal(2.0)) should be(2.25) + sim.clip(BigDecimal(2.25)) should be(2.25) + sim.clip(BigDecimal(2.5)) should be(2.5) + sim.clip(BigDecimal(5.75)) should be(5.75) + sim.clip(BigDecimal(6.0)) should be(5.75) + sim.clip(BigDecimal(6.25)) should be(5.75) + sim.clip(BigDecimal(6.5)) should be(5.75) + sim.clip(BigDecimal(8.5)) should be(5.75) } } "wrap tests" - { "Should work for closed ranges" in { val sim = ScalaIntervalSimulator(range"[2,6]") - sim.wrap(BigDecimal(1.0)) should be (6.0) - sim.wrap(BigDecimal(2.0)) should be (2.0) - sim.wrap(BigDecimal(3.0)) should be (3.0) - sim.wrap(BigDecimal(4.0)) should be (4.0) - sim.wrap(BigDecimal(5.0)) should be (5.0) - sim.wrap(BigDecimal(6.0)) should be (6.0) - sim.wrap(BigDecimal(7.0)) should be (2.0) + sim.wrap(BigDecimal(1.0)) should be(6.0) + sim.wrap(BigDecimal(2.0)) should be(2.0) + sim.wrap(BigDecimal(3.0)) should be(3.0) + sim.wrap(BigDecimal(4.0)) should be(4.0) + sim.wrap(BigDecimal(5.0)) should be(5.0) + sim.wrap(BigDecimal(6.0)) should be(6.0) + sim.wrap(BigDecimal(7.0)) should be(2.0) } "Should work for closed ranges with binary point" in { val sim = ScalaIntervalSimulator(range"[2,6].2") - sim.wrap(BigDecimal(1.75)) should be (6.0) - sim.wrap(BigDecimal(2.0)) should be (2.0) - sim.wrap(BigDecimal(2.25)) should be (2.25) - sim.wrap(BigDecimal(2.5)) should be (2.5) - sim.wrap(BigDecimal(5.75)) should be (5.75) - sim.wrap(BigDecimal(6.0)) should be (6.0) - sim.wrap(BigDecimal(6.25)) should be (2.0) - sim.wrap(BigDecimal(6.5)) should be (2.25) + sim.wrap(BigDecimal(1.75)) should be(6.0) + sim.wrap(BigDecimal(2.0)) should be(2.0) + sim.wrap(BigDecimal(2.25)) should be(2.25) + sim.wrap(BigDecimal(2.5)) should be(2.5) + sim.wrap(BigDecimal(5.75)) should be(5.75) + sim.wrap(BigDecimal(6.0)) should be(6.0) + sim.wrap(BigDecimal(6.25)) should be(2.0) + sim.wrap(BigDecimal(6.5)) should be(2.25) } "Should work for open ranges" in { val sim = ScalaIntervalSimulator(range"(2,6)") - sim.wrap(BigDecimal(1.0)) should be (4.0) - sim.wrap(BigDecimal(2.0)) should be (5.0) - sim.wrap(BigDecimal(3.0)) should be (3.0) - sim.wrap(BigDecimal(4.0)) should be (4.0) - sim.wrap(BigDecimal(5.0)) should be (5.0) - sim.wrap(BigDecimal(6.0)) should be (3.0) - sim.wrap(BigDecimal(7.0)) should be (4.0) + sim.wrap(BigDecimal(1.0)) should be(4.0) + sim.wrap(BigDecimal(2.0)) should be(5.0) + sim.wrap(BigDecimal(3.0)) should be(3.0) + sim.wrap(BigDecimal(4.0)) should be(4.0) + sim.wrap(BigDecimal(5.0)) should be(5.0) + sim.wrap(BigDecimal(6.0)) should be(3.0) + sim.wrap(BigDecimal(7.0)) should be(4.0) } "Should work for open ranges with binary point" in { val sim = ScalaIntervalSimulator(range"(2,6).2") - sim.wrap(BigDecimal(1.75)) should be (5.5) - sim.wrap(BigDecimal(2.0)) should be (5.75) - sim.wrap(BigDecimal(2.25)) should be (2.25) - sim.wrap(BigDecimal(2.5)) should be (2.5) - sim.wrap(BigDecimal(5.75)) should be (5.75) - sim.wrap(BigDecimal(6.0)) should be (2.25) - sim.wrap(BigDecimal(6.25)) should be (2.5) - sim.wrap(BigDecimal(7.0)) should be (3.25) + sim.wrap(BigDecimal(1.75)) should be(5.5) + sim.wrap(BigDecimal(2.0)) should be(5.75) + sim.wrap(BigDecimal(2.25)) should be(2.25) + sim.wrap(BigDecimal(2.5)) should be(2.5) + sim.wrap(BigDecimal(5.75)) should be(5.75) + sim.wrap(BigDecimal(6.0)) should be(2.25) + sim.wrap(BigDecimal(6.25)) should be(2.5) + sim.wrap(BigDecimal(7.0)) should be(3.25) } } } diff --git a/src/test/scala/chiselTests/Stack.scala b/src/test/scala/chiselTests/Stack.scala index cb21e2c0..085f4e34 100644 --- a/src/test/scala/chiselTests/Stack.scala +++ b/src/test/scala/chiselTests/Stack.scala @@ -8,25 +8,25 @@ import chisel3.util._ class ChiselStack(val depth: Int) extends Module { val io = IO(new Bundle { - val push = Input(Bool()) - val pop = Input(Bool()) - val en = Input(Bool()) - val dataIn = Input(UInt(32.W)) + val push = Input(Bool()) + val pop = Input(Bool()) + val en = Input(Bool()) + val dataIn = Input(UInt(32.W)) val dataOut = Output(UInt(32.W)) }) val stack_mem = Mem(depth, UInt(32.W)) - val sp = RegInit(0.U(log2Ceil(depth + 1).W)) - val out = RegInit(0.U(32.W)) + val sp = RegInit(0.U(log2Ceil(depth + 1).W)) + val out = RegInit(0.U(32.W)) - when (io.en) { + when(io.en) { when(io.push && (sp < depth.asUInt)) { stack_mem(sp) := io.dataIn sp := sp +% 1.U - } .elsewhen(io.pop && (sp > 0.U)) { + }.elsewhen(io.pop && (sp > 0.U)) { sp := sp -% 1.U } - when (sp > 0.U) { + when(sp > 0.U) { out := stack_mem(sp -% 1.U) } } @@ -65,7 +65,7 @@ class StackTester(c: Stack) extends Tester(c) { expect(c.io.dataOut, dataOut) } } -*/ + */ class StackSpec extends ChiselPropSpec { @@ -73,5 +73,5 @@ class StackSpec extends ChiselPropSpec { ChiselStage.elaborate { new ChiselStack(2) } } - ignore("StackTester should return the correct result") { } + ignore("StackTester should return the correct result") {} } diff --git a/src/test/scala/chiselTests/Stop.scala b/src/test/scala/chiselTests/Stop.scala index 1634f776..25aae2d9 100644 --- a/src/test/scala/chiselTests/Stop.scala +++ b/src/test/scala/chiselTests/Stop.scala @@ -12,7 +12,7 @@ class StopTester() extends BasicTester { class StopImmediatelyTester extends BasicTester { val cycle = RegInit(0.asUInt(4.W)) cycle := cycle + 1.U - when (cycle === 4.U) { + when(cycle === 4.U) { stop() } assert(cycle =/= 5.U, "Simulation did not exit upon executing stop()") diff --git a/src/test/scala/chiselTests/StrongEnum.scala b/src/test/scala/chiselTests/StrongEnum.scala index 404c3f66..c43d832a 100644 --- a/src/test/scala/chiselTests/StrongEnum.scala +++ b/src/test/scala/chiselTests/StrongEnum.scala @@ -142,21 +142,21 @@ class StrongEnumFSM extends Module { io.out := (state === sTwo1s) io.state := state - switch (state) { - is (sNone) { - when (io.in) { + switch(state) { + is(sNone) { + when(io.in) { state := sOne1 } } - is (sOne1) { - when (io.in) { + is(sOne1) { + when(io.in) { state := sTwo1s - } .otherwise { + }.otherwise { state := sNone } } - is (sTwo1s) { - when (!io.in) { + is(sTwo1s) { + when(!io.in) { state := sNone } } @@ -164,7 +164,7 @@ class StrongEnumFSM extends Module { } class CastToUIntTester extends BasicTester { - for ((enum,lit) <- EnumExample.all zip EnumExample.litValues) { + for ((enum, lit) <- EnumExample.all.zip(EnumExample.litValues)) { val mod = Module(new CastToUInt) mod.io.in := enum assert(mod.io.out === lit) @@ -173,7 +173,7 @@ class CastToUIntTester extends BasicTester { } class CastFromLitTester extends BasicTester { - for ((enum,lit) <- EnumExample.all zip EnumExample.litValues) { + for ((enum, lit) <- EnumExample.all.zip(EnumExample.litValues)) { val mod = Module(new CastFromLit(lit)) assert(mod.io.out === enum) assert(mod.io.valid === true.B) @@ -182,16 +182,15 @@ class CastFromLitTester extends BasicTester { } class CastFromNonLitTester extends BasicTester { - for ((enum,lit) <- EnumExample.all zip EnumExample.litValues) { + for ((enum, lit) <- EnumExample.all.zip(EnumExample.litValues)) { val mod = Module(new CastFromNonLit) mod.io.in := lit assert(mod.io.out === enum) assert(mod.io.valid === true.B) } - val invalid_values = (1 until (1 << EnumExample.getWidth)). - filter(!EnumExample.litValues.map(_.litValue).contains(_)). - map(_.U) + val invalid_values = + (1 until (1 << EnumExample.getWidth)).filter(!EnumExample.litValues.map(_.litValue).contains(_)).map(_.U) for (invalid_val <- invalid_values) { val mod = Module(new CastFromNonLit) @@ -204,16 +203,15 @@ class CastFromNonLitTester extends BasicTester { } class SafeCastFromNonLitTester extends BasicTester { - for ((enum,lit) <- EnumExample.all zip EnumExample.litValues) { + for ((enum, lit) <- EnumExample.all.zip(EnumExample.litValues)) { val mod = Module(new SafeCastFromNonLit) mod.io.in := lit assert(mod.io.out === enum) assert(mod.io.valid === true.B) } - val invalid_values = (1 until (1 << EnumExample.getWidth)). - filter(!EnumExample.litValues.map(_.litValue).contains(_)). - map(_.U) + val invalid_values = + (1 until (1 << EnumExample.getWidth)).filter(!EnumExample.litValues.map(_.litValue).contains(_)).map(_.U) for (invalid_val <- invalid_values) { val mod = Module(new SafeCastFromNonLit) @@ -231,8 +229,10 @@ class CastToInvalidEnumTester extends BasicTester { } class EnumOpsTester extends BasicTester { - for (x <- EnumExample.all; - y <- EnumExample.all) { + for { + x <- EnumExample.all + y <- EnumExample.all + } { val mod = Module(new EnumOps(EnumExample, EnumExample)) mod.io.x := x mod.io.y := y @@ -264,7 +264,7 @@ class IsLitTester extends BasicTester { } class NextTester extends BasicTester { - for ((e,n) <- EnumExample.all.zip(EnumExample.litValues.tail :+ EnumExample.litValues.head)) { + for ((e, n) <- EnumExample.all.zip(EnumExample.litValues.tail :+ EnumExample.litValues.head)) { assert(e.next.litValue == n.litValue) val w = WireDefault(e) assert(w.next === EnumExample(n)) @@ -275,7 +275,7 @@ class NextTester extends BasicTester { class WidthTester extends BasicTester { assert(EnumExample.getWidth == EnumExample.litValues.last.getWidth) assert(EnumExample.all.forall(_.getWidth == EnumExample.litValues.last.getWidth)) - assert(EnumExample.all.forall{e => + assert(EnumExample.all.forall { e => val w = WireDefault(e) w.getWidth == EnumExample.litValues.last.getWidth }) @@ -289,7 +289,8 @@ class StrongEnumFSMTester extends BasicTester { // Inputs and expected results val inputs: Vec[Bool] = VecInit(false.B, true.B, false.B, true.B, true.B, true.B, false.B, true.B, true.B, false.B) - val expected: Vec[Bool] = VecInit(false.B, false.B, false.B, false.B, false.B, true.B, true.B, false.B, false.B, true.B) + val expected: Vec[Bool] = + VecInit(false.B, false.B, false.B, false.B, false.B, true.B, true.B, false.B, false.B, true.B) val expected_state = VecInit(sNone, sNone, sOne1, sNone, sOne1, sTwo1s, sTwo1s, sNone, sOne1, sTwo1s) val cntr = Counter(inputs.length) @@ -342,16 +343,16 @@ class IsOneOfTester extends BasicTester { class StrongEnumSpec extends ChiselFlatSpec with Utils { import chisel3.internal.ChiselException - behavior of "Strong enum tester" + behavior.of("Strong enum tester") it should "fail to instantiate non-literal enums with the Value function" in { - an [ExceptionInInitializerError] should be thrownBy extractCause[ExceptionInInitializerError] { + an[ExceptionInInitializerError] should be thrownBy extractCause[ExceptionInInitializerError] { ChiselStage.elaborate(new SimpleConnector(NonLiteralEnumType(), NonLiteralEnumType())) } } it should "fail to instantiate non-increasing enums with the Value function" in { - an [ExceptionInInitializerError] should be thrownBy extractCause[ExceptionInInitializerError] { + an[ExceptionInInitializerError] should be thrownBy extractCause[ExceptionInInitializerError] { ChiselStage.elaborate(new SimpleConnector(NonIncreasingEnum(), NonIncreasingEnum())) } } @@ -362,17 +363,17 @@ class StrongEnumSpec extends ChiselFlatSpec with Utils { } it should "fail to connect a strong enum to a UInt" in { - a [ChiselException] should be thrownBy extractCause[ChiselException] { + a[ChiselException] should be thrownBy extractCause[ChiselException] { ChiselStage.elaborate(new SimpleConnector(EnumExample(), UInt())) } } it should "fail to connect enums of different types" in { - a [ChiselException] should be thrownBy extractCause[ChiselException] { + a[ChiselException] should be thrownBy extractCause[ChiselException] { ChiselStage.elaborate(new SimpleConnector(EnumExample(), OtherEnum())) } - a [ChiselException] should be thrownBy extractCause[ChiselException] { + a[ChiselException] should be thrownBy extractCause[ChiselException] { ChiselStage.elaborate(new SimpleConnector(EnumExample.Type(), OtherEnum.Type())) } } @@ -394,7 +395,7 @@ class StrongEnumSpec extends ChiselFlatSpec with Utils { } it should "prevent illegal literal casts to enums" in { - a [ChiselException] should be thrownBy extractCause[ChiselException] { + a[ChiselException] should be thrownBy extractCause[ChiselException] { ChiselStage.elaborate(new CastToInvalidEnumTester) } } @@ -403,12 +404,12 @@ class StrongEnumSpec extends ChiselFlatSpec with Utils { for (w <- 0 to EnumExample.getWidth) ChiselStage.elaborate(new CastFromNonLitWidth(Some(w))) - a [ChiselException] should be thrownBy extractCause[ChiselException] { + a[ChiselException] should be thrownBy extractCause[ChiselException] { ChiselStage.elaborate(new CastFromNonLitWidth) } for (w <- (EnumExample.getWidth + 1) to (EnumExample.getWidth + 100)) { - a [ChiselException] should be thrownBy extractCause[ChiselException] { + a[ChiselException] should be thrownBy extractCause[ChiselException] { ChiselStage.elaborate(new CastFromNonLitWidth(Some(w))) } } @@ -419,7 +420,7 @@ class StrongEnumSpec extends ChiselFlatSpec with Utils { } it should "fail to compare enums of different types" in { - a [ChiselException] should be thrownBy extractCause[ChiselException] { + a[ChiselException] should be thrownBy extractCause[ChiselException] { ChiselStage.elaborate(new InvalidEnumOpsTester) } } @@ -462,8 +463,8 @@ class StrongEnumSpec extends ChiselFlatSpec with Utils { out := MyEnum(in) } val (log, _) = grabLog(ChiselStage.elaborate(new MyModule)) - log should include ("warn") - log should include ("Casting non-literal UInt") + log should include("warn") + log should include("Casting non-literal UInt") } it should "NOT warn if the Enum is total" in { @@ -477,7 +478,7 @@ class StrongEnumSpec extends ChiselFlatSpec with Utils { out := TotalEnum(in) } val (log, _) = grabLog(ChiselStage.elaborate(new MyModule)) - log should not include ("warn") + (log should not).include("warn") } "Casting a UInt to an Enum with .safe" should "NOT warn" in { @@ -491,7 +492,7 @@ class StrongEnumSpec extends ChiselFlatSpec with Utils { out := MyEnum.safe(in)._1 } val (log, _) = grabLog(ChiselStage.elaborate(new MyModule)) - log should not include ("warn") + (log should not).include("warn") } it should "NOT generate any validity logic if the Enum is total" in { @@ -507,7 +508,7 @@ class StrongEnumSpec extends ChiselFlatSpec with Utils { out := res } val (log, _) = grabLog(ChiselStage.elaborate(new MyModule)) - log should not include ("warn") + (log should not).include("warn") } it should "correctly check if the enumeration is one of the values in a given sequence" in { @@ -524,7 +525,7 @@ class StrongEnumAnnotator extends Module { val le100 = Value(100.U) } - val io = IO(new Bundle{ + val io = IO(new Bundle { val in = Input(EnumExample()) val out = Output(EnumExample()) val other = Output(OtherEnum()) @@ -584,7 +585,7 @@ class StrongEnumAnnotatorWithChiselName extends Module { val le100 = Value(100.U) } - val io = IO(new Bundle{ + val io = IO(new Bundle { val in = Input(EnumExample()) val out = Output(EnumExample()) val other = Output(OtherEnum()) @@ -636,7 +637,7 @@ class StrongEnumAnnotatorWithChiselName extends Module { class StrongEnumAnnotationSpec extends AnyFreeSpec with Matchers { import chisel3.experimental.EnumAnnotations._ - import firrtl.annotations.{ComponentName, Annotation} + import firrtl.annotations.{Annotation, ComponentName} val enumExampleName = "EnumExample" val otherEnumName = "OtherEnum" @@ -667,7 +668,11 @@ class StrongEnumAnnotationSpec extends AnyFreeSpec with Matchers { val correctVecAnnos = Seq( CorrectVecAnno("vec", enumExampleName, Set()), CorrectVecAnno("vec_of_vecs", enumExampleName, Set()), - CorrectVecAnno("vec_of_bundles", enumExampleName, Set(Seq("field"), Seq("vec"), Seq("inner_bundle1", "e"), Seq("inner_bundle1", "v"))), + CorrectVecAnno( + "vec_of_bundles", + enumExampleName, + Set(Seq("field"), Seq("vec"), Seq("inner_bundle1", "e"), Seq("inner_bundle1", "v")) + ), CorrectVecAnno("vec_of_bundles", otherEnumName, Set(Seq("other"))), CorrectVecAnno("vec_of_bundles", localEnumName, Set(Seq("local"))), CorrectVecAnno("bund.vec", enumExampleName, Set()), @@ -678,49 +683,49 @@ class StrongEnumAnnotationSpec extends AnyFreeSpec with Matchers { println("Enum definitions:") annos.foreach { case EnumDefAnnotation(enumTypeName, definition) => println(s"\t$enumTypeName: $definition") - case _ => + case _ => } println("Enum components:") - annos.foreach{ + annos.foreach { case EnumComponentAnnotation(target, enumTypeName) => println(s"\t$target => $enumTypeName") - case _ => + case _ => } println("Enum vecs:") - annos.foreach{ + annos.foreach { case EnumVecAnnotation(target, enumTypeName, fields) => println(s"\t$target[$fields] => $enumTypeName") - case _ => + case _ => } } def isCorrect(anno: EnumDefAnnotation, correct: CorrectDefAnno): Boolean = { (anno.typeName == correct.typeName || - anno.typeName.endsWith("." + correct.typeName) || - anno.typeName.endsWith("$" + correct.typeName)) && - anno.definition == correct.definition + anno.typeName.endsWith("." + correct.typeName) || + anno.typeName.endsWith("$" + correct.typeName)) && + anno.definition == correct.definition } def isCorrect(anno: EnumComponentAnnotation, correct: CorrectCompAnno): Boolean = { (anno.target match { case ComponentName(name, _) => name == correct.targetName - case _ => throw new Exception("Unknown target type in EnumComponentAnnotation") + case _ => throw new Exception("Unknown target type in EnumComponentAnnotation") }) && - (anno.enumTypeName == correct.typeName || anno.enumTypeName.endsWith("." + correct.typeName) || - anno.enumTypeName.endsWith("$" + correct.typeName)) + (anno.enumTypeName == correct.typeName || anno.enumTypeName.endsWith("." + correct.typeName) || + anno.enumTypeName.endsWith("$" + correct.typeName)) } def isCorrect(anno: EnumVecAnnotation, correct: CorrectVecAnno): Boolean = { (anno.target match { case ComponentName(name, _) => name == correct.targetName - case _ => throw new Exception("Unknown target type in EnumVecAnnotation") + case _ => throw new Exception("Unknown target type in EnumVecAnnotation") }) && - (anno.typeName == correct.typeName || anno.typeName.endsWith("." + correct.typeName) || - anno.typeName.endsWith("$" + correct.typeName)) && - anno.fields.map(_.toSeq).toSet == correct.fields + (anno.typeName == correct.typeName || anno.typeName.endsWith("." + correct.typeName) || + anno.typeName.endsWith("$" + correct.typeName)) && + anno.fields.map(_.toSeq).toSet == correct.fields } def allCorrectDefs(annos: Seq[EnumDefAnnotation], corrects: Seq[CorrectDefAnno]): Boolean = { corrects.forall(c => annos.exists(isCorrect(_, c))) && - correctDefAnnos.length == annos.length + correctDefAnnos.length == annos.length } // Because temporary variables might be formed and annotated, we do not check that every component or vector @@ -732,8 +737,10 @@ class StrongEnumAnnotationSpec extends AnyFreeSpec with Matchers { corrects.forall(c => annos.exists(isCorrect(_, c))) def test(strongEnumAnnotatorGen: () => Module) { - val annos = (new ChiselStage).execute(Array("--target-dir", "test_run_dir", "--no-run-firrtl"), - Seq(ChiselGeneratorAnnotation(strongEnumAnnotatorGen))) + val annos = (new ChiselStage).execute( + Array("--target-dir", "test_run_dir", "--no-run-firrtl"), + Seq(ChiselGeneratorAnnotation(strongEnumAnnotatorGen)) + ) val enumDefAnnos = annos.collect { case a: EnumDefAnnotation => a } val enumCompAnnos = annos.collect { case a: EnumComponentAnnotation => a } diff --git a/src/test/scala/chiselTests/SwitchSpec.scala b/src/test/scala/chiselTests/SwitchSpec.scala index 12bbb9e7..52f50a53 100644 --- a/src/test/scala/chiselTests/SwitchSpec.scala +++ b/src/test/scala/chiselTests/SwitchSpec.scala @@ -4,30 +4,30 @@ package chiselTests import chisel3._ import chisel3.stage.ChiselStage -import chisel3.util.{switch, is} +import chisel3.util.{is, switch} class SwitchSpec extends ChiselFlatSpec with Utils { "switch" should "require literal conditions" in { - a [java.lang.IllegalArgumentException] should be thrownBy extractCause[IllegalArgumentException] { + a[java.lang.IllegalArgumentException] should be thrownBy extractCause[IllegalArgumentException] { ChiselStage.elaborate(new Module { val io = IO(new Bundle {}) val state = RegInit(0.U) val wire = WireDefault(0.U) - switch (state) { - is (wire) { state := 1.U } + switch(state) { + is(wire) { state := 1.U } } }) } } it should "require mutually exclusive conditions" in { - a [java.lang.IllegalArgumentException] should be thrownBy extractCause[IllegalArgumentException] { + a[java.lang.IllegalArgumentException] should be thrownBy extractCause[IllegalArgumentException] { ChiselStage.elaborate(new Module { val io = IO(new Bundle {}) val state = RegInit(0.U) - switch (state) { - is (0.U) { state := 1.U } - is (1.U) { state := 2.U } - is (0.U) { state := 3.U } + switch(state) { + is(0.U) { state := 1.U } + is(1.U) { state := 2.U } + is(0.U) { state := 3.U } } }) } @@ -40,14 +40,14 @@ class SwitchSpec extends ChiselFlatSpec with Utils { }) io.out := 0.U - switch (io.in) { - is (0.U) { io.out := 3.U } - is (1.U) { io.out := 0.U } - is (2.U) { io.out := 1.U } - is (3.U) { io.out := 3.U } + switch(io.in) { + is(0.U) { io.out := 3.U } + is(1.U) { io.out := 0.U } + is(2.U) { io.out := 1.U } + is(3.U) { io.out := 3.U } } }) - chirrtl should not include "Conditional.scala" + (chirrtl should not).include("Conditional.scala") } } diff --git a/src/test/scala/chiselTests/Tbl.scala b/src/test/scala/chiselTests/Tbl.scala index c7b45a16..5e127770 100644 --- a/src/test/scala/chiselTests/Tbl.scala +++ b/src/test/scala/chiselTests/Tbl.scala @@ -8,15 +8,15 @@ import chisel3.util._ class Tbl(w: Int, n: Int) extends Module { val io = IO(new Bundle { - val wi = Input(UInt(log2Ceil(n).W)) - val ri = Input(UInt(log2Ceil(n).W)) - val we = Input(Bool()) - val d = Input(UInt(w.W)) - val o = Output(UInt(w.W)) + val wi = Input(UInt(log2Ceil(n).W)) + val ri = Input(UInt(log2Ceil(n).W)) + val we = Input(Bool()) + val d = Input(UInt(w.W)) + val o = Output(UInt(w.W)) }) val m = Mem(n, UInt(w.W)) io.o := m(io.ri) - when (io.we) { + when(io.we) { m(io.wi) := io.d when(io.ri === io.wi) { io.o := io.d @@ -35,10 +35,10 @@ class TblTester(w: Int, n: Int, idxs: List[Int], values: List[Int]) extends Basi dut.io.ri := prev_idx dut.io.we := true.B //TODO enSequence dut.io.d := vvalues(cnt) - when (cnt > 0.U) { - when (prev_idx === vidxs(cnt)) { + when(cnt > 0.U) { + when(prev_idx === vidxs(cnt)) { assert(dut.io.o === vvalues(cnt)) - } .otherwise { + }.otherwise { assert(dut.io.o === prev_value) } } @@ -49,13 +49,14 @@ class TblTester(w: Int, n: Int, idxs: List[Int], values: List[Int]) extends Basi class TblSpec extends ChiselPropSpec { property("All table reads should return the previous write") { - forAll(safeUIntPairN(8)) { case(w: Int, pairs: List[(Int, Int)]) => - // Provide an appropriate whenever clause. - // ScalaTest will try and shrink the values on error to determine the smallest values that cause the error. - whenever(w > 0 && pairs.length > 0) { - val (idxs, values) = pairs.unzip - assertTesterPasses{ new TblTester(w, 1 << w, idxs, values) } - } + forAll(safeUIntPairN(8)) { + case (w: Int, pairs: List[(Int, Int)]) => + // Provide an appropriate whenever clause. + // ScalaTest will try and shrink the values on error to determine the smallest values that cause the error. + whenever(w > 0 && pairs.length > 0) { + val (idxs, values) = pairs.unzip + assertTesterPasses { new TblTester(w, 1 << w, idxs, values) } + } } } } diff --git a/src/test/scala/chiselTests/TesterDriverSpec.scala b/src/test/scala/chiselTests/TesterDriverSpec.scala index 5c0e277e..c3cc232f 100644 --- a/src/test/scala/chiselTests/TesterDriverSpec.scala +++ b/src/test/scala/chiselTests/TesterDriverSpec.scala @@ -42,4 +42,3 @@ class TesterDriverSpec extends ChiselFlatSpec { } } } - diff --git a/src/test/scala/chiselTests/TransitNameSpec.scala b/src/test/scala/chiselTests/TransitNameSpec.scala index 656c6731..ae08336d 100644 --- a/src/test/scala/chiselTests/TransitNameSpec.scala +++ b/src/test/scala/chiselTests/TransitNameSpec.scala @@ -1,7 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 package chiselTests - import chisel3._ import chisel3.stage.{ChiselGeneratorAnnotation, ChiselStage} import chisel3.util.TransitName @@ -12,7 +11,7 @@ import org.scalatest.matchers.should.Matchers class TransitNameSpec extends AnyFlatSpec with Matchers { class MyModule extends RawModule { - val io = IO(new Bundle{}) + val io = IO(new Bundle {}) override val desiredName: String = "MyModule" } @@ -42,13 +41,13 @@ class TransitNameSpec extends AnyFlatSpec with Matchers { .emitFirrtl(new Top, Array("--target-dir", "test_run_dir/TransitNameSpec")) info("""output FIRRTL includes "inst MyModule"""") - firrtl should include ("inst MyModule of MyModule") + firrtl should include("inst MyModule of MyModule") info("""output FIRRTL includes "inst bar"""") - firrtl should include ("inst bar of MyModule") + firrtl should include("inst bar of MyModule") info("""output FIRRTL includes "inst baz_generated"""") - firrtl should include ("inst baz_generated of MyModule") + firrtl should include("inst baz_generated of MyModule") } } diff --git a/src/test/scala/chiselTests/UIntOps.scala b/src/test/scala/chiselTests/UIntOps.scala index bc6454b8..5fb86001 100644 --- a/src/test/scala/chiselTests/UIntOps.scala +++ b/src/test/scala/chiselTests/UIntOps.scala @@ -70,8 +70,8 @@ class UIntOpsTester(a: Long, b: Long) extends BasicTester { assert(dut.io.addampout === (a + b).U(33.W)) assert(dut.io.subampout === (a - b).S(33.W).asUInt) assert(dut.io.timesout === (a * b).U(32.W)) - assert(dut.io.divout === (a / (b max 1)).U(32.W)) - assert(dut.io.modout === (a % (b max 1)).U(32.W)) + assert(dut.io.divout === (a / (b.max(1))).U(32.W)) + assert(dut.io.modout === (a % (b.max(1))).U(32.W)) assert(dut.io.lshiftout === (a << (b % 16)).U(32.W)) assert(dut.io.rshiftout === (a >> b).U(32.W)) assert( @@ -117,7 +117,6 @@ class BasicRotate extends BasicTester { val shiftAmount = random.LFSR(4) val ctr = RegInit(0.U(4.W)) - val rotL = 1.U(3.W).rotateLeft(shiftAmount) val rotR = 1.U(3.W).rotateRight(shiftAmount) @@ -140,7 +139,7 @@ class BasicRotate extends BasicTester { ctr := ctr + 1.U - when (ctr === 15.U){ + when(ctr === 15.U) { stop() } } @@ -197,7 +196,7 @@ class UIntOpsSpec extends ChiselPropSpec with Matchers with Utils { } property("Bools cannot be created from >1 bit UInts") { - a [Exception] should be thrownBy extractCause[Exception] { ChiselStage.elaborate(new BadBoolConversion) } + a[Exception] should be thrownBy extractCause[Exception] { ChiselStage.elaborate(new BadBoolConversion) } } property("UIntOps should elaborate") { @@ -209,7 +208,7 @@ class UIntOpsSpec extends ChiselPropSpec with Matchers with Utils { } property("Negative shift amounts are invalid") { - a [ChiselException] should be thrownBy extractCause[ChiselException] { + a[ChiselException] should be thrownBy extractCause[ChiselException] { ChiselStage.elaborate(new NegativeShift(UInt())) } } diff --git a/src/test/scala/chiselTests/Util.scala b/src/test/scala/chiselTests/Util.scala index e8354b8d..d2f8bd9b 100644 --- a/src/test/scala/chiselTests/Util.scala +++ b/src/test/scala/chiselTests/Util.scala @@ -25,14 +25,14 @@ class PassthroughRawModule extends RawModule with AbstractPassthroughModule case class ScalaIntervalSimulator(intervalRange: IntervalRange) { val binaryPoint: Int = intervalRange.binaryPoint.asInstanceOf[KnownBinaryPoint].value - val epsilon: Double = 1.0 / math.pow(2.0, binaryPoint.toDouble) + val epsilon: Double = 1.0 / math.pow(2.0, binaryPoint.toDouble) val (lower, upper) = (intervalRange.lowerBound, intervalRange.upperBound) match { case (firrtlir.Closed(lower1), firrtlir.Closed(upper1)) => (lower1, upper1) case (firrtlir.Closed(lower1), firrtlir.Open(upper1)) => (lower1, upper1 - epsilon) - case (firrtlir.Open(lower1), firrtlir.Closed(upper1)) => (lower1 + epsilon, upper1) - case (firrtlir.Open(lower1), firrtlir.Open(upper1)) => (lower1 + epsilon, upper1 - epsilon) + case (firrtlir.Open(lower1), firrtlir.Closed(upper1)) => (lower1 + epsilon, upper1) + case (firrtlir.Open(lower1), firrtlir.Open(upper1)) => (lower1 + epsilon, upper1 - epsilon) case _ => throw new Exception(s"lower and upper bounds must be defined, range here is $intervalRange") } @@ -41,11 +41,9 @@ case class ScalaIntervalSimulator(intervalRange: IntervalRange) { if (value < lower) { lower - } - else if (value > upper) { + } else if (value > upper) { upper - } - else { + } else { value } } @@ -54,11 +52,9 @@ case class ScalaIntervalSimulator(intervalRange: IntervalRange) { if (value < lower) { upper + (value - lower) + epsilon - } - else if (value > upper) { + } else if (value > upper) { ((value - upper) - epsilon) + lower - } - else { + } else { value } } @@ -71,5 +67,3 @@ case class ScalaIntervalSimulator(intervalRange: IntervalRange) { Interval.fromDouble(value.toDouble, width = Width(), binaryPoint = binaryPoint.BP) } } - - diff --git a/src/test/scala/chiselTests/Vec.scala b/src/test/scala/chiselTests/Vec.scala index 24ba0bf8..2eb6ae5f 100644 --- a/src/test/scala/chiselTests/Vec.scala +++ b/src/test/scala/chiselTests/Vec.scala @@ -15,7 +15,7 @@ class LitTesterMod(vecSize: Int) extends Module { val io = IO(new Bundle { val out = Output(Vec(vecSize, UInt())) }) - io.out := VecInit(Seq.fill(vecSize){0.U}) + io.out := VecInit(Seq.fill(vecSize) { 0.U }) } class RegTesterMod(vecSize: Int) extends Module { @@ -23,7 +23,7 @@ class RegTesterMod(vecSize: Int) extends Module { val in = Input(Vec(vecSize, UInt())) val out = Output(Vec(vecSize, UInt())) }) - val vecReg = RegNext(io.in, VecInit(Seq.fill(vecSize){0.U})) + val vecReg = RegNext(io.in, VecInit(Seq.fill(vecSize) { 0.U })) io.out := vecReg } @@ -56,11 +56,11 @@ class RegTester(w: Int, values: List[Int]) extends BasicTester { val dut = Module(new RegTesterMod(values.length)) val doneReg = RegInit(false.B) dut.io.in := v - when (doneReg) { - for ((a,b) <- dut.io.out.zip(values)) + when(doneReg) { + for ((a, b) <- dut.io.out.zip(values)) assert(a === b.U) stop() - } .otherwise { + }.otherwise { doneReg := true.B for (a <- dut.io.out) assert(a === 0.U) @@ -71,7 +71,7 @@ class IOTester(w: Int, values: List[Int]) extends BasicTester { val v = VecInit(values.map(_.U(w.W))) // Does this need a Wire? No. It's a Vec of Lits and hence synthesizeable. val dut = Module(new IOTesterMod(values.length)) dut.io.in := v - for ((a,b) <- dut.io.out.zip(values)) { + for ((a, b) <- dut.io.out.zip(values)) { assert(a === b.U) } stop() @@ -81,24 +81,24 @@ class IOTesterModFill(vecSize: Int) extends Module { // This should generate a BindingException when we attempt to wire up the Vec.fill elements // since they're pure types and hence unsynthesizeable. val io = IO(new Bundle { - val in = Input(VecInit(Seq.fill(vecSize) {UInt()})) - val out = Output(VecInit(Seq.fill(vecSize) {UInt()})) + val in = Input(VecInit(Seq.fill(vecSize) { UInt() })) + val out = Output(VecInit(Seq.fill(vecSize) { UInt() })) }) io.out := io.in } class ValueTester(w: Int, values: List[Int]) extends BasicTester { val v = VecInit(values.map(_.asUInt(w.W))) - for ((a,b) <- v.zip(values)) { + for ((a, b) <- v.zip(values)) { assert(a === b.asUInt) } stop() } class TabulateTester(n: Int) extends BasicTester { - val v = VecInit(Range(0, n).map(i => (i*2).asUInt)) - val x = VecInit(Array.tabulate(n){ i => (i*2).asUInt }) - val u = VecInit.tabulate(n)(i => (i*2).asUInt) + val v = VecInit(Range(0, n).map(i => (i * 2).asUInt)) + val x = VecInit(Array.tabulate(n) { i => (i * 2).asUInt }) + val u = VecInit.tabulate(n)(i => (i * 2).asUInt) assert(v.asUInt() === x.asUInt()) assert(v.asUInt() === u.asUInt()) @@ -115,54 +115,54 @@ class FillTester(n: Int, value: Int) extends BasicTester { stop() } -object VecMultiDimTester { - +object VecMultiDimTester { + @tailrec private def assert2DIsCorrect(n: Int, arr: Vec[Vec[UInt]], compArr: Seq[Seq[Int]]): Unit = { - val compareRow = arr(n) zip compArr(n) - compareRow.foreach (x => assert(x._1 === x._2.U)) - if (n != 0) assert2DIsCorrect(n-1, arr, compArr) + val compareRow = arr(n).zip(compArr(n)) + compareRow.foreach(x => assert(x._1 === x._2.U)) + if (n != 0) assert2DIsCorrect(n - 1, arr, compArr) } @tailrec private def assert3DIsCorrect(n: Int, m: Int, arr: Vec[Vec[Vec[UInt]]], compArr: Seq[Seq[Seq[Int]]]): Unit = { - assert2DIsCorrect(m-1, arr(n), compArr(n)) - if (n != 0) assert3DIsCorrect(n-1, m, arr, compArr) + assert2DIsCorrect(m - 1, arr(n), compArr(n)) + if (n != 0) assert3DIsCorrect(n - 1, m, arr, compArr) } class TabulateTester2D(n: Int, m: Int) extends BasicTester { - def gen(x: Int, y: Int): UInt = (x+y).asUInt - def genCompVec(x: Int, y:Int): Int = x+y - val vec = VecInit.tabulate(n, m){ gen } - val compArr = Seq.tabulate(n,m){ genCompVec } - - assert2DIsCorrect(n-1, vec, compArr) + def gen(x: Int, y: Int): UInt = (x + y).asUInt + def genCompVec(x: Int, y: Int): Int = x + y + val vec = VecInit.tabulate(n, m) { gen } + val compArr = Seq.tabulate(n, m) { genCompVec } + + assert2DIsCorrect(n - 1, vec, compArr) stop() } class TabulateTester3D(n: Int, m: Int, p: Int) extends BasicTester { - def gen(x: Int, y: Int, z: Int): UInt = (x+y+z).asUInt - def genCompVec(x: Int, y:Int, z: Int): Int = x+y+z - val vec = VecInit.tabulate(n, m, p){ gen } - val compArr = Seq.tabulate(n, m, p){ genCompVec } + def gen(x: Int, y: Int, z: Int): UInt = (x + y + z).asUInt + def genCompVec(x: Int, y: Int, z: Int): Int = x + y + z + val vec = VecInit.tabulate(n, m, p) { gen } + val compArr = Seq.tabulate(n, m, p) { genCompVec } - assert3DIsCorrect(n-1, m, vec, compArr) + assert3DIsCorrect(n - 1, m, vec, compArr) stop() } class Fill2DTester(n: Int, m: Int, value: Int) extends BasicTester { - val u = VecInit.fill(n,m)(value.U) - val compareArr = Seq.fill(n,m)(value) - - assert2DIsCorrect(n-1, u, compareArr) + val u = VecInit.fill(n, m)(value.U) + val compareArr = Seq.fill(n, m)(value) + + assert2DIsCorrect(n - 1, u, compareArr) stop() } class Fill3DTester(n: Int, m: Int, p: Int, value: Int) extends BasicTester { - val u = VecInit.fill(n,m,p)(value.U) - val compareArr = Seq.fill(n,m,p)(value) + val u = VecInit.fill(n, m, p)(value.U) + val compareArr = Seq.fill(n, m, p)(value) - assert3DIsCorrect(n-1, m, u, compareArr) + assert3DIsCorrect(n - 1, m, u, compareArr) stop() } @@ -181,7 +181,7 @@ object VecMultiDimTester { class BidirectionalTester3DFill(n: Int, m: Int, p: Int) extends BasicTester { val mod = Module(new PassthroughModule) val vec3D = VecInit.fill(n, m, p)(mod.io) - + for { vec2D <- vec3D vec1D <- vec2D @@ -191,7 +191,7 @@ object VecMultiDimTester { } stop() } - + class TabulateModuleTester(value: Int) extends Module { val io = IO(Flipped(new PassthroughModuleIO)) // This drives the input of a PassthroughModule @@ -199,11 +199,11 @@ object VecMultiDimTester { } class BidirectionalTester2DTabulate(n: Int, m: Int) extends BasicTester { - val vec2D = VecInit.tabulate(n, m) { (x, y) => Module(new TabulateModuleTester(x + y + 1)).io} + val vec2D = VecInit.tabulate(n, m) { (x, y) => Module(new TabulateModuleTester(x + y + 1)).io } for { x <- 0 until n - y <- 0 until m + y <- 0 until m } yield { val value = x + y + 1 val receiveMod = Module(new PassthroughModule).io @@ -233,20 +233,23 @@ object VecMultiDimTester { class IterateTester(start: Int, len: Int)(f: UInt => UInt) extends BasicTester { val controlVec = VecInit(Seq.iterate(start.U, len)(f)) val testVec = VecInit.iterate(start.U, len)(f) - assert(controlVec.asUInt() === testVec.asUInt(), s"Expected Vec to be filled like $controlVec, instead creaeted $testVec\n") + assert( + controlVec.asUInt() === testVec.asUInt(), + s"Expected Vec to be filled like $controlVec, instead creaeted $testVec\n" + ) stop() } class ShiftRegisterTester(n: Int) extends BasicTester { - val (cnt, wrap) = Counter(true.B, n*2) - val shifter = Reg(Vec(n, UInt((log2Ceil(n) max 1).W))) - (shifter, shifter drop 1).zipped.foreach(_ := _) - shifter(n-1) := cnt - when (cnt >= n.asUInt) { + val (cnt, wrap) = Counter(true.B, n * 2) + val shifter = Reg(Vec(n, UInt((log2Ceil(n).max(1)).W))) + (shifter, shifter.drop(1)).zipped.foreach(_ := _) + shifter(n - 1) := cnt + when(cnt >= n.asUInt) { val expected = cnt - n.asUInt assert(shifter(0) === expected) } - when (wrap) { + when(wrap) { stop() } } @@ -299,10 +302,10 @@ class ModuleIODynamicIndexTester(n: Int) extends BasicTester { val (cycle, done) = Counter(true.B, n) for ((m, i) <- duts.zipWithIndex) { - when (cycle =/= i.U) { - m.in := 0.U // default + when(cycle =/= i.U) { + m.in := 0.U // default assert(m.out === 0.U) - } .otherwise { + }.otherwise { m.in := DontCare } } @@ -310,7 +313,7 @@ class ModuleIODynamicIndexTester(n: Int) extends BasicTester { duts(cycle) <> tester.io assert(duts(cycle).out === 123.U) - when (done) { stop() } + when(done) { stop() } } class ReduceTreeTester() extends BasicTester { @@ -349,84 +352,107 @@ class VecSpec extends ChiselPropSpec with Utils { implicit val noShrinkInt = Shrink[Int](_ => Stream.empty) property("Vecs should be assignable") { - forAll(safeUIntN(8)) { case(w: Int, v: List[Int]) => - assertTesterPasses{ new ValueTester(w, v) } + forAll(safeUIntN(8)) { + case (w: Int, v: List[Int]) => + assertTesterPasses { new ValueTester(w, v) } } } property("Vecs should be passed through vec IO") { - forAll(safeUIntN(8)) { case(w: Int, v: List[Int]) => - assertTesterPasses{ new IOTester(w, v) } + forAll(safeUIntN(8)) { + case (w: Int, v: List[Int]) => + assertTesterPasses { new IOTester(w, v) } } } property("Vec.fill with a pure type should generate an exception") { // We don't really need a sequence of random widths here, since any should throw an exception. - forAll(safeUIntWidth) { case(w: Int) => - an[BindingException] should be thrownBy extractCause[BindingException] { - ChiselStage.elaborate(new IOTesterModFill(w)) - } + forAll(safeUIntWidth) { + case (w: Int) => + an[BindingException] should be thrownBy extractCause[BindingException] { + ChiselStage.elaborate(new IOTesterModFill(w)) + } } } property("A Reg of a Vec should operate correctly") { - forAll(safeUIntN(8)) { case(w: Int, v: List[Int]) => - assertTesterPasses{ new RegTester(w, v) } + forAll(safeUIntN(8)) { + case (w: Int, v: List[Int]) => + assertTesterPasses { new RegTester(w, v) } } } property("A Vec of lit should operate correctly") { - forAll(safeUIntN(8)) { case(w: Int, v: List[Int]) => - assertTesterPasses{ new LitTester(w, v) } + forAll(safeUIntN(8)) { + case (w: Int, v: List[Int]) => + assertTesterPasses { new LitTester(w, v) } } } property("VecInit should tabulate correctly") { - forAll(smallPosInts) { (n: Int) => assertTesterPasses{ new TabulateTester(n) } } + forAll(smallPosInts) { (n: Int) => assertTesterPasses { new TabulateTester(n) } } } property("VecInit should tabulate 2D vec correctly") { - forAll(smallPosInts, smallPosInts) { (n: Int, m: Int) => assertTesterPasses { new VecMultiDimTester.TabulateTester2D(n, m) } } + forAll(smallPosInts, smallPosInts) { (n: Int, m: Int) => + assertTesterPasses { new VecMultiDimTester.TabulateTester2D(n, m) } + } } property("VecInit should tabulate 3D vec correctly") { - forAll(smallPosInts, smallPosInts, smallPosInts) { (n: Int, m: Int, p: Int) => assertTesterPasses{ new VecMultiDimTester.TabulateTester3D(n, m, p) } } + forAll(smallPosInts, smallPosInts, smallPosInts) { (n: Int, m: Int, p: Int) => + assertTesterPasses { new VecMultiDimTester.TabulateTester3D(n, m, p) } + } } property("VecInit should fill correctly") { - forAll(smallPosInts, Gen.choose(0, 50)) { (n: Int, value: Int) => assertTesterPasses{ new FillTester(n, value) } } + forAll(smallPosInts, Gen.choose(0, 50)) { (n: Int, value: Int) => assertTesterPasses { new FillTester(n, value) } } } property("VecInit should fill 2D vec correctly") { - forAll(smallPosInts, smallPosInts, Gen.choose(0, 50)) { (n: Int, m: Int, value: Int) => assertTesterPasses{ new VecMultiDimTester.Fill2DTester(n, m, value) } } + forAll(smallPosInts, smallPosInts, Gen.choose(0, 50)) { (n: Int, m: Int, value: Int) => + assertTesterPasses { new VecMultiDimTester.Fill2DTester(n, m, value) } + } } - + property("VecInit should fill 3D vec correctly") { - forAll(smallPosInts, smallPosInts, smallPosInts, Gen.choose(0, 50)) { (n: Int, m: Int, p: Int, value: Int) => assertTesterPasses{ new VecMultiDimTester.Fill3DTester(n, m, p, value) } } + forAll(smallPosInts, smallPosInts, smallPosInts, Gen.choose(0, 50)) { (n: Int, m: Int, p: Int, value: Int) => + assertTesterPasses { new VecMultiDimTester.Fill3DTester(n, m, p, value) } + } } property("VecInit should support 2D fill bidirectional wire connection") { - forAll(smallPosInts, smallPosInts) { (n: Int, m: Int) => assertTesterPasses{ new VecMultiDimTester.BidirectionalTester2DFill(n, m) }} + forAll(smallPosInts, smallPosInts) { (n: Int, m: Int) => + assertTesterPasses { new VecMultiDimTester.BidirectionalTester2DFill(n, m) } + } } - + property("VecInit should support 3D fill bidirectional wire connection") { - forAll(smallPosInts, smallPosInts, smallPosInts) { (n: Int, m: Int, p: Int) => assertTesterPasses{ new VecMultiDimTester.BidirectionalTester3DFill(n, m, p) }} + forAll(smallPosInts, smallPosInts, smallPosInts) { (n: Int, m: Int, p: Int) => + assertTesterPasses { new VecMultiDimTester.BidirectionalTester3DFill(n, m, p) } + } } property("VecInit should support 2D tabulate bidirectional wire connection") { - forAll(smallPosInts, smallPosInts) { (n: Int, m: Int) => assertTesterPasses{ new VecMultiDimTester.BidirectionalTester2DTabulate(n, m) }} + forAll(smallPosInts, smallPosInts) { (n: Int, m: Int) => + assertTesterPasses { new VecMultiDimTester.BidirectionalTester2DTabulate(n, m) } + } } - + property("VecInit should support 3D tabulate bidirectional wire connection") { - forAll(smallPosInts, smallPosInts, smallPosInts) { (n: Int, m: Int, p: Int) => assertTesterPasses{ new VecMultiDimTester.BidirectionalTester3DTabulate(n, m, p) }} + forAll(smallPosInts, smallPosInts, smallPosInts) { (n: Int, m: Int, p: Int) => + assertTesterPasses { new VecMultiDimTester.BidirectionalTester3DTabulate(n, m, p) } + } } - + property("VecInit should iterate correctly") { - forAll(Gen.choose(1, 10), smallPosInts) { (start: Int, len: Int) => assertTesterPasses{ new IterateTester(start, len)(x => x + 50.U)}} + forAll(Gen.choose(1, 10), smallPosInts) { (start: Int, len: Int) => + assertTesterPasses { new IterateTester(start, len)(x => x + 50.U) } + } } property("Regs of vecs should be usable as shift registers") { - forAll(smallPosInts) { (n: Int) => assertTesterPasses{ new ShiftRegisterTester(n) } } + forAll(smallPosInts) { (n: Int) => assertTesterPasses { new ShiftRegisterTester(n) } } } property("Infering widths on huge Vecs should not cause a stack overflow") { @@ -434,15 +460,15 @@ class VecSpec extends ChiselPropSpec with Utils { } property("A Reg of a Vec of a single 1 bit element should compile and work") { - assertTesterPasses{ new OneBitUnitRegVecTester } + assertTesterPasses { new OneBitUnitRegVecTester } } property("A Vec with zero entries should compile and have zero width") { - assertTesterPasses{ new ZeroEntryVecTester } + assertTesterPasses { new ZeroEntryVecTester } } property("Dynamic indexing of a Vec of Module IOs should work") { - assertTesterPasses{ new ModuleIODynamicIndexTester(4) } + assertTesterPasses { new ModuleIODynamicIndexTester(4) } } property("It should be possible to bulk connect a Vec and a Seq") { @@ -456,7 +482,7 @@ class VecSpec extends ChiselPropSpec with Utils { } property("Bulk connecting a Vec and Seq of different sizes should report a ChiselException") { - a [ChiselException] should be thrownBy extractCause[ChiselException] { + a[ChiselException] should be thrownBy extractCause[ChiselException] { ChiselStage.elaborate(new Module { val io = IO(new Bundle { val out = Output(Vec(4, UInt(8.W))) @@ -477,17 +503,18 @@ class VecSpec extends ChiselPropSpec with Utils { } property("Indexing a Chisel type Vec by a hardware type should give a sane error message") { - a [ExpectedHardwareException] should be thrownBy extractCause[ChiselException] { - ChiselStage.elaborate{ + a[ExpectedHardwareException] should be thrownBy extractCause[ChiselException] { + ChiselStage.elaborate { new Module { - val io = IO(new Bundle{}) + val io = IO(new Bundle {}) val foo = Vec(2, Bool()) foo(0.U) := false.B - }} + } + } } } property("reduceTree should preserve input/output type") { - assertTesterPasses { new ReduceTreeTester() } + assertTesterPasses { new ReduceTreeTester() } } } diff --git a/src/test/scala/chiselTests/VecLiteralSpec.scala b/src/test/scala/chiselTests/VecLiteralSpec.scala index 74d8c005..228f409b 100644 --- a/src/test/scala/chiselTests/VecLiteralSpec.scala +++ b/src/test/scala/chiselTests/VecLiteralSpec.scala @@ -20,10 +20,10 @@ class VecLiteralSpec extends ChiselFreeSpec with Utils { } "Vec literals should work with chisel Enums" in { - val enumVec = Vec(3, MyEnum()).Lit(0 -> MyEnum.sA, 1 -> MyEnum.sB, 2-> MyEnum.sC) - enumVec(0).toString should include (MyEnum.sA.toString) - enumVec(1).toString should include (MyEnum.sB.toString) - enumVec(2).toString should include (MyEnum.sC.toString) + val enumVec = Vec(3, MyEnum()).Lit(0 -> MyEnum.sA, 1 -> MyEnum.sB, 2 -> MyEnum.sC) + enumVec(0).toString should include(MyEnum.sA.toString) + enumVec(1).toString should include(MyEnum.sB.toString) + enumVec(2).toString should include(MyEnum.sC.toString) } "improperly constructed vec literals should be detected" - { @@ -31,7 +31,7 @@ class VecLiteralSpec extends ChiselFreeSpec with Utils { val e = intercept[VecLiteralException] { Vec(2, UInt(4.W)).Lit(0 -> 1.U, 1 -> 2.U, 2 -> 3.U, 3 -> 4.U, -2 -> 7.U) } - e.getMessage should include ( + e.getMessage should include( "VecLiteral: The following indices (2,3,-2) are less than zero or greater or equal to than Vec length" ) } @@ -56,7 +56,7 @@ class VecLiteralSpec extends ChiselFreeSpec with Utils { val v = Vec(2, SInt(4.W)).Lit(0 -> 1.S, 1 -> -2.S) v(0).toString should include(1.S(4.W).toString) v(1).toString should include((-2).S(4.W).toString) - v.toString should include ("SInt<4>[2](0=SLit(1,<4>), 1=SLit(-2,<4>)") + v.toString should include("SInt<4>[2](0=SLit(1,<4>), 1=SLit(-2,<4>)") } "all lits must be the same type but width cannot be greater than Vec's element width" in { @@ -71,7 +71,7 @@ class VecLiteralSpec extends ChiselFreeSpec with Utils { //NOTE: I had problems where this would not work if this class declaration was inside test scope class HasVecInit extends Module { - val initValue = Vec(4, UInt(8.W)).Lit(0 -> 0xAB.U(8.W), 1 -> 0xCD.U(8.W), 2 -> 0xEF.U(8.W), 3 -> 0xFF.U(8.W)) + val initValue = Vec(4, UInt(8.W)).Lit(0 -> 0xab.U(8.W), 1 -> 0xcd.U(8.W), 2 -> 0xef.U(8.W), 3 -> 0xff.U(8.W)) val y = RegInit(initValue) } @@ -86,7 +86,7 @@ class VecLiteralSpec extends ChiselFreeSpec with Utils { //NOTE: I had problems where this would not work if this class declaration was inside test scope class HasPartialVecInit extends Module { - val initValue = Vec(4, UInt(8.W)).Lit(0 -> 0xAB.U(8.W), 2 -> 0xEF.U(8.W), 3 -> 0xFF.U(8.W)) + val initValue = Vec(4, UInt(8.W)).Lit(0 -> 0xab.U(8.W), 2 -> 0xef.U(8.W), 3 -> 0xff.U(8.W)) val y = RegInit(initValue) } @@ -102,7 +102,7 @@ class VecLiteralSpec extends ChiselFreeSpec with Utils { class ResetRegWithPartialVecLiteral extends Module { val in = IO(Input(Vec(4, UInt(8.W)))) val out = IO(Output(Vec(4, UInt(8.W)))) - val initValue = Vec(4, UInt(8.W)).Lit(0 -> 0xAB.U(8.W), 2 -> 0xEF.U(8.W), 3 -> 0xFF.U(8.W)) + val initValue = Vec(4, UInt(8.W)).Lit(0 -> 0xab.U(8.W), 2 -> 0xef.U(8.W), 3 -> 0xff.U(8.W)) val y = RegInit(initValue) when(in(1) > 0.U) { y(1) := in(1) @@ -132,7 +132,7 @@ class VecLiteralSpec extends ChiselFreeSpec with Utils { }.elsewhen(counter > 2.U) { // m.out(1) should not be reset, m.out(2) should be reset chisel3.assert(m.out(1) === 0xff.U) - chisel3.assert(m.out(2) === 0xEF.U) + chisel3.assert(m.out(2) === 0xef.U) } when(wrapped) { stop() @@ -141,12 +141,12 @@ class VecLiteralSpec extends ChiselFreeSpec with Utils { } "lowest of vec literal contains least significant bits and " in { - val y = Vec(4, UInt(8.W)).Lit(0 -> 0xAB.U(8.W), 1 -> 0xCD.U(8.W), 2 -> 0xEF.U(8.W), 3 -> 0xFF.U(8.W)) + val y = Vec(4, UInt(8.W)).Lit(0 -> 0xab.U(8.W), 1 -> 0xcd.U(8.W), 2 -> 0xef.U(8.W), 3 -> 0xff.U(8.W)) y.litValue should be(BigInt("FFEFCDAB", 16)) } "the order lits are specified does not matter" in { - val y = Vec(4, UInt(8.W)).Lit(3 -> 0xFF.U(8.W), 2 -> 0xEF.U(8.W), 1 -> 0xCD.U(8.W), 0 -> 0xAB.U(8.W)) + val y = Vec(4, UInt(8.W)).Lit(3 -> 0xff.U(8.W), 2 -> 0xef.U(8.W), 1 -> 0xcd.U(8.W), 0 -> 0xab.U(8.W)) y.litValue should be(BigInt("FFEFCDAB", 16)) } @@ -164,7 +164,7 @@ class VecLiteralSpec extends ChiselFreeSpec with Utils { "registers can be initialized with a Vec literal" in { assertTesterPasses(new BasicTester { - val y = RegInit(Vec(4, UInt(8.W)).Lit(0 -> 0xAB.U(8.W), 1 -> 0xCD.U(8.W), 2 -> 0xEF.U(8.W), 3 -> 0xFF.U(8.W))) + val y = RegInit(Vec(4, UInt(8.W)).Lit(0 -> 0xab.U(8.W), 1 -> 0xcd.U(8.W), 2 -> 0xef.U(8.W), 3 -> 0xff.U(8.W))) chisel3.assert(y.asUInt === BigInt("FFEFCDAB", 16).U) stop() }) @@ -172,9 +172,9 @@ class VecLiteralSpec extends ChiselFreeSpec with Utils { "how does asUInt work" in { assertTesterPasses(new BasicTester { - val vec1 = Vec(4, UInt(16.W)).Lit(0 -> 0xDD.U, 1 -> 0xCC.U, 2 -> 0xBB.U, 3 -> 0xAA.U) + val vec1 = Vec(4, UInt(16.W)).Lit(0 -> 0xdd.U, 1 -> 0xcc.U, 2 -> 0xbb.U, 3 -> 0xaa.U) - val vec2 = VecInit(Seq(0xDD.U, 0xCC.U, 0xBB.U, 0xAA.U)) + val vec2 = VecInit(Seq(0xdd.U, 0xcc.U, 0xbb.U, 0xaa.U)) printf("vec1 %x\n", vec1.asUInt()) printf("vec2 %x\n", vec2.asUInt()) stop() @@ -186,10 +186,10 @@ class VecLiteralSpec extends ChiselFreeSpec with Utils { val out1 = IO(Output(UInt(64.W))) val out2 = IO(Output(UInt(64.W))) - val v1 = Vec(4, UInt(16.W)).Lit(0 -> 0xDD.U, 1 -> 0xCC.U, 2 -> 0xBB.U, 3 -> 0xAA.U) + val v1 = Vec(4, UInt(16.W)).Lit(0 -> 0xdd.U, 1 -> 0xcc.U, 2 -> 0xbb.U, 3 -> 0xaa.U) out1 := v1.asUInt - val v2 = VecInit(0xDD.U(16.W), 0xCC.U, 0xBB.U, 0xAA.U) + val v2 = VecInit(0xdd.U(16.W), 0xcc.U, 0xbb.U, 0xaa.U) out2 := v2.asUInt } @@ -201,33 +201,33 @@ class VecLiteralSpec extends ChiselFreeSpec with Utils { } "VecLits should work properly with .asUInt" in { - val outsideVecLit = Vec(4, UInt(16.W)).Lit(0 -> 0xDD.U, 1 -> 0xCC.U, 2 -> 0xBB.U, 3 -> 0xAA.U) + val outsideVecLit = Vec(4, UInt(16.W)).Lit(0 -> 0xdd.U, 1 -> 0xcc.U, 2 -> 0xbb.U, 3 -> 0xaa.U) assertTesterPasses { new BasicTester { - chisel3.assert(outsideVecLit(0) === 0xDD.U, s"v(0)") + chisel3.assert(outsideVecLit(0) === 0xdd.U, s"v(0)") stop() } } } "bundle literals should work in RTL" in { - val outsideVecLit = Vec(4, UInt(16.W)).Lit(0 -> 0xDD.U, 1 -> 0xCC.U, 2 -> 0xBB.U, 3 -> 0xAA.U) + val outsideVecLit = Vec(4, UInt(16.W)).Lit(0 -> 0xdd.U, 1 -> 0xcc.U, 2 -> 0xbb.U, 3 -> 0xaa.U) assertTesterPasses { new BasicTester { - chisel3.assert(outsideVecLit(0) === 0xDD.U, s"v(0)") - chisel3.assert(outsideVecLit(1) === 0xCC.U) - chisel3.assert(outsideVecLit(2) === 0xBB.U) - chisel3.assert(outsideVecLit(3) === 0xAA.U) + chisel3.assert(outsideVecLit(0) === 0xdd.U, s"v(0)") + chisel3.assert(outsideVecLit(1) === 0xcc.U) + chisel3.assert(outsideVecLit(2) === 0xbb.U) + chisel3.assert(outsideVecLit(3) === 0xaa.U) chisel3.assert(outsideVecLit.litValue.U === outsideVecLit.asUInt()) - val insideVecLit = Vec(4, UInt(16.W)).Lit(0 -> 0xDD.U, 1 -> 0xCC.U, 2 -> 0xBB.U, 3 -> 0xAA.U) - chisel3.assert(insideVecLit(0) === 0xDD.U) - chisel3.assert(insideVecLit(1) === 0xCC.U) - chisel3.assert(insideVecLit(2) === 0xBB.U) - chisel3.assert(insideVecLit(3) === 0xAA.U) + val insideVecLit = Vec(4, UInt(16.W)).Lit(0 -> 0xdd.U, 1 -> 0xcc.U, 2 -> 0xbb.U, 3 -> 0xaa.U) + chisel3.assert(insideVecLit(0) === 0xdd.U) + chisel3.assert(insideVecLit(1) === 0xcc.U) + chisel3.assert(insideVecLit(2) === 0xbb.U) + chisel3.assert(insideVecLit(3) === 0xaa.U) chisel3.assert(insideVecLit(0) === outsideVecLit(0)) chisel3.assert(insideVecLit(1) === outsideVecLit(1)) @@ -237,18 +237,18 @@ class VecLiteralSpec extends ChiselFreeSpec with Utils { val vecWire1 = Wire(Vec(4, UInt(16.W))) vecWire1 := outsideVecLit - chisel3.assert(vecWire1(0) === 0xDD.U) - chisel3.assert(vecWire1(1) === 0xCC.U) - chisel3.assert(vecWire1(2) === 0xBB.U) - chisel3.assert(vecWire1(3) === 0xAA.U) + chisel3.assert(vecWire1(0) === 0xdd.U) + chisel3.assert(vecWire1(1) === 0xcc.U) + chisel3.assert(vecWire1(2) === 0xbb.U) + chisel3.assert(vecWire1(3) === 0xaa.U) val vecWire2 = Wire(Vec(4, UInt(16.W))) vecWire2 := insideVecLit - chisel3.assert(vecWire2(0) === 0xDD.U) - chisel3.assert(vecWire2(1) === 0xCC.U) - chisel3.assert(vecWire2(2) === 0xBB.U) - chisel3.assert(vecWire2(3) === 0xAA.U) + chisel3.assert(vecWire2(0) === 0xdd.U) + chisel3.assert(vecWire2(1) === 0xcc.U) + chisel3.assert(vecWire2(2) === 0xbb.U) + chisel3.assert(vecWire2(3) === 0xaa.U) stop() } @@ -256,19 +256,21 @@ class VecLiteralSpec extends ChiselFreeSpec with Utils { } "partial vec literals should work in RTL" in { - assertTesterPasses{ new BasicTester{ - val vecLit = Vec(4, UInt(8.W)).Lit(0 -> 42.U, 2 -> 5.U) - chisel3.assert(vecLit(0) === 42.U) - chisel3.assert(vecLit(2) === 5.U) + assertTesterPasses { + new BasicTester { + val vecLit = Vec(4, UInt(8.W)).Lit(0 -> 42.U, 2 -> 5.U) + chisel3.assert(vecLit(0) === 42.U) + chisel3.assert(vecLit(2) === 5.U) - val vecWire = Wire(Vec(4, UInt(8.W))) - vecWire := vecLit + val vecWire = Wire(Vec(4, UInt(8.W))) + vecWire := vecLit - chisel3.assert(vecWire(0) === 42.U) - chisel3.assert(vecWire(2) === 5.U) + chisel3.assert(vecWire(0) === 42.U) + chisel3.assert(vecWire(2) === 5.U) - stop() - }} + stop() + } + } } "nested vec literals should be constructable" in { @@ -277,42 +279,44 @@ class VecLiteralSpec extends ChiselFreeSpec with Utils { 1 -> Vec(3, UInt(4.W)).Lit(0 -> 4.U, 1 -> 5.U, 2 -> 6.U) ) - outerVec.litValue should be (BigInt("654321", 16)) - outerVec(0).litValue should be (BigInt("321", 16)) - outerVec(1).litValue should be (BigInt("654", 16)) - outerVec(0)(0).litValue should be (BigInt(1)) - outerVec(0)(1).litValue should be (BigInt(2)) - outerVec(0)(2).litValue should be (BigInt(3)) - outerVec(1)(0).litValue should be (BigInt(4)) - outerVec(1)(1).litValue should be (BigInt(5)) - outerVec(1)(2).litValue should be (BigInt(6)) + outerVec.litValue should be(BigInt("654321", 16)) + outerVec(0).litValue should be(BigInt("321", 16)) + outerVec(1).litValue should be(BigInt("654", 16)) + outerVec(0)(0).litValue should be(BigInt(1)) + outerVec(0)(1).litValue should be(BigInt(2)) + outerVec(0)(2).litValue should be(BigInt(3)) + outerVec(1)(0).litValue should be(BigInt(4)) + outerVec(1)(1).litValue should be(BigInt(5)) + outerVec(1)(2).litValue should be(BigInt(6)) } "contained vecs should work" in { - assertTesterPasses{ new BasicTester { - val outerVec = Vec(2, Vec(3, UInt(4.W))).Lit( - 0 -> Vec(3, UInt(4.W)).Lit(0 -> 1.U, 1 -> 2.U, 2 -> 3.U), - 1 -> Vec(3, UInt(4.W)).Lit(0 -> 4.U, 1 -> 5.U, 2 -> 6.U) - ) - - chisel3.assert(outerVec(0)(0) === 1.U) - chisel3.assert(outerVec(0)(1) === 2.U) - chisel3.assert(outerVec(0)(2) === 3.U) - chisel3.assert(outerVec(1)(0) === 4.U) - chisel3.assert(outerVec(1)(1) === 5.U) - chisel3.assert(outerVec(1)(2) === 6.U) - - val v0 = outerVec(0) - val v1 = outerVec(1) - chisel3.assert(v0(0) === 1.U) - chisel3.assert(v0(1) === 2.U) - chisel3.assert(v0(2) === 3.U) - chisel3.assert(v1(0) === 4.U) - chisel3.assert(v1(1) === 5.U) - chisel3.assert(v1(2) === 6.U) + assertTesterPasses { + new BasicTester { + val outerVec = Vec(2, Vec(3, UInt(4.W))).Lit( + 0 -> Vec(3, UInt(4.W)).Lit(0 -> 1.U, 1 -> 2.U, 2 -> 3.U), + 1 -> Vec(3, UInt(4.W)).Lit(0 -> 4.U, 1 -> 5.U, 2 -> 6.U) + ) + + chisel3.assert(outerVec(0)(0) === 1.U) + chisel3.assert(outerVec(0)(1) === 2.U) + chisel3.assert(outerVec(0)(2) === 3.U) + chisel3.assert(outerVec(1)(0) === 4.U) + chisel3.assert(outerVec(1)(1) === 5.U) + chisel3.assert(outerVec(1)(2) === 6.U) + + val v0 = outerVec(0) + val v1 = outerVec(1) + chisel3.assert(v0(0) === 1.U) + chisel3.assert(v0(1) === 2.U) + chisel3.assert(v0(2) === 3.U) + chisel3.assert(v1(0) === 4.U) + chisel3.assert(v1(1) === 5.U) + chisel3.assert(v1(2) === 6.U) - stop() - }} + stop() + } + } } //TODO: decide what behavior here should be @@ -360,13 +364,13 @@ class VecLiteralSpec extends ChiselFreeSpec with Utils { "Vec literals should work as register reset values" in { assertTesterPasses { new BasicTester { - val r = RegInit(Vec(3, UInt(11.W)).Lit(0 -> 0xA.U, 1 -> 0xB.U, 2 -> 0xC.U)) + val r = RegInit(Vec(3, UInt(11.W)).Lit(0 -> 0xa.U, 1 -> 0xb.U, 2 -> 0xc.U)) r := (r.asUInt + 1.U).asTypeOf(Vec(3, UInt(11.W))) // prevent constprop // check reset values on first cycle out of reset - chisel3.assert(r(0) === 0xA.U) - chisel3.assert(r(1) === 0xB.U) - chisel3.assert(r(2) === 0xC.U) + chisel3.assert(r(0) === 0xa.U) + chisel3.assert(r(1) === 0xb.U) + chisel3.assert(r(2) === 0xc.U) stop() } } @@ -375,11 +379,11 @@ class VecLiteralSpec extends ChiselFreeSpec with Utils { "partially initialized Vec literals should work as register reset values" in { assertTesterPasses { new BasicTester { - val r = RegInit(Vec(3, UInt(11.W)).Lit(0 -> 0xA.U, 2 -> 0xC.U)) + val r = RegInit(Vec(3, UInt(11.W)).Lit(0 -> 0xa.U, 2 -> 0xc.U)) r := (r.asUInt + 1.U).asTypeOf(Vec(3, UInt(11.W))) // prevent constprop // check reset values on first cycle out of reset - chisel3.assert(r(0) === 0xA.U) - chisel3.assert(r(2) === 0xC.U) + chisel3.assert(r(0) === 0xa.U) + chisel3.assert(r(2) === 0xc.U) stop() } } @@ -388,9 +392,9 @@ class VecLiteralSpec extends ChiselFreeSpec with Utils { "Fields extracted from Vec Literals should work as register reset values" in { assertTesterPasses { new BasicTester { - val r = RegInit(Vec(3, UInt(11.W)).Lit(0 -> 0xA.U, 2 -> 0xC.U).apply(0)) + val r = RegInit(Vec(3, UInt(11.W)).Lit(0 -> 0xa.U, 2 -> 0xc.U).apply(0)) r := r + 1.U // prevent const prop - chisel3.assert(r === 0xA.U) // coming out of reset + chisel3.assert(r === 0xa.U) // coming out of reset stop() } } diff --git a/src/test/scala/chiselTests/VectorPacketIO.scala b/src/test/scala/chiselTests/VectorPacketIO.scala index c4b0f1f7..1474177f 100644 --- a/src/test/scala/chiselTests/VectorPacketIO.scala +++ b/src/test/scala/chiselTests/VectorPacketIO.scala @@ -28,7 +28,7 @@ class Packet extends Bundle { * The problem does not occur if the Vec is taken out */ class VectorPacketIO(val n: Int) extends Bundle { - val ins = Vec(n, chisel3.util.DeqIO(new Packet())) + val ins = Vec(n, chisel3.util.DeqIO(new Packet())) val outs = Vec(n, chisel3.util.EnqIO(new Packet())) } @@ -37,7 +37,7 @@ class VectorPacketIO(val n: Int) extends Bundle { * the value of n does not affect the error */ class BrokenVectorPacketModule extends Module { - val n = 4 + val n = 4 val io = IO(new VectorPacketIO(n)) // Avoid a "Reference io is not fully initialized" error from firrtl. diff --git a/src/test/scala/chiselTests/VerificationSpec.scala b/src/test/scala/chiselTests/VerificationSpec.scala index 2d7144df..95b0ffe6 100644 --- a/src/test/scala/chiselTests/VerificationSpec.scala +++ b/src/test/scala/chiselTests/VerificationSpec.scala @@ -11,13 +11,13 @@ import org.scalatest.matchers.should.Matchers import java.io.File class SimpleTest extends Module { - val io = IO(new Bundle{ + val io = IO(new Bundle { val in = Input(UInt(8.W)) val out = Output(UInt(8.W)) }) io.out := io.in cover(io.in === 3.U) - when (io.in === 3.U) { + when(io.in === 3.U) { assume(io.in =/= 2.U) assert(io.out === io.in) } @@ -31,6 +31,7 @@ case class VerifAnnotation(target: ReferenceTarget) extends SingleTargetAnnotati } object VerifAnnotation { + /** Create annotation for a given verification component. * @param c component to be annotated */ @@ -64,9 +65,10 @@ class VerificationSpec extends ChiselPropSpec with Matchers { } property("annotation of verification constructs should work") { + /** Circuit that contains and annotates verification nodes. */ class AnnotationTest extends Module { - val io = IO(new Bundle{ + val io = IO(new Bundle { val in = Input(UInt(8.W)) val out = Output(UInt(8.W)) }) @@ -92,10 +94,10 @@ class VerificationSpec extends ChiselPropSpec with Matchers { val annoLines = scala.io.Source.fromFile(annoFile).getLines.toList // check for expected verification annotations - exactly(3, annoLines) should include ("chiselTests.VerifAnnotation") - exactly(1, annoLines) should include ("~AnnotationTest|AnnotationTest>asst") - exactly(1, annoLines) should include ("~AnnotationTest|AnnotationTest>assm") - exactly(1, annoLines) should include ("~AnnotationTest|AnnotationTest>cov") + exactly(3, annoLines) should include("chiselTests.VerifAnnotation") + exactly(1, annoLines) should include("~AnnotationTest|AnnotationTest>asst") + exactly(1, annoLines) should include("~AnnotationTest|AnnotationTest>assm") + exactly(1, annoLines) should include("~AnnotationTest|AnnotationTest>cov") // read in FIRRTL file val firFile = new File(testDir, "AnnotationTest.fir") @@ -103,15 +105,16 @@ class VerificationSpec extends ChiselPropSpec with Matchers { val firLines = scala.io.Source.fromFile(firFile).getLines.toList // check that verification components have expected names - exactly(1, firLines) should include ("cover(clock, _T, UInt<1>(\"h1\"), \"\") : cov") - exactly(1, firLines) should include ("assume(clock, _T_3, UInt<1>(\"h1\"), \"\") : assm") - exactly(1, firLines) should include ("assert(clock, _T_7, UInt<1>(\"h1\"), \"\") : asst") + exactly(1, firLines) should include("cover(clock, _T, UInt<1>(\"h1\"), \"\") : cov") + exactly(1, firLines) should include("assume(clock, _T_3, UInt<1>(\"h1\"), \"\") : assm") + exactly(1, firLines) should include("assert(clock, _T_7, UInt<1>(\"h1\"), \"\") : asst") } property("annotation of verification constructs with suggested name should work") { + /** Circuit that annotates a renamed verification nodes. */ class AnnotationRenameTest extends Module { - val io = IO(new Bundle{ + val io = IO(new Bundle { val in = Input(UInt(8.W)) val out = Output(UInt(8.W)) }) @@ -137,9 +140,9 @@ class VerificationSpec extends ChiselPropSpec with Matchers { val annoLines = scala.io.Source.fromFile(annoFile).getLines.toList // check for expected verification annotations - exactly(2, annoLines) should include ("chiselTests.VerifAnnotation") - exactly(1, annoLines) should include ("~AnnotationRenameTest|AnnotationRenameTest>hello") - exactly(1, annoLines) should include ("~AnnotationRenameTest|AnnotationRenameTest>howdy") + exactly(2, annoLines) should include("chiselTests.VerifAnnotation") + exactly(1, annoLines) should include("~AnnotationRenameTest|AnnotationRenameTest>hello") + exactly(1, annoLines) should include("~AnnotationRenameTest|AnnotationRenameTest>howdy") // read in FIRRTL file val firFile = new File(testDir, "AnnotationRenameTest.fir") @@ -147,7 +150,7 @@ class VerificationSpec extends ChiselPropSpec with Matchers { val firLines = scala.io.Source.fromFile(firFile).getLines.toList // check that verification components have expected names - exactly(1, firLines) should include ("assert(clock, _T, UInt<1>(\"h1\"), \"\") : hello") - exactly(1, firLines) should include ("assume(clock, _T_4, UInt<1>(\"h1\"), \"\") : howdy") + exactly(1, firLines) should include("assert(clock, _T, UInt<1>(\"h1\"), \"\") : hello") + exactly(1, firLines) should include("assume(clock, _T_4, UInt<1>(\"h1\"), \"\") : howdy") } } diff --git a/src/test/scala/chiselTests/When.scala b/src/test/scala/chiselTests/When.scala index 3b5ec62e..032a8eac 100644 --- a/src/test/scala/chiselTests/When.scala +++ b/src/test/scala/chiselTests/When.scala @@ -14,11 +14,11 @@ class WhenTester() extends BasicTester { val out = Wire(UInt(3.W)) when(cnt.value === 0.U) { out := 1.U - } .elsewhen (cnt.value === 1.U) { + }.elsewhen(cnt.value === 1.U) { out := 2.U - } .elsewhen (cnt.value === 2.U) { + }.elsewhen(cnt.value === 2.U) { out := 3.U - } .otherwise { + }.otherwise { out := 0.U } @@ -36,11 +36,11 @@ class OverlappedWhenTester() extends BasicTester { val out = Wire(UInt(3.W)) when(cnt.value <= 0.U) { out := 1.U - } .elsewhen (cnt.value <= 1.U) { + }.elsewhen(cnt.value <= 1.U) { out := 2.U - } .elsewhen (cnt.value <= 2.U) { + }.elsewhen(cnt.value <= 2.U) { out := 3.U - } .otherwise { + }.otherwise { out := 0.U } @@ -58,13 +58,13 @@ class NoOtherwiseOverlappedWhenTester() extends BasicTester { val out = Wire(UInt(3.W)) when(cnt.value <= 0.U) { out := 1.U - } .elsewhen (cnt.value <= 1.U) { + }.elsewhen(cnt.value <= 1.U) { out := 2.U - } .elsewhen (cnt.value <= 2.U) { + }.elsewhen(cnt.value <= 2.U) { out := 3.U - } .elsewhen (cnt.value <= 3.U) { + }.elsewhen(cnt.value <= 3.U) { out := 0.U - } .otherwise { + }.otherwise { out := DontCare } @@ -77,15 +77,14 @@ class NoOtherwiseOverlappedWhenTester() extends BasicTester { class SubmoduleWhenTester extends BasicTester { val (cycle, done) = Counter(true.B, 3) - when (done) { stop() } - val children = Seq(Module(new PassthroughModule), - Module(new PassthroughMultiIOModule), - Module(new PassthroughRawModule)) + when(done) { stop() } + val children = + Seq(Module(new PassthroughModule), Module(new PassthroughMultiIOModule), Module(new PassthroughRawModule)) children.foreach { child => - when (cycle === 1.U) { + when(cycle === 1.U) { child.io.in := "hdeadbeef".U assert(child.io.out === "hdeadbeef".U) - } .otherwise { + }.otherwise { child.io.in := "h0badcad0".U assert(child.io.out === "h0badcad0".U) } @@ -97,17 +96,17 @@ class WhenCondTester extends BasicTester { val (cycle, done) = Counter(true.B, 1 << pred.size) // Cycle through every predicate pred := cycle.asBools - val Seq(a, b, c, d) = pred // Just for nicer accessors + val Seq(a, b, c, d) = pred // Just for nicer accessors // When want the when predicates on connection to optimize away, // it's not necessary but it makes the Verilog prettier val w1, w2, w3, w4, w5, w6, w7 = WireInit(Bool(), DontCare) - when (a) { + when(a) { w1 := when.cond - when (b) { + when(b) { w2 := when.cond - }.elsewhen (c) { + }.elsewhen(c) { w3 := when.cond - }.elsewhen (d) { + }.elsewhen(d) { w4 := when.cond }.otherwise { w5 := when.cond @@ -125,18 +124,18 @@ class WhenCondTester extends BasicTester { assert(w6 === !a) assert(w7) - when (done) { stop() } + when(done) { stop() } } class WhenSpec extends ChiselFlatSpec with Utils { "When, elsewhen, and otherwise with orthogonal conditions" should "work" in { - assertTesterPasses{ new WhenTester } + assertTesterPasses { new WhenTester } } "When, elsewhen, and otherwise with overlapped conditions" should "work" in { - assertTesterPasses{ new OverlappedWhenTester } + assertTesterPasses { new OverlappedWhenTester } } "When and elsewhen without otherwise with overlapped conditions" should "work" in { - assertTesterPasses{ new NoOtherwiseOverlappedWhenTester } + assertTesterPasses { new NoOtherwiseOverlappedWhenTester } } "Conditional connections to submodule ports" should "be handled properly" in { assertTesterPasses(new SubmoduleWhenTester) @@ -146,7 +145,7 @@ class WhenSpec extends ChiselFlatSpec with Utils { } "Returning in a when scope" should "give a reasonable error message" in { - val e = the [ChiselException] thrownBy extractCause[ChiselException] { + val e = the[ChiselException] thrownBy extractCause[ChiselException] { ChiselStage.elaborate(new Module { val io = IO(new Bundle { val foo = Input(UInt(8.W)) @@ -164,6 +163,6 @@ class WhenSpec extends ChiselFlatSpec with Utils { io.out := func() }) } - e.getMessage should include ("Cannot exit from a when() block with a \"return\"") + e.getMessage should include("Cannot exit from a when() block with a \"return\"") } } diff --git a/src/test/scala/chiselTests/WidthSpec.scala b/src/test/scala/chiselTests/WidthSpec.scala index 34159214..77a09e1c 100644 --- a/src/test/scala/chiselTests/WidthSpec.scala +++ b/src/test/scala/chiselTests/WidthSpec.scala @@ -19,13 +19,13 @@ object SimpleBundle { class WidthSpec extends ChiselFlatSpec { "Literals without specified widths" should "get the minimum legal width" in { - "hdeadbeef".U.getWidth should be (32) - "h_dead_beef".U.getWidth should be (32) - "h0a".U.getWidth should be (4) - "h1a".U.getWidth should be (5) - "h0".U.getWidth should be (1) - 1.U.getWidth should be (1) - 1.S.getWidth should be (2) + "hdeadbeef".U.getWidth should be(32) + "h_dead_beef".U.getWidth should be(32) + "h0a".U.getWidth should be(4) + "h1a".U.getWidth should be(5) + "h0".U.getWidth should be(1) + 1.U.getWidth should be(1) + 1.S.getWidth should be(2) } } @@ -33,7 +33,7 @@ abstract class WireRegWidthSpecImpl extends ChiselFlatSpec { def name: String def builder[T <: Data](x: T): T - behavior of name + behavior.of(name) it should "set the width if the template type has a set width" in { assertKnownWidth(4) { @@ -83,7 +83,7 @@ abstract class WireDefaultRegInitSpecImpl extends ChiselFlatSpec { def builder1[T <: Data](x: T): T def builder2[T <: Data](x: T, y: T): T - behavior of s"$name (Single Argument)" + behavior.of(s"$name (Single Argument)") it should "set width if passed a literal with forced width" in { assertKnownWidth(4) { @@ -129,7 +129,7 @@ abstract class WireDefaultRegInitSpecImpl extends ChiselFlatSpec { } } - behavior of s"$name (Double Argument)" + behavior.of(s"$name (Double Argument)") it should "set the width if the template type has a set width" in { assertKnownWidth(4) { @@ -152,7 +152,10 @@ abstract class WireDefaultRegInitSpecImpl extends ChiselFlatSpec { it should "infer the width if the template type has no width" in { val templates = Seq( - () => 0.U, () => 0.U(2.W), () => WireDefault(0.U), () => WireDefault(0.U(2.W)) + () => 0.U, + () => 0.U(2.W), + () => WireDefault(0.U), + () => WireDefault(0.U(2.W)) ) for (gen <- templates) { assertInferredWidth(4) { diff --git a/src/test/scala/chiselTests/aop/InjectionSpec.scala b/src/test/scala/chiselTests/aop/InjectionSpec.scala index a28501a5..9b29b0ba 100644 --- a/src/test/scala/chiselTests/aop/InjectionSpec.scala +++ b/src/test/scala/chiselTests/aop/InjectionSpec.scala @@ -38,12 +38,15 @@ object InjectionHierarchy { val in = Input(Bool()) }) //scalastyle:off regex - setInline("SubmoduleC.v", s""" - |module SubmoduleC( - | input io_in - |); - |endmodule - """.stripMargin) + setInline( + "SubmoduleC.v", + s""" + |module SubmoduleC( + | input io_in + |); + |endmodule + """.stripMargin + ) } class AspectTester(results: Seq[Int]) extends BasicTester { @@ -63,26 +66,26 @@ object InjectionHierarchy { class InjectionSpec extends ChiselFlatSpec with Utils { import InjectionHierarchy._ val correctValueAspect = InjectingAspect( - {dut: AspectTester => Seq(dut)}, - {dut: AspectTester => - for(i <- 0 until dut.values.length) { + { dut: AspectTester => Seq(dut) }, + { dut: AspectTester => + for (i <- 0 until dut.values.length) { dut.values(i) := i.U } } ) val wrongValueAspect = InjectingAspect( - {dut: AspectTester => Seq(dut)}, - {dut: AspectTester => - for(i <- 0 until dut.values.length) { + { dut: AspectTester => Seq(dut) }, + { dut: AspectTester => + for (i <- 0 until dut.values.length) { dut.values(i) := (i + 1).U } } ) val manipulateSubmoduleAspect = InjectingAspect( - {dut: SubmoduleManipulationTester => Seq(dut)}, - {dut: SubmoduleManipulationTester => + { dut: SubmoduleManipulationTester => Seq(dut) }, + { dut: SubmoduleManipulationTester => val moduleSubmoduleB = Module(new SubmoduleB) moduleSubmoduleB.io.in := dut.moduleSubmoduleA.io.out //if we're here then we've elaborated correctly @@ -91,8 +94,8 @@ class InjectionSpec extends ChiselFlatSpec with Utils { ) val duplicateSubmoduleAspect = InjectingAspect( - {dut: SubmoduleManipulationTester => Seq(dut)}, - {_: SubmoduleManipulationTester => + { dut: SubmoduleManipulationTester => Seq(dut) }, + { _: SubmoduleManipulationTester => // By creating a second SubmoduleA, the module names would conflict unless they were uniquified val moduleSubmoduleA2 = Module(new SubmoduleA) //if we're here then we've elaborated correctly @@ -101,8 +104,8 @@ class InjectionSpec extends ChiselFlatSpec with Utils { ) val addingExternalModules = InjectingAspect( - {dut: SubmoduleManipulationTester => Seq(dut)}, - {_: SubmoduleManipulationTester => + { dut: SubmoduleManipulationTester => Seq(dut) }, + { _: SubmoduleManipulationTester => // By creating a second SubmoduleA, the module names would conflict unless they were uniquified val moduleSubmoduleC = Module(new SubmoduleC) //if we're here then we've elaborated correctly @@ -123,30 +126,36 @@ class InjectionSpec extends ChiselFlatSpec with Utils { ) "Test" should "pass if inserted the correct values" in { - assertTesterPasses{ new AspectTester(Seq(0, 1, 2)) } + assertTesterPasses { new AspectTester(Seq(0, 1, 2)) } } "Test" should "fail if inserted the wrong values" in { - assertTesterFails{ new AspectTester(Seq(9, 9, 9)) } + assertTesterFails { new AspectTester(Seq(9, 9, 9)) } } "Test" should "pass if pass wrong values, but correct with aspect" in { - assertTesterPasses({ new AspectTester(Seq(9, 9, 9))} , Nil, Seq(correctValueAspect) ++ TesterDriver.verilatorOnly) + assertTesterPasses({ new AspectTester(Seq(9, 9, 9)) }, Nil, Seq(correctValueAspect) ++ TesterDriver.verilatorOnly) } "Test" should "pass if pass wrong values, then wrong aspect, then correct aspect" in { assertTesterPasses( - new AspectTester(Seq(9, 9, 9)), Nil, Seq(wrongValueAspect, correctValueAspect) ++ TesterDriver.verilatorOnly + new AspectTester(Seq(9, 9, 9)), + Nil, + Seq(wrongValueAspect, correctValueAspect) ++ TesterDriver.verilatorOnly ) } "Test" should "fail if pass wrong values, then correct aspect, then wrong aspect" in { - assertTesterFails({ new AspectTester(Seq(9, 9, 9))} , Nil, Seq(correctValueAspect, wrongValueAspect)) + assertTesterFails({ new AspectTester(Seq(9, 9, 9)) }, Nil, Seq(correctValueAspect, wrongValueAspect)) } "Test" should "pass if the submodules in SubmoduleManipulationTester can be manipulated by manipulateSubmoduleAspect" in { - assertTesterPasses({ new SubmoduleManipulationTester} , Nil, Seq(manipulateSubmoduleAspect) ++ TesterDriver.verilatorOnly) + assertTesterPasses( + { new SubmoduleManipulationTester }, + Nil, + Seq(manipulateSubmoduleAspect) ++ TesterDriver.verilatorOnly + ) } "Module name collisions when adding a new module" should "be resolved" in { assertTesterPasses( - { new SubmoduleManipulationTester}, + { new SubmoduleManipulationTester }, Nil, Seq(duplicateSubmoduleAspect) ++ TesterDriver.verilatorOnly ) @@ -154,7 +163,7 @@ class InjectionSpec extends ChiselFlatSpec with Utils { "Adding external modules" should "work" in { assertTesterPasses( - { new SubmoduleManipulationTester}, + { new SubmoduleManipulationTester }, Nil, Seq(addingExternalModules) ++ TesterDriver.verilatorOnly ) @@ -162,7 +171,7 @@ class InjectionSpec extends ChiselFlatSpec with Utils { "Injection into multiple submodules of the same class" should "work" in { assertTesterPasses( - {new MultiModuleInjectionTester}, + { new MultiModuleInjectionTester }, Nil, Seq(multiModuleInjectionAspect) ++ TesterDriver.verilatorOnly ) diff --git a/src/test/scala/chiselTests/aop/SelectSpec.scala b/src/test/scala/chiselTests/aop/SelectSpec.scala index 2b47c6b8..72802c80 100644 --- a/src/test/scala/chiselTests/aop/SelectSpec.scala +++ b/src/test/scala/chiselTests/aop/SelectSpec.scala @@ -39,22 +39,35 @@ case class SelectAspect[T <: RawModule, X](selector: T => Seq[X], desired: T => override def toAnnotation(top: T): AnnotationSeq = { val results = selector(top) val desiredSeq = desired(top) - assert(results.length == desiredSeq.length, s"Failure! Results $results have different length than desired $desiredSeq!") + assert( + results.length == desiredSeq.length, + s"Failure! Results $results have different length than desired $desiredSeq!" + ) val mismatches = results.zip(desiredSeq).flatMap { case (res, des) if res != des => Seq((res, des)) - case other => Nil + case other => Nil } - assert(mismatches.isEmpty,s"Failure! The following selected items do not match their desired item:\n" + mismatches.map{ - case (res: Select.Serializeable, des: Select.Serializeable) => s" ${res.serialize} does not match:\n ${des.serialize}" - case (res, des) => s" $res does not match:\n $des" - }.mkString("\n")) + assert( + mismatches.isEmpty, + s"Failure! The following selected items do not match their desired item:\n" + mismatches.map { + case (res: Select.Serializeable, des: Select.Serializeable) => + s" ${res.serialize} does not match:\n ${des.serialize}" + case (res, des) => s" $res does not match:\n $des" + }.mkString("\n") + ) Nil } } class SelectSpec extends ChiselFlatSpec { - def execute[T <: RawModule, X](dut: () => T, selector: T => Seq[X], desired: T => Seq[X])(implicit tTag: TypeTag[T]): Unit = { + def execute[T <: RawModule, X]( + dut: () => T, + selector: T => Seq[X], + desired: T => Seq[X] + )( + implicit tTag: TypeTag[T] + ): Unit = { val ret = new chisel3.stage.ChiselStage().run( Seq( new chisel3.stage.ChiselGeneratorAnnotation(dut), @@ -85,16 +98,20 @@ class SelectSpec extends ChiselFlatSpec { () => new SelectTester(Seq(0, 1, 2)), { dut: SelectTester => Seq(Select.printfs(dut).last.toString) }, { dut: SelectTester => - Seq(Select.Printf( - dut.p, - Seq( - When(Select.ops("eq")(dut).last.asInstanceOf[Bool]), - When(dut.nreset), - WhenNot(dut.overflow) - ), - dut.p.pable, - dut.clock - ).toString) + Seq( + Select + .Printf( + dut.p, + Seq( + When(Select.ops("eq")(dut).last.asInstanceOf[Bool]), + When(dut.nreset), + WhenNot(dut.overflow) + ), + dut.p.pable, + dut.clock + ) + .toString + ) } ) } @@ -104,8 +121,10 @@ class SelectSpec extends ChiselFlatSpec { () => new SelectTester(Seq(0, 1, 2)), { dut: SelectTester => Select.connectionsTo(dut)(dut.counter) }, { dut: SelectTester => - Seq(PredicatedConnect(Nil, dut.counter, dut.added, false), - PredicatedConnect(Seq(When(dut.overflow)), dut.counter, dut.zero, false)) + Seq( + PredicatedConnect(Nil, dut.counter, dut.added, false), + PredicatedConnect(Seq(When(dut.overflow)), dut.counter, dut.zero, false) + ) } ) } @@ -121,7 +140,7 @@ class SelectSpec extends ChiselFlatSpec { "Test" should "pass if selecting ops" in { execute( () => new SelectTester(Seq(0, 1, 2)), - { dut: SelectTester => Select.ops(dut).collect { case ("tail", d) => d} }, + { dut: SelectTester => Select.ops(dut).collect { case ("tail", d) => d } }, { dut: SelectTester => Seq(dut.added, dut.zero) } ) } @@ -131,20 +150,22 @@ class SelectSpec extends ChiselFlatSpec { () => new SelectTester(Seq(0, 1, 2)), { dut: SelectTester => Seq(Select.stops(dut).last) }, { dut: SelectTester => - Seq(Select.Stop( - Seq( - When(Select.ops("eq")(dut)(1).asInstanceOf[Bool]), - When(dut.overflow) - ), - 0, - dut.clock - )) + Seq( + Select.Stop( + Seq( + When(Select.ops("eq")(dut)(1).asInstanceOf[Bool]), + When(dut.overflow) + ), + 0, + dut.clock + ) + ) } ) } "Blackboxes" should "be supported in Select.instances" in { - class BB extends ExtModule { } + class BB extends ExtModule {} class Top extends RawModule { val bb = Module(new BB) } @@ -173,12 +194,10 @@ class SelectSpec extends ChiselFlatSpec { } val top = ChiselGeneratorAnnotation(() => { new Top() - }).elaborate - .collectFirst { case DesignAnnotation(design: Top) => design } - .get - Select.collectDeep(top) { case x => x } should equal (Seq(top, top.inst0)) - Select.getDeep(top)(x => Seq(x)) should equal (Seq(top, top.inst0)) - Select.instances(top) should equal (Seq(top.inst0)) + }).elaborate.collectFirst { case DesignAnnotation(design: Top) => design }.get + Select.collectDeep(top) { case x => x } should equal(Seq(top, top.inst0)) + Select.getDeep(top)(x => Seq(x)) should equal(Seq(top, top.inst0)) + Select.instances(top) should equal(Seq(top.inst0)) } "Using Definition/Instance with Injecting Aspects" should "throw an error" in { @@ -202,13 +221,10 @@ class SelectSpec extends ChiselFlatSpec { } val top = ChiselGeneratorAnnotation(() => { new Top() - }).elaborate - .collectFirst { case DesignAnnotation(design: Top) => design } - .get + }).elaborate.collectFirst { case DesignAnnotation(design: Top) => design }.get intercept[Exception] { Select.collectDeep(top) { case x => x } } intercept[Exception] { Select.getDeep(top)(x => Seq(x)) } intercept[Exception] { Select.instances(top) } } } - diff --git a/src/test/scala/chiselTests/experimental/DataView.scala b/src/test/scala/chiselTests/experimental/DataView.scala index 7c5d170b..5ef062fa 100644 --- a/src/test/scala/chiselTests/experimental/DataView.scala +++ b/src/test/scala/chiselTests/experimental/DataView.scala @@ -54,7 +54,7 @@ object FlatDecoupledDataView { class DataViewSpec extends ChiselFlatSpec { - behavior of "DataView" + behavior.of("DataView") it should "support simple Bundle viewing" in { import SimpleBundleDataView._ @@ -240,8 +240,8 @@ class DataViewSpec extends ChiselFlatSpec { fooOut := cat } val chirrtl = ChiselStage.emitChirrtl(new MyModule) - chirrtl should include ("node cat = cat(barIn.foo, barIn.bar)") - chirrtl should include ("fooOut <= cat") + chirrtl should include("node cat = cat(barIn.foo, barIn.bar)") + chirrtl should include("fooOut <= cat") } it should "be composable" in { @@ -262,8 +262,8 @@ class DataViewSpec extends ChiselFlatSpec { z := b.viewAs[Bar].viewAs[Fizz] } val chirrtl = ChiselStage.emitChirrtl(new MyModule) - chirrtl should include ("y.fizz <= a.foo") - chirrtl should include ("z.fizz <= b.foo") + chirrtl should include("y.fizz <= a.foo") + chirrtl should include("z.fizz <= b.foo") } it should "enable using Seq like Data" in { @@ -277,8 +277,8 @@ class DataViewSpec extends ChiselFlatSpec { } // Verilog instead of CHIRRTL because the optimizations make it much prettier val verilog = ChiselStage.emitVerilog(new MyModule) - verilog should include ("assign y = sel ? a : c;") - verilog should include ("assign z = sel ? b : d;") + verilog should include("assign y = sel ? a : c;") + verilog should include("assign z = sel ? b : d;") } // This example should be turned into a built-in feature @@ -291,9 +291,9 @@ class DataViewSpec extends ChiselFlatSpec { } // Verilog instead of CHIRRTL because the optimizations make it much prettier val verilog = ChiselStage.emitVerilog(new MyModule) - verilog should include ("assign x = a;") - verilog should include ("assign y = b;") - verilog should include ("assign z = c;") + verilog should include("assign x = a;") + verilog should include("assign y = b;") + verilog should include("assign z = c;") } it should "support recursive composition of views" in { @@ -307,10 +307,10 @@ class DataViewSpec extends ChiselFlatSpec { Seq((w, x), (y, z)) := VecInit[HWTuple2[UInt, UInt]]((a, b), (c, d)) } val verilog = ChiselStage.emitVerilog(new MyModule) - verilog should include ("assign w = a;") - verilog should include ("assign x = b;") - verilog should include ("assign y = c;") - verilog should include ("assign z = d;") + verilog should include("assign w = a;") + verilog should include("assign x = b;") + verilog should include("assign y = c;") + verilog should include("assign z = d;") } it should "support dynamic indexing for Vec identity views" in { @@ -328,8 +328,8 @@ class DataViewSpec extends ChiselFlatSpec { dataOut := selected } val chirrtl = ChiselStage.emitChirrtl(new MyModule) - chirrtl should include ("vec[addr] <= dataIn") - chirrtl should include ("dataOut <= vec[addr]") + chirrtl should include("vec[addr] <= dataIn") + chirrtl should include("dataOut <= vec[addr]") } it should "error if you try to dynamically index a Vec view that does not correspond to a Vec target" in { @@ -346,9 +346,9 @@ class DataViewSpec extends ChiselFlatSpec { selected := (inA, inB) (outA, outB) := selected } - (the [InvalidViewException] thrownBy { + (the[InvalidViewException] thrownBy { ChiselStage.emitChirrtl(new MyModule) - }).getMessage should include ("Dynamic indexing of Views is not yet supported") + }).getMessage should include("Dynamic indexing of Views is not yet supported") } it should "error if the mapping is non-total in the view" in { @@ -360,8 +360,8 @@ class DataViewSpec extends ChiselFlatSpec { val out = IO(Output(tpe)) out := in.viewAs[MyBundle] } - val err = the [InvalidViewException] thrownBy (ChiselStage.emitVerilog(new MyModule)) - err.toString should include ("View field '_.foo' is missing") + val err = the[InvalidViewException] thrownBy (ChiselStage.emitVerilog(new MyModule)) + err.toString should include("View field '_.foo' is missing") } it should "error if the mapping is non-total in the target" in { @@ -371,8 +371,8 @@ class DataViewSpec extends ChiselFlatSpec { val out = IO(Output(UInt(8.W))) out := (a, b).viewAs[UInt] } - val err = the [InvalidViewException] thrownBy (ChiselStage.emitVerilog(new MyModule)) - err.toString should include ("Target field '_._2' is missing") + val err = the[InvalidViewException] thrownBy (ChiselStage.emitVerilog(new MyModule)) + err.toString should include("Target field '_._2' is missing") } it should "error if the mapping contains Data that are not part of the Target" in { @@ -389,8 +389,8 @@ class DataViewSpec extends ChiselFlatSpec { val out = IO(Output(new BundleB)) out := in.viewAs[BundleB] } - val err = the [InvalidViewException] thrownBy (ChiselStage.emitVerilog(new MyModule)) - err.toString should include ("View mapping must only contain Elements within the Target") + val err = the[InvalidViewException] thrownBy (ChiselStage.emitVerilog(new MyModule)) + err.toString should include("View mapping must only contain Elements within the Target") } it should "error if the mapping contains Data that are not part of the View" in { @@ -408,8 +408,8 @@ class DataViewSpec extends ChiselFlatSpec { val out = IO(Output(new BundleB)) out.viewAs[BundleA] := in } - val err = the [InvalidViewException] thrownBy (ChiselStage.emitVerilog(new MyModule)) - err.toString should include ("View mapping must only contain Elements within the View") + val err = the[InvalidViewException] thrownBy (ChiselStage.emitVerilog(new MyModule)) + err.toString should include("View mapping must only contain Elements within the View") } it should "error if a view has a width that does not match the target" in { @@ -425,9 +425,9 @@ class DataViewSpec extends ChiselFlatSpec { val out = IO(Output(new BundleB)) out := in.viewAs[BundleB] } - val err = the [InvalidViewException] thrownBy ChiselStage.emitChirrtl(new MyModule) + val err = the[InvalidViewException] thrownBy ChiselStage.emitChirrtl(new MyModule) val expected = """View field _\.bar UInt<4> has width <4> that is incompatible with target value .+'s width <8>""".r - err.getMessage should fullyMatch regex expected + (err.getMessage should fullyMatch).regex(expected) } it should "error if a view has a known width when the target width is unknown" in { @@ -443,12 +443,13 @@ class DataViewSpec extends ChiselFlatSpec { val out = IO(Output(new BundleB)) out := in.viewAs[BundleB] } - val err = the [InvalidViewException] thrownBy ChiselStage.emitChirrtl(new MyModule) - val expected = """View field _\.bar UInt<4> has width <4> that is incompatible with target value .+'s width <unknown>""".r - err.getMessage should fullyMatch regex expected + val err = the[InvalidViewException] thrownBy ChiselStage.emitChirrtl(new MyModule) + val expected = + """View field _\.bar UInt<4> has width <4> that is incompatible with target value .+'s width <unknown>""".r + (err.getMessage should fullyMatch).regex(expected) } - behavior of "PartialDataView" + behavior.of("PartialDataView") it should "still error if the mapping is non-total in the view" in { class MyBundle(val foo: UInt, val bar: UInt) extends Bundle @@ -458,8 +459,8 @@ class DataViewSpec extends ChiselFlatSpec { val out = IO(Output(new MyBundle(UInt(8.W), UInt(8.W)))) out := in.viewAs[MyBundle] } - val err = the [InvalidViewException] thrownBy (ChiselStage.emitVerilog(new MyModule)) - err.toString should include ("View field '_.foo' is missing") + val err = the[InvalidViewException] thrownBy (ChiselStage.emitVerilog(new MyModule)) + err.toString should include("View field '_.foo' is missing") } it should "NOT error if the mapping is non-total in the target" in { @@ -470,6 +471,6 @@ class DataViewSpec extends ChiselFlatSpec { out := (a, b).viewAs[UInt] } val verilog = ChiselStage.emitVerilog(new MyModule) - verilog should include ("assign out = b;") + verilog should include("assign out = b;") } } diff --git a/src/test/scala/chiselTests/experimental/DataViewIntegrationSpec.scala b/src/test/scala/chiselTests/experimental/DataViewIntegrationSpec.scala index 3f149f75..4704a942 100644 --- a/src/test/scala/chiselTests/experimental/DataViewIntegrationSpec.scala +++ b/src/test/scala/chiselTests/experimental/DataViewIntegrationSpec.scala @@ -5,7 +5,7 @@ package chiselTests.experimental import chisel3._ import chisel3.experimental.{BaseModule, ExtModule} import chisel3.experimental.dataview._ -import chisel3.util.{Decoupled, DecoupledIO, Queue, QueueIO, log2Ceil} +import chisel3.util.{log2Ceil, Decoupled, DecoupledIO, Queue, QueueIO} import chiselTests.ChiselFlatSpec import firrtl.transforms.DontTouchAnnotation @@ -52,6 +52,6 @@ class DataViewIntegrationSpec extends ChiselFlatSpec { "Users" should "be able to view and annotate Modules" in { val (_, annos) = getFirrtlAndAnnos(new MyModule) val ts = annos.collect { case DontTouchAnnotation(t) => t.serialize } - ts should equal (Seq("~MyModule|Queue>enq_ptr_value")) + ts should equal(Seq("~MyModule|Queue>enq_ptr_value")) } } diff --git a/src/test/scala/chiselTests/experimental/DataViewTargetSpec.scala b/src/test/scala/chiselTests/experimental/DataViewTargetSpec.scala index a17b0f40..da27c9c8 100644 --- a/src/test/scala/chiselTests/experimental/DataViewTargetSpec.scala +++ b/src/test/scala/chiselTests/experimental/DataViewTargetSpec.scala @@ -5,7 +5,7 @@ package chiselTests.experimental import chisel3._ import chisel3.experimental.dataview._ import chisel3.experimental.conversions._ -import chisel3.experimental.{ChiselAnnotation, annotate} +import chisel3.experimental.{annotate, ChiselAnnotation} import chiselTests.ChiselFlatSpec object DataViewTargetSpec { @@ -29,22 +29,22 @@ class DataViewTargetSpec extends ChiselFlatSpec { _.instanceName, _.pathName, _.parentPathName, - _.parentModName, + _.parentModName ) // Check helpers private def checkAll(impl: Data, refs: String*): Unit = { - refs.size should be (checks.size) + refs.size should be(checks.size) for ((check, value) <- checks.zip(refs)) { - check(impl) should be (value) + check(impl) should be(value) } } private def checkSameAs(impl: Data, refs: Data*): Unit = for (ref <- refs) { - checkAll(impl, checks.map(_(ref)):_*) + checkAll(impl, checks.map(_(ref)): _*) } - behavior of "DataView Naming" + behavior.of("DataView Naming") it should "support views of Elements" in { class MyChild extends Module { @@ -67,7 +67,8 @@ class DataViewTargetSpec extends ChiselFlatSpec { val foo = UInt(8.W) val bars = Vec(2, UInt(8.W)) } - implicit val dv = DataView[MyBundle, Vec[UInt]](_ => Vec(3, UInt(8.W)), _.foo -> _(0), _.bars(0) -> _(1), _.bars(1) -> _(2)) + implicit val dv = + DataView[MyBundle, Vec[UInt]](_ => Vec(3, UInt(8.W)), _.foo -> _(0), _.bars(0) -> _(1), _.bars(1) -> _(2)) class MyChild extends Module { val out = IO(Output(new MyBundle)) val outView = out.viewAs[Vec[UInt]] // Note different type @@ -82,7 +83,7 @@ class DataViewTargetSpec extends ChiselFlatSpec { out := inst.out } val m = elaborateAndGetModule(new MyParent) - val outView = m.inst.out.viewAs[Vec[UInt]]// Note different type + val outView = m.inst.out.viewAs[Vec[UInt]] // Note different type val outFooView = m.inst.out.foo.viewAs[UInt] val outBarsView = m.inst.out.bars.viewAs[Vec[UInt]] val outBars0View = m.inst.out.bars(0).viewAs[UInt] @@ -90,8 +91,15 @@ class DataViewTargetSpec extends ChiselFlatSpec { checkSameAs(m.inst.out, m.inst.outView, outView) checkSameAs(m.inst.out.foo, m.inst.outFooView, m.inst.outView(0), outFooView, outView(0)) checkSameAs(m.inst.out.bars, m.inst.outBarsView, outBarsView) - checkSameAs(m.inst.out.bars(0), m.inst.outBars0View, outBars0View, m.inst.outView(1), outView(1), - m.inst.outBarsView(0), outBarsView(0)) + checkSameAs( + m.inst.out.bars(0), + m.inst.outBars0View, + outBars0View, + m.inst.outView(1), + outView(1), + m.inst.outBarsView(0), + outBarsView(0) + ) } // Ideally this would work 1:1 but that requires changing the binding @@ -123,7 +131,7 @@ class DataViewTargetSpec extends ChiselFlatSpec { 2 -> "~MyParent|MyParent/inst:MyChild>out.foo", 3 -> "~MyParent|MyParent/inst:MyChild>out" ) - pairs should equal (expected) + pairs should equal(expected) } it should "support annotating views that cannot be mapped to a single ReferenceTarget" in { @@ -161,9 +169,9 @@ class DataViewTargetSpec extends ChiselFlatSpec { 3 -> "~MyParent|MyParent/inst:MyChild>io.c", 3 -> "~MyParent|MyParent/inst:MyChild>io.d", 4 -> "~MyParent|MyChild>io.b", - 4 -> "~MyParent|MyChild>io.d", + 4 -> "~MyParent|MyChild>io.d" ) - pairs should equal (expected) + pairs should equal(expected) } // TODO check these properties when using @instance API (especially preservation of totality) diff --git a/src/test/scala/chiselTests/experimental/ForceNames.scala b/src/test/scala/chiselTests/experimental/ForceNames.scala index 06f911e6..233b4a5f 100644 --- a/src/test/scala/chiselTests/experimental/ForceNames.scala +++ b/src/test/scala/chiselTests/experimental/ForceNames.scala @@ -6,7 +6,7 @@ import firrtl._ import chisel3._ import chisel3.experimental.annotate import chisel3.stage.{ChiselGeneratorAnnotation, ChiselStage} -import chisel3.util.experimental.{ForceNameAnnotation, ForceNamesTransform, InlineInstance, forceName} +import chisel3.util.experimental.{forceName, ForceNameAnnotation, ForceNamesTransform, InlineInstance} import firrtl.annotations.{Annotation, ReferenceTarget} import firrtl.options.{Dependency, TargetDirAnnotation} import firrtl.stage.RunFirrtlTransformAnnotation @@ -61,7 +61,12 @@ object ForceNamesHierarchy { class ForceNamesSpec extends ChiselFlatSpec { - def run[T <: RawModule](dut: => T, testName: String, inputAnnos: Seq[Annotation] = Nil, info: LogLevel.Value = LogLevel.None): Iterable[String] = { + def run[T <: RawModule]( + dut: => T, + testName: String, + inputAnnos: Seq[Annotation] = Nil, + info: LogLevel.Value = LogLevel.None + ): Iterable[String] = { def stage = new ChiselStage { override val targets = Seq( Dependency[chisel3.stage.phases.Elaborate], @@ -85,11 +90,11 @@ class ForceNamesSpec extends ChiselFlatSpec { } "Force Names on a wrapping instance" should "work" in { val verilog = run(new ForceNamesHierarchy.WrapperExample, "wrapper") - exactly(1, verilog) should include ("MyLeaf inst") + exactly(1, verilog) should include("MyLeaf inst") } "Force Names on an instance port" should "work" in { val verilog = run(new ForceNamesHierarchy.RenamePortsExample, "instports") - atLeast(1, verilog) should include ("input [2:0] inn") + atLeast(1, verilog) should include("input [2:0] inn") } "Force Names with a conflicting name" should "error" in { intercept[CustomTransformException] { diff --git a/src/test/scala/chiselTests/experimental/GroupSpec.scala b/src/test/scala/chiselTests/experimental/GroupSpec.scala index 52435ad8..5e0c34bb 100644 --- a/src/test/scala/chiselTests/experimental/GroupSpec.scala +++ b/src/test/scala/chiselTests/experimental/GroupSpec.scala @@ -16,9 +16,9 @@ import scala.collection.mutable class GroupSpec extends ChiselFlatSpec { - def collectInstances(c: fir.Circuit, top: Option[String] = None): Seq[String] = new InstanceGraph(c) - .fullHierarchy.values.flatten.toSeq - .map( v => (top.getOrElse(v.head.name) +: v.tail.map(_.name)).mkString(".") ) + def collectInstances(c: fir.Circuit, top: Option[String] = None): Seq[String] = + new InstanceGraph(c).fullHierarchy.values.flatten.toSeq + .map(v => (top.getOrElse(v.head.name) +: v.tail.map(_.name)).mkString(".")) def collectDeclarations(m: fir.DefModule): Set[String] = { val decs = mutable.HashSet[String]() @@ -32,17 +32,16 @@ class GroupSpec extends ChiselFlatSpec { def lower[T <: RawModule](gen: () => T): fir.Circuit = { (new ChiselStage) - .execute(Array("--compiler", "low", - "--target-dir", "test_run_dir"), - Seq(ChiselGeneratorAnnotation(gen))) + .execute(Array("--compiler", "low", "--target-dir", "test_run_dir"), Seq(ChiselGeneratorAnnotation(gen))) .collectFirst { case firrtl.stage.FirrtlCircuitAnnotation(circuit) => circuit - }.get + } + .get } "Module Grouping" should "compile to low FIRRTL" in { class MyModule extends Module { - val io = IO(new Bundle{ + val io = IO(new Bundle { val a = Input(Bool()) val b = Output(Bool()) }) @@ -56,17 +55,17 @@ class GroupSpec extends ChiselFlatSpec { val firrtlCircuit = lower(() => new MyModule) firrtlCircuit.modules.collect { case m: fir.Module if m.name == "MyModule" => - Set("doubleReg") should be (collectDeclarations(m)) + Set("doubleReg") should be(collectDeclarations(m)) case m: fir.Module if m.name == "DosRegisters" => - Set("reg1", "reg2") should be (collectDeclarations(m)) + Set("reg1", "reg2") should be(collectDeclarations(m)) } val instances = collectInstances(firrtlCircuit, Some("MyModule")).toSet - Set("MyModule", "MyModule.doubleReg") should be (instances) + Set("MyModule", "MyModule.doubleReg") should be(instances) } "Module Grouping" should "not include intermediate registers" in { class MyModule extends Module { - val io = IO(new Bundle{ + val io = IO(new Bundle { val a = Input(Bool()) val b = Output(Bool()) }) @@ -81,17 +80,17 @@ class GroupSpec extends ChiselFlatSpec { val firrtlCircuit = lower(() => new MyModule) firrtlCircuit.modules.collect { case m: fir.Module if m.name == "MyModule" => - Set("reg2", "doubleReg") should be (collectDeclarations(m)) + Set("reg2", "doubleReg") should be(collectDeclarations(m)) case m: fir.Module if m.name == "DosRegisters" => - Set("reg1", "reg3") should be (collectDeclarations(m)) + Set("reg1", "reg3") should be(collectDeclarations(m)) } val instances = collectInstances(firrtlCircuit, Some("MyModule")).toSet - Set("MyModule", "MyModule.doubleReg") should be (instances) + Set("MyModule", "MyModule.doubleReg") should be(instances) } "Module Grouping" should "include intermediate wires" in { class MyModule extends Module { - val io = IO(new Bundle{ + val io = IO(new Bundle { val a = Input(Bool()) val b = Output(Bool()) }) @@ -106,11 +105,11 @@ class GroupSpec extends ChiselFlatSpec { val firrtlCircuit = lower(() => new MyModule) firrtlCircuit.modules.collect { case m: fir.Module if m.name == "MyModule" => - Set("doubleReg") should be (collectDeclarations(m)) + Set("doubleReg") should be(collectDeclarations(m)) case m: fir.Module if m.name == "DosRegisters" => - Set("reg1", "reg3", "wire") should be (collectDeclarations(m)) + Set("reg1", "reg3", "wire") should be(collectDeclarations(m)) } val instances = collectInstances(firrtlCircuit, Some("MyModule")).toSet - Set("MyModule", "MyModule.doubleReg") should be (instances) + Set("MyModule", "MyModule.doubleReg") should be(instances) } } diff --git a/src/test/scala/chiselTests/experimental/ModuleDataProductSpec.scala b/src/test/scala/chiselTests/experimental/ModuleDataProductSpec.scala index 78986517..713f9d04 100644 --- a/src/test/scala/chiselTests/experimental/ModuleDataProductSpec.scala +++ b/src/test/scala/chiselTests/experimental/ModuleDataProductSpec.scala @@ -39,7 +39,7 @@ object ModuleDataProductSpec { class ModuleDataProductSpec extends ChiselFlatSpec { import ModuleDataProductSpec._ - behavior of "DataProduct" + behavior.of("DataProduct") it should "work for UserModules (recursively)" in { val m = elaborateAndGetModule(new MyUserModule) @@ -62,7 +62,7 @@ class ModuleDataProductSpec extends ChiselFlatSpec { val impl = implicitly[DataProduct[MyUserModule]] val set = impl.dataSet(m) for ((d, _) <- expected) { - set(d) should be (true) + set(d) should be(true) } val it = impl.dataIterator(m, "m") it.toList should contain theSameElementsAs (expected) @@ -82,7 +82,7 @@ class ModuleDataProductSpec extends ChiselFlatSpec { val impl = implicitly[DataProduct[MyExtModule]] val set = impl.dataSet(m) for ((d, _) <- expected) { - set(d) should be (true) + set(d) should be(true) } val it = impl.dataIterator(m, "m") it.toList should contain theSameElementsAs (expected) diff --git a/src/test/scala/chiselTests/experimental/ProgrammaticPortsSpec.scala b/src/test/scala/chiselTests/experimental/ProgrammaticPortsSpec.scala index ffe3a37f..64aabb4b 100644 --- a/src/test/scala/chiselTests/experimental/ProgrammaticPortsSpec.scala +++ b/src/test/scala/chiselTests/experimental/ProgrammaticPortsSpec.scala @@ -63,7 +63,7 @@ class ProgrammaticPortsSpec extends ChiselFlatSpec with Utils { } "SuggestName collisions on ports" should "be illegal" in { - a [ChiselException] should be thrownBy extractCause[ChiselException] { + a[ChiselException] should be thrownBy extractCause[ChiselException] { ChiselStage.elaborate(new Module { val foo = IO(UInt(8.W)).suggestName("apple") val bar = IO(UInt(8.W)).suggestName("apple") diff --git a/src/test/scala/chiselTests/experimental/TraceSpec.scala b/src/test/scala/chiselTests/experimental/TraceSpec.scala index 59548921..31ccdf9b 100644 --- a/src/test/scala/chiselTests/experimental/TraceSpec.scala +++ b/src/test/scala/chiselTests/experimental/TraceSpec.scala @@ -88,13 +88,17 @@ class TraceSpec extends ChiselFlatSpec with Matchers { .flatMap(finalTarget(annos)) .toSet .map { target: CompleteTarget => - s"""public_flat_rd -module "${target.tokens.collectFirst { case OfModule(m) => m }.get}" -var "${target.tokens.collectFirst { case Ref(r) => r }.get}"""" + s"""public_flat_rd -module "${target.tokens.collectFirst { + case OfModule(m) => m + }.get}" -var "${target.tokens.collectFirst { case Ref(r) => r }.get}"""" } .mkString("\n") + "\n" def verilatorTemplate(data: Seq[Data], annos: AnnotationSeq): String = { val vpiNames = data.flatMap(finalTarget(annos)).map { ct => - s"""TOP.${ct.circuit}.${ct.path.map { case (Instance(i), _) => i }.mkString(".")}.${ct.tokens.collectFirst { case Ref(r) => r }.get}""" + s"""TOP.${ct.circuit}.${ct.path.map { case (Instance(i), _) => i }.mkString(".")}.${ct.tokens.collectFirst { + case Ref(r) => r + }.get}""" } s""" |#include "V${topName}.h" @@ -155,20 +159,34 @@ class TraceSpec extends ChiselFlatSpec with Matchers { val verilog = testDir / s"$topName.v" val cpp = os.temp(dir = testDir, suffix = ".cpp", contents = verilatorTemplate(Seq(dut.m0.o.a.b), annos)) val exe = testDir / "obj_dir" / s"V$topName" - os.proc("verilator", "-Wall", "--cc", "--exe", "--build", "--vpi", s"$cpp", s"$verilog", s"$config").call(stdout = os.Inherit, stderr = os.Inherit, cwd = testDir) - assert(os.proc(s"$exe").call(stdout = os.Inherit, stderr = os.Inherit).exitCode == 0, "verilator should exit peacefully") + os.proc("verilator", "-Wall", "--cc", "--exe", "--build", "--vpi", s"$cpp", s"$verilog", s"$config") + .call(stdout = os.Inherit, stderr = os.Inherit, cwd = testDir) + assert( + os.proc(s"$exe").call(stdout = os.Inherit, stderr = os.Inherit).exitCode == 0, + "verilator should exit peacefully" + ) } "TraceFromCollideBundle" should "work" in { class CollideModule extends Module { - val a = IO(Input(Vec(2, new Bundle { - val b = Flipped(Bool()) - val c = Vec(2, new Bundle { - val d = UInt(2.W) - val e = Flipped(UInt(3.W)) - }) - val c_1_e = UInt(4.W) - }))) + val a = IO( + Input( + Vec( + 2, + new Bundle { + val b = Flipped(Bool()) + val c = Vec( + 2, + new Bundle { + val d = UInt(2.W) + val e = Flipped(UInt(3.W)) + } + ) + val c_1_e = UInt(4.W) + } + ) + ) + ) val a_0_c = IO(Output(UInt(5.W))) val a__0 = IO(Output(UInt(5.W))) a_0_c := DontCare @@ -298,12 +316,14 @@ class TraceSpec extends ChiselFlatSpec with Matchers { val (_, annos) = compile("NestedModule", () => new M) val dut = annos.collectFirst { case DesignAnnotation(dut) => dut }.get.asInstanceOf[M] val allTargets = finalTargetMap(annos) - allTargets(dut.a.toAbsoluteTarget) should be (Seq(refTarget("M", "a"))) - allTargets(dut.b.toAbsoluteTarget) should be (Seq( - refTarget("M", "b_0"), - refTarget("M", "b_1"), - )) - allTargets(dut.b(0).toAbsoluteTarget) should be (Seq(refTarget("M", "b_0"))) - allTargets(dut.b(1).toAbsoluteTarget) should be (Seq(refTarget("M", "b_1"))) + allTargets(dut.a.toAbsoluteTarget) should be(Seq(refTarget("M", "a"))) + allTargets(dut.b.toAbsoluteTarget) should be( + Seq( + refTarget("M", "b_0"), + refTarget("M", "b_1") + ) + ) + allTargets(dut.b(0).toAbsoluteTarget) should be(Seq(refTarget("M", "b_0"))) + allTargets(dut.b(1).toAbsoluteTarget) should be(Seq(refTarget("M", "b_1"))) } } diff --git a/src/test/scala/chiselTests/experimental/Tuple.scala b/src/test/scala/chiselTests/experimental/Tuple.scala index 5f897fbc..b57766e7 100644 --- a/src/test/scala/chiselTests/experimental/Tuple.scala +++ b/src/test/scala/chiselTests/experimental/Tuple.scala @@ -9,7 +9,7 @@ import chisel3.stage.ChiselStage class TupleSpec extends ChiselFlatSpec { - behavior of "Tuple" + behavior.of("Tuple") it should "enable using Tuple2 like Data" in { class MyModule extends Module { @@ -20,8 +20,8 @@ class TupleSpec extends ChiselFlatSpec { } // Verilog instead of CHIRRTL because the optimizations make it much prettier val verilog = ChiselStage.emitVerilog(new MyModule) - verilog should include ("assign y = sel ? a : c;") - verilog should include ("assign z = sel ? b : d;") + verilog should include("assign y = sel ? a : c;") + verilog should include("assign z = sel ? b : d;") } it should "support nesting of tuples" in { @@ -31,10 +31,10 @@ class TupleSpec extends ChiselFlatSpec { ((w, x), (y, z)) := ((a, b), (c, d)) } val chirrtl = ChiselStage.emitChirrtl(new MyModule) - chirrtl should include ("w <= a") - chirrtl should include ("x <= b") - chirrtl should include ("y <= c") - chirrtl should include ("z <= d") + chirrtl should include("w <= a") + chirrtl should include("x <= b") + chirrtl should include("y <= c") + chirrtl should include("z <= d") } it should "enable using Tuple3 like Data" in { @@ -47,9 +47,9 @@ class TupleSpec extends ChiselFlatSpec { } // Verilog instead of CHIRRTL because the optimizations make it much prettier val verilog = ChiselStage.emitVerilog(new MyModule) - verilog should include ("assign v = sel ? a : f;") - verilog should include ("assign w = sel ? b : g;") - verilog should include ("assign x = sel ? c : h;") + verilog should include("assign v = sel ? a : f;") + verilog should include("assign w = sel ? b : g;") + verilog should include("assign x = sel ? c : h;") } it should "enable using Tuple4 like Data" in { @@ -62,10 +62,10 @@ class TupleSpec extends ChiselFlatSpec { } // Verilog instead of CHIRRTL because the optimizations make it much prettier val verilog = ChiselStage.emitVerilog(new MyModule) - verilog should include ("assign v = sel ? a : f;") - verilog should include ("assign w = sel ? b : g;") - verilog should include ("assign x = sel ? c : h;") - verilog should include ("assign y = sel ? d : i;") + verilog should include("assign v = sel ? a : f;") + verilog should include("assign w = sel ? b : g;") + verilog should include("assign x = sel ? c : h;") + verilog should include("assign y = sel ? d : i;") } it should "enable using Tuple5 like Data" in { diff --git a/src/test/scala/chiselTests/experimental/hierarchy/Annotations.scala b/src/test/scala/chiselTests/experimental/hierarchy/Annotations.scala index eba412f1..2c1d2e9e 100644 --- a/src/test/scala/chiselTests/experimental/hierarchy/Annotations.scala +++ b/src/test/scala/chiselTests/experimental/hierarchy/Annotations.scala @@ -5,20 +5,22 @@ package chiselTests.experimental.hierarchy import _root_.firrtl.annotations._ import chisel3.experimental.{annotate, BaseModule} import chisel3.Data -import chisel3.experimental.hierarchy.{Instance, Definition, Hierarchy} +import chisel3.experimental.hierarchy.{Definition, Hierarchy, Instance} object Annotations { case class MarkAnnotation(target: IsMember, tag: String) extends SingleTargetAnnotation[IsMember] { def duplicate(n: IsMember): Annotation = this.copy(target = n) } - case class MarkChiselHierarchyAnnotation[B <: BaseModule](d: Hierarchy[B], tag: String, isAbsolute: Boolean) extends chisel3.experimental.ChiselAnnotation { + case class MarkChiselHierarchyAnnotation[B <: BaseModule](d: Hierarchy[B], tag: String, isAbsolute: Boolean) + extends chisel3.experimental.ChiselAnnotation { def toFirrtl = MarkAnnotation(d.toTarget, tag) } - case class MarkChiselAnnotation(d: Data, tag: String, isAbsolute: Boolean) extends chisel3.experimental.ChiselAnnotation { - def toFirrtl = if(isAbsolute) MarkAnnotation(d.toAbsoluteTarget, tag) else MarkAnnotation(d.toTarget, tag) + case class MarkChiselAnnotation(d: Data, tag: String, isAbsolute: Boolean) + extends chisel3.experimental.ChiselAnnotation { + def toFirrtl = if (isAbsolute) MarkAnnotation(d.toAbsoluteTarget, tag) else MarkAnnotation(d.toTarget, tag) } - def mark(d: Data, tag: String): Unit = annotate(MarkChiselAnnotation(d, tag, false)) - def mark[B <: BaseModule](d: Hierarchy[B], tag: String): Unit = annotate(MarkChiselHierarchyAnnotation(d, tag, true)) - def amark(d: Data, tag: String): Unit = annotate(MarkChiselAnnotation(d, tag, true)) + def mark(d: Data, tag: String): Unit = annotate(MarkChiselAnnotation(d, tag, false)) + def mark[B <: BaseModule](d: Hierarchy[B], tag: String): Unit = annotate(MarkChiselHierarchyAnnotation(d, tag, true)) + def amark(d: Data, tag: String): Unit = annotate(MarkChiselAnnotation(d, tag, true)) def amark[B <: BaseModule](d: Hierarchy[B], tag: String): Unit = annotate(MarkChiselHierarchyAnnotation(d, tag, true)) } diff --git a/src/test/scala/chiselTests/experimental/hierarchy/DefinitionSpec.scala b/src/test/scala/chiselTests/experimental/hierarchy/DefinitionSpec.scala index f33f7869..63beb394 100644 --- a/src/test/scala/chiselTests/experimental/hierarchy/DefinitionSpec.scala +++ b/src/test/scala/chiselTests/experimental/hierarchy/DefinitionSpec.scala @@ -5,7 +5,7 @@ package experimental.hierarchy import chisel3._ import chisel3.experimental.BaseModule -import chisel3.experimental.hierarchy.{Definition, Instance, instantiable, public} +import chisel3.experimental.hierarchy.{instantiable, public, Definition, Instance} // TODO/Notes // - In backport, clock/reset are not automatically assigned. I think this is fixed in 3.5 @@ -19,7 +19,7 @@ class DefinitionSpec extends ChiselFunSpec with Utils { val definition = Definition(new AddOne) } val (chirrtl, _) = getFirrtlAndAnnos(new Top) - chirrtl.serialize should include ("module AddOne :") + chirrtl.serialize should include("module AddOne :") } it("0.2: accessing internal fields through non-generated means is hard to do") { class Top extends Module { @@ -29,7 +29,7 @@ class DefinitionSpec extends ChiselFunSpec with Utils { definition.in } val (chirrtl, _) = getFirrtlAndAnnos(new Top) - chirrtl.serialize should include ("module AddOne :") + chirrtl.serialize should include("module AddOne :") } it("0.2: reset inference is not defaulted to Bool for definitions") { class Top extends Module with RequireAsyncReset { @@ -38,21 +38,27 @@ class DefinitionSpec extends ChiselFunSpec with Utils { i0.in := 0.U } val (chirrtl, _) = getFirrtlAndAnnos(new Top) - chirrtl.serialize should include ("inst i0 of HasUninferredReset") + chirrtl.serialize should include("inst i0 of HasUninferredReset") } it("0.3: module names of repeated definition should be sequential") { class Top extends Module { - val k = Module(new AddTwoParameterized(4, (x: Int) => Seq.tabulate(x){j => - val addOneDef = Definition(new AddOneParameterized(x+j)) - val addOne = Instance(addOneDef) - addOne - })) + val k = Module( + new AddTwoParameterized( + 4, + (x: Int) => + Seq.tabulate(x) { j => + val addOneDef = Definition(new AddOneParameterized(x + j)) + val addOne = Instance(addOneDef) + addOne + } + ) + ) } val (chirrtl, _) = getFirrtlAndAnnos(new Top) - chirrtl.serialize should include ("module AddOneParameterized :") - chirrtl.serialize should include ("module AddOneParameterized_1 :") - chirrtl.serialize should include ("module AddOneParameterized_2 :") - chirrtl.serialize should include ("module AddOneParameterized_3 :") + chirrtl.serialize should include("module AddOneParameterized :") + chirrtl.serialize should include("module AddOneParameterized_1 :") + chirrtl.serialize should include("module AddOneParameterized_2 :") + chirrtl.serialize should include("module AddOneParameterized_3 :") } it("0.4: multiple instantiations should have sequential names") { class Top extends Module { @@ -61,22 +67,28 @@ class DefinitionSpec extends ChiselFunSpec with Utils { val otherAddOne = Module(new AddOneParameterized(4)) } val (chirrtl, _) = getFirrtlAndAnnos(new Top) - chirrtl.serialize should include ("module AddOneParameterized :") - chirrtl.serialize should include ("module AddOneParameterized_1 :") + chirrtl.serialize should include("module AddOneParameterized :") + chirrtl.serialize should include("module AddOneParameterized_1 :") } it("0.5: nested definitions should have sequential names") { class Top extends Module { - val k = Module(new AddTwoWithNested(4, (x: Int) => Seq.tabulate(x){j => - val addOneDef = Definition(new AddOneWithNested(x+j)) - val addOne = Instance(addOneDef) - addOne - })) + val k = Module( + new AddTwoWithNested( + 4, + (x: Int) => + Seq.tabulate(x) { j => + val addOneDef = Definition(new AddOneWithNested(x + j)) + val addOne = Instance(addOneDef) + addOne + } + ) + ) } val (chirrtl, _) = getFirrtlAndAnnos(new Top) - chirrtl.serialize should include ("module AddOneWithNested :") - chirrtl.serialize should include ("module AddOneWithNested_1 :") - chirrtl.serialize should include ("module AddOneWithNested_2 :") - chirrtl.serialize should include ("module AddOneWithNested_3 :") + chirrtl.serialize should include("module AddOneWithNested :") + chirrtl.serialize should include("module AddOneWithNested_1 :") + chirrtl.serialize should include("module AddOneWithNested_2 :") + chirrtl.serialize should include("module AddOneWithNested_3 :") } } describe("1: Annotations on definitions in same chisel compilation") { @@ -179,7 +191,7 @@ class DefinitionSpec extends ChiselFunSpec with Utils { val (_, annos) = getFirrtlAndAnnos(new Top) annos should contain(MarkAnnotation("~Top|AddOneWithInstantiableInstantiable/i0:AddOne".it, "i0.i0")) } - it("1.10: should work for targets on definition to have correct circuit name"){ + it("1.10: should work for targets on definition to have correct circuit name") { class Top extends Module { val definition = Definition(new AddOneWithAnnotation) } @@ -307,6 +319,16 @@ class DefinitionSpec extends ChiselFunSpec with Utils { val (_, annos) = getFirrtlAndAnnos(new Top) annos should contain(MarkAnnotation("~Top|ConcreteHasBlah".mt, "10")) } + it("3.11: should work on eithers") { + class Top() extends Module { + val i = Definition(new HasEither()) + i.x.map(x => mark(x, "xright")).left.map(x => mark(x, "xleft")) + i.y.map(x => mark(x, "yright")).left.map(x => mark(x, "yleft")) + } + val (_, annos) = getFirrtlAndAnnos(new Top) + annos should contain(MarkAnnotation("~Top|HasEither>x".rt, "xright")) + annos should contain(MarkAnnotation("~Top|HasEither>y".rt, "yleft")) + } } describe("4: toDefinition") { it("4.0: should work on modules") { @@ -401,10 +423,12 @@ class DefinitionSpec extends ChiselFunSpec with Utils { ) val (chirrtl, annos) = getFirrtlAndAnnos(new Top) for (e <- expected.map(MarkAnnotation.tupled)) { - annos should contain (e) + annos should contain(e) } } - it("6.1 An @instantiable Module that implements an @instantiable trait should be able to use extension methods from both") { + it( + "6.1 An @instantiable Module that implements an @instantiable trait should be able to use extension methods from both" + ) { class Top extends Module { val i: Definition[ModuleWithCommonIntf] = Definition(new ModuleWithCommonIntf) mark(i.io.in, "gotcha") @@ -418,7 +442,7 @@ class DefinitionSpec extends ChiselFunSpec with Utils { ) val (chirrtl, annos) = getFirrtlAndAnnos(new Top) for (e <- expected.map(MarkAnnotation.tupled)) { - annos should contain (e) + annos should contain(e) } } it("6.2 A BlackBox that implements an @instantiable trait should be instantiable as that trait") { @@ -434,7 +458,7 @@ class DefinitionSpec extends ChiselFunSpec with Utils { ) val (chirrtl, annos) = getFirrtlAndAnnos(new Top) for (e <- expected.map(MarkAnnotation.tupled)) { - annos should contain (e) + annos should contain(e) } } it("6.3 It should be possible to have Vectors of @instantiable traits mixing concrete subclasses") { @@ -456,7 +480,7 @@ class DefinitionSpec extends ChiselFunSpec with Utils { ) val (chirrtl, annos) = getFirrtlAndAnnos(new Top) for (e <- expected.map(MarkAnnotation.tupled)) { - annos should contain (e) + annos should contain(e) } } } @@ -495,10 +519,10 @@ class DefinitionSpec extends ChiselFunSpec with Utils { val (chirrtl, annos) = getFirrtlAndAnnos(new Top) val text = chirrtl.serialize for (line <- expectedLines) { - text should include (line) + text should include(line) } for (e <- expectedAnnos.map(MarkAnnotation.tupled)) { - annos should contain (e) + annos should contain(e) } } ignore("7.1: should work on Aggregate Views that are mapped 1:1") { @@ -523,7 +547,7 @@ class DefinitionSpec extends ChiselFunSpec with Utils { } val expectedAnnos = List( "~Top|MyModule>a".rt -> "in", - "~Top|MyModule>a.foo".rt -> "in_bar", + "~Top|MyModule>a.foo".rt -> "in_bar" ) val expectedLines = List( "i.a <= foo", @@ -532,10 +556,10 @@ class DefinitionSpec extends ChiselFunSpec with Utils { val (chirrtl, annos) = getFirrtlAndAnnos(new Top) val text = chirrtl.serialize for (line <- expectedLines) { - text should include (line) + text should include(line) } for (e <- expectedAnnos.map(MarkAnnotation.tupled)) { - annos should contain (e) + annos should contain(e) } } } diff --git a/src/test/scala/chiselTests/experimental/hierarchy/Examples.scala b/src/test/scala/chiselTests/experimental/hierarchy/Examples.scala index c0f504ff..5b78b7cc 100644 --- a/src/test/scala/chiselTests/experimental/hierarchy/Examples.scala +++ b/src/test/scala/chiselTests/experimental/hierarchy/Examples.scala @@ -11,7 +11,7 @@ object Examples { import Annotations._ @instantiable class AddOne extends Module { - @public val in = IO(Input(UInt(32.W))) + @public val in = IO(Input(UInt(32.W))) @public val out = IO(Output(UInt(32.W))) @public val innerWire = Wire(UInt(32.W)) innerWire := in + 1.U @@ -19,7 +19,7 @@ object Examples { } @instantiable class AddOneWithAnnotation extends Module { - @public val in = IO(Input(UInt(32.W))) + @public val in = IO(Input(UInt(32.W))) @public val out = IO(Output(UInt(32.W))) @public val innerWire = Wire(UInt(32.W)) mark(innerWire, "innerWire") @@ -28,7 +28,7 @@ object Examples { } @instantiable class AddOneWithAbsoluteAnnotation extends Module { - @public val in = IO(Input(UInt(32.W))) + @public val in = IO(Input(UInt(32.W))) @public val out = IO(Output(UInt(32.W))) @public val innerWire = Wire(UInt(32.W)) amark(innerWire, "innerWire") @@ -37,12 +37,12 @@ object Examples { } @instantiable class AddOneParameterized(width: Int) extends Module { - @public val in = IO(Input(UInt(width.W))) + @public val in = IO(Input(UInt(width.W))) @public val out = IO(Output(UInt(width.W))) out := in + 1.U } class AddOneWithNested(width: Int) extends Module { - @public val in = IO(Input(UInt(width.W))) + @public val in = IO(Input(UInt(width.W))) @public val out = IO(Output(UInt(width.W))) val addOneDef = Seq.fill(3)(Definition(new AddOne)) out := in + 1.U @@ -50,7 +50,7 @@ object Examples { @instantiable class AddTwo extends Module { - @public val in = IO(Input(UInt(32.W))) + @public val in = IO(Input(UInt(32.W))) @public val out = IO(Output(UInt(32.W))) @public val definition = Definition(new AddOne) @public val i0: Instance[AddOne] = Instance(definition) @@ -61,7 +61,7 @@ object Examples { } @instantiable class AddTwoMixedModules extends Module { - @public val in = IO(Input(UInt(32.W))) + @public val in = IO(Input(UInt(32.W))) @public val out = IO(Output(UInt(32.W))) val definition = Definition(new AddOne) @public val i0: Instance[AddOne] = Instance(definition) @@ -71,24 +71,25 @@ object Examples { out := i1.out } @instantiable - class AddTwoParameterized(width: Int, makeParameterizedOnes: Int => Seq[Instance[AddOneParameterized]]) extends Module { - val in = IO(Input(UInt(width.W))) + class AddTwoParameterized(width: Int, makeParameterizedOnes: Int => Seq[Instance[AddOneParameterized]]) + extends Module { + val in = IO(Input(UInt(width.W))) val out = IO(Output(UInt(width.W))) val addOnes = makeParameterizedOnes(width) addOnes.head.in := in out := addOnes.last.out - addOnes.zip(addOnes.tail).foreach{ case (head, tail) => tail.in := head.out} + addOnes.zip(addOnes.tail).foreach { case (head, tail) => tail.in := head.out } } @instantiable class AddTwoWithNested(width: Int, makeParameterizedOnes: Int => Seq[Instance[AddOneWithNested]]) extends Module { - val in = IO(Input(UInt(width.W))) + val in = IO(Input(UInt(width.W))) val out = IO(Output(UInt(width.W))) val addOnes = makeParameterizedOnes(width) } @instantiable class AddFour extends Module { - @public val in = IO(Input(UInt(32.W))) + @public val in = IO(Input(UInt(32.W))) @public val out = IO(Output(UInt(32.W))) @public val definition = Definition(new AddTwoMixedModules) @public val i0 = Instance(definition) @@ -111,7 +112,7 @@ object Examples { } @instantiable class AddOneWithInstantiableWire extends Module { - @public val in = IO(Input(UInt(32.W))) + @public val in = IO(Input(UInt(32.W))) @public val out = IO(Output(UInt(32.W))) @public val wireContainer = new WireContainer() wireContainer.innerWire := in + 1.U @@ -123,7 +124,7 @@ object Examples { } @instantiable class AddOneWithInstantiableModule extends Module { - @public val in = IO(Input(UInt(32.W))) + @public val in = IO(Input(UInt(32.W))) @public val out = IO(Output(UInt(32.W))) @public val moduleContainer = new AddOneContainer() moduleContainer.i0.in := in @@ -136,7 +137,7 @@ object Examples { } @instantiable class AddOneWithInstantiableInstance extends Module { - @public val in = IO(Input(UInt(32.W))) + @public val in = IO(Input(UInt(32.W))) @public val out = IO(Output(UInt(32.W))) @public val instanceContainer = new AddOneInstanceContainer() instanceContainer.i0.in := in @@ -148,7 +149,7 @@ object Examples { } @instantiable class AddOneWithInstantiableInstantiable extends Module { - @public val in = IO(Input(UInt(32.W))) + @public val in = IO(Input(UInt(32.W))) @public val out = IO(Output(UInt(32.W))) @public val containerContainer = new AddOneContainerContainer() containerContainer.container.i0.in := in @@ -157,12 +158,12 @@ object Examples { @instantiable class Viewer(val y: AddTwo, markPlease: Boolean) { @public val x = y - if(markPlease) mark(x.i0.innerWire, "first") + if (markPlease) mark(x.i0.innerWire, "first") } @instantiable class ViewerParent(val x: AddTwo, markHere: Boolean, markThere: Boolean) extends Module { @public val viewer = new Viewer(x, markThere) - if(markHere) mark(viewer.x.i0.innerWire, "second") + if (markHere) mark(viewer.x.i0.innerWire, "second") } @instantiable class MultiVal() extends Module { @@ -194,6 +195,11 @@ object Examples { @public val x: Option[UInt] = Some(Wire(UInt(3.W))) } @instantiable + class HasEither() extends Module { + @public val x: Either[Bool, UInt] = Right(Wire(UInt(3.W)).suggestName("x")) + @public val y: Either[Bool, UInt] = Left(Wire(Bool()).suggestName("y")) + } + @instantiable class HasVec() extends Module { @public val x = VecInit(1.U, 2.U, 3.U) } @@ -236,4 +242,14 @@ object Examples { class HasTypeParams[D <: Data](d: D) extends Module { @public val blah = Wire(d) } + + @instantiable + class HasMultipleTypeParamsInside extends Module { + val tpDef0 = Definition(new HasTypeParams(Bool())) + val tpDef1 = Definition(new HasTypeParams(UInt(4.W))) + val i00 = Instance(tpDef0) + val i01 = Instance(tpDef0) + val i10 = Instance(tpDef1) + val i11 = Instance(tpDef1) + } } diff --git a/src/test/scala/chiselTests/experimental/hierarchy/InstanceSpec.scala b/src/test/scala/chiselTests/experimental/hierarchy/InstanceSpec.scala index 9ceb9b40..f62d1e49 100644 --- a/src/test/scala/chiselTests/experimental/hierarchy/InstanceSpec.scala +++ b/src/test/scala/chiselTests/experimental/hierarchy/InstanceSpec.scala @@ -5,10 +5,9 @@ package experimental.hierarchy import chisel3._ import chisel3.experimental.BaseModule -import chisel3.experimental.hierarchy.{Definition, Instance, instantiable, public} +import chisel3.experimental.hierarchy.{instantiable, public, Definition, Instance} import chisel3.util.{DecoupledIO, Valid} - // TODO/Notes // - In backport, clock/reset are not automatically assigned. I think this is fixed in 3.5 // - CircuitTarget for annotations on the definition are wrong - needs to be fixed. @@ -22,7 +21,7 @@ class InstanceSpec extends ChiselFunSpec with Utils { val i0 = Instance(definition) } val (chirrtl, _) = getFirrtlAndAnnos(new Top) - chirrtl.serialize should include ("inst i0 of AddOne") + chirrtl.serialize should include("inst i0 of AddOne") } it("0.1: name of an instanceclone should not error") { class Top extends Module { @@ -31,7 +30,7 @@ class InstanceSpec extends ChiselFunSpec with Utils { val i = i0.i0 // This should not error } val (chirrtl, _) = getFirrtlAndAnnos(new Top) - chirrtl.serialize should include ("inst i0 of AddTwo") + chirrtl.serialize should include("inst i0 of AddTwo") } it("0.2: accessing internal fields through non-generated means is hard to do") { class Top extends Module { @@ -42,63 +41,63 @@ class InstanceSpec extends ChiselFunSpec with Utils { i0.in } val (chirrtl, _) = getFirrtlAndAnnos(new Top) - chirrtl.serialize should include ("inst i0 of AddOne") + chirrtl.serialize should include("inst i0 of AddOne") } } describe("1: Annotations on instances in same chisel compilation") { it("1.0: should work on a single instance, annotating the instance") { class Top extends Module { val definition: Definition[AddOne] = Definition(new AddOne) - val i0: Instance[AddOne] = Instance(definition) + val i0: Instance[AddOne] = Instance(definition) mark(i0, "i0") } val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain (MarkAnnotation("~Top|Top/i0:AddOne".it, "i0")) + annos should contain(MarkAnnotation("~Top|Top/i0:AddOne".it, "i0")) } it("1.1: should work on a single instance, annotating an inner wire") { class Top extends Module { val definition: Definition[AddOne] = Definition(new AddOne) - val i0: Instance[AddOne] = Instance(definition) + val i0: Instance[AddOne] = Instance(definition) mark(i0.innerWire, "i0.innerWire") } val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain (MarkAnnotation("~Top|Top/i0:AddOne>innerWire".rt, "i0.innerWire")) + annos should contain(MarkAnnotation("~Top|Top/i0:AddOne>innerWire".rt, "i0.innerWire")) } it("1.2: should work on a two nested instances, annotating the instance") { class Top extends Module { val definition: Definition[AddTwo] = Definition(new AddTwo) - val i0: Instance[AddTwo] = Instance(definition) + val i0: Instance[AddTwo] = Instance(definition) mark(i0.i0, "i0.i0") } val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain (MarkAnnotation("~Top|Top/i0:AddTwo/i0:AddOne".it, "i0.i0")) + annos should contain(MarkAnnotation("~Top|Top/i0:AddTwo/i0:AddOne".it, "i0.i0")) } it("1.3: should work on a two nested instances, annotating the inner wire") { class Top extends Module { val definition: Definition[AddTwo] = Definition(new AddTwo) - val i0: Instance[AddTwo] = Instance(definition) + val i0: Instance[AddTwo] = Instance(definition) mark(i0.i0.innerWire, "i0.i0.innerWire") } val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain (MarkAnnotation("~Top|Top/i0:AddTwo/i0:AddOne>innerWire".rt, "i0.i0.innerWire")) + annos should contain(MarkAnnotation("~Top|Top/i0:AddTwo/i0:AddOne>innerWire".rt, "i0.i0.innerWire")) } it("1.4: should work on a nested module in an instance, annotating the module") { class Top extends Module { val definition: Definition[AddTwoMixedModules] = Definition(new AddTwoMixedModules) - val i0: Instance[AddTwoMixedModules] = Instance(definition) + val i0: Instance[AddTwoMixedModules] = Instance(definition) mark(i0.i1, "i0.i1") } val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain (MarkAnnotation("~Top|Top/i0:AddTwoMixedModules/i1:AddOne_1".it, "i0.i1")) + annos should contain(MarkAnnotation("~Top|Top/i0:AddTwoMixedModules/i1:AddOne_1".it, "i0.i1")) } it("1.5: should work on an instantiable container, annotating a wire") { class Top extends Module { val definition: Definition[AddOneWithInstantiableWire] = Definition(new AddOneWithInstantiableWire) - val i0: Instance[AddOneWithInstantiableWire] = Instance(definition) + val i0: Instance[AddOneWithInstantiableWire] = Instance(definition) mark(i0.wireContainer.innerWire, "i0.innerWire") } val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain (MarkAnnotation("~Top|Top/i0:AddOneWithInstantiableWire>innerWire".rt, "i0.innerWire")) + annos should contain(MarkAnnotation("~Top|Top/i0:AddOneWithInstantiableWire>innerWire".rt, "i0.innerWire")) } it("1.6: should work on an instantiable container, annotating a module") { class Top extends Module { @@ -107,7 +106,7 @@ class InstanceSpec extends ChiselFunSpec with Utils { mark(i0.moduleContainer.i0, "i0.i0") } val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain (MarkAnnotation("~Top|Top/i0:AddOneWithInstantiableModule/i0:AddOne".it, "i0.i0")) + annos should contain(MarkAnnotation("~Top|Top/i0:AddOneWithInstantiableModule/i0:AddOne".it, "i0.i0")) } it("1.7: should work on an instantiable container, annotating an instance") { class Top extends Module { @@ -116,7 +115,7 @@ class InstanceSpec extends ChiselFunSpec with Utils { mark(i0.instanceContainer.i0, "i0.i0") } val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain (MarkAnnotation("~Top|Top/i0:AddOneWithInstantiableInstance/i0:AddOne".it, "i0.i0")) + annos should contain(MarkAnnotation("~Top|Top/i0:AddOneWithInstantiableInstance/i0:AddOne".it, "i0.i0")) } it("1.8: should work on an instantiable container, annotating an instantiable container's module") { class Top extends Module { @@ -125,7 +124,7 @@ class InstanceSpec extends ChiselFunSpec with Utils { mark(i0.containerContainer.container.i0, "i0.i0") } val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain (MarkAnnotation("~Top|Top/i0:AddOneWithInstantiableInstantiable/i0:AddOne".it, "i0.i0")) + annos should contain(MarkAnnotation("~Top|Top/i0:AddOneWithInstantiableInstantiable/i0:AddOne".it, "i0.i0")) } it("1.9: should work on public member which references public member of another instance") { class Top extends Module { @@ -134,24 +133,24 @@ class InstanceSpec extends ChiselFunSpec with Utils { mark(i0.containerContainer.container.i0, "i0.i0") } val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain (MarkAnnotation("~Top|Top/i0:AddOneWithInstantiableInstantiable/i0:AddOne".it, "i0.i0")) + annos should contain(MarkAnnotation("~Top|Top/i0:AddOneWithInstantiableInstantiable/i0:AddOne".it, "i0.i0")) } - it("1.10: should work for targets on definition to have correct circuit name"){ + it("1.10: should work for targets on definition to have correct circuit name") { class Top extends Module { val definition = Definition(new AddOneWithAnnotation) val i0 = Instance(definition) } val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain (MarkAnnotation("~Top|AddOneWithAnnotation>innerWire".rt, "innerWire")) + annos should contain(MarkAnnotation("~Top|AddOneWithAnnotation>innerWire".rt, "innerWire")) } - it("1.11: should work on things with type parameters"){ + it("1.11: should work on things with type parameters") { class Top extends Module { val definition = Definition(new HasTypeParams[UInt](UInt(3.W))) val i0 = Instance(definition) mark(i0.blah, "blah") } val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain (MarkAnnotation("~Top|Top/i0:HasTypeParams>blah".rt, "blah")) + annos should contain(MarkAnnotation("~Top|Top/i0:HasTypeParams>blah".rt, "blah")) } } describe("2: Annotations on designs not in the same chisel compilation") { @@ -161,7 +160,7 @@ class InstanceSpec extends ChiselFunSpec with Utils { val parent = Instance(Definition(new ViewerParent(x, false, true))) } val (_, annos) = getFirrtlAndAnnos(new Top(first)) - annos should contain (MarkAnnotation("~AddTwo|AddTwo/i0:AddOne>innerWire".rt, "first")) + annos should contain(MarkAnnotation("~AddTwo|AddTwo/i0:AddOne>innerWire".rt, "first")) } it("2.1: should work on an innerWire, marked in a different compilation, in instanced instantiable") { val first = elaborateAndGetModule(new AddTwo) @@ -169,7 +168,7 @@ class InstanceSpec extends ChiselFunSpec with Utils { val parent = Instance(Definition(new ViewerParent(x, true, false))) } val (_, annos) = getFirrtlAndAnnos(new Top(first)) - annos should contain (MarkAnnotation("~AddTwo|AddTwo/i0:AddOne>innerWire".rt, "second")) + annos should contain(MarkAnnotation("~AddTwo|AddTwo/i0:AddOne>innerWire".rt, "second")) } it("2.2: should work on an innerWire, marked in a different compilation, in instanced module") { val first = elaborateAndGetModule(new AddTwo) @@ -178,7 +177,7 @@ class InstanceSpec extends ChiselFunSpec with Utils { mark(parent.viewer.x.i0.innerWire, "third") } val (_, annos) = getFirrtlAndAnnos(new Top(first)) - annos should contain (MarkAnnotation("~AddTwo|AddTwo/i0:AddOne>innerWire".rt, "third")) + annos should contain(MarkAnnotation("~AddTwo|AddTwo/i0:AddOne>innerWire".rt, "third")) } } describe("3: @public") { @@ -188,7 +187,7 @@ class InstanceSpec extends ChiselFunSpec with Utils { mark(mv.x, "mv.x") } val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain (MarkAnnotation("~Top|Top/mv:MultiVal>x".rt, "mv.x")) + annos should contain(MarkAnnotation("~Top|Top/mv:MultiVal>x".rt, "mv.x")) } it("3.1: should work on lazy vals") { class Top() extends Module { @@ -196,7 +195,7 @@ class InstanceSpec extends ChiselFunSpec with Utils { mark(lv.x, lv.y) } val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain (MarkAnnotation("~Top|Top/lv:LazyVal>x".rt, "Hi")) + annos should contain(MarkAnnotation("~Top|Top/lv:LazyVal>x".rt, "Hi")) } it("3.2: should work on islookupables") { class Top() extends Module { @@ -275,10 +274,10 @@ class InstanceSpec extends ChiselFunSpec with Utils { val (chirrtl, annos) = getFirrtlAndAnnos(new Top) val text = chirrtl.serialize for (line <- lines) { - text should include (line) + text should include(line) } for (e <- expected.map(MarkAnnotation.tupled)) { - annos should contain (e) + annos should contain(e) } } ignore("3.10: should work on vals in constructor arguments") { @@ -289,6 +288,16 @@ class InstanceSpec extends ChiselFunSpec with Utils { val (_, annos) = getFirrtlAndAnnos(new Top) annos should contain(MarkAnnotation("~Top|Top/i:HasPublicConstructorArgs>x".rt, "10")) } + it("3.11: should work on eithers") { + class Top() extends Module { + val i = Instance(Definition(new HasEither())) + i.x.map(x => mark(x, "xright")).left.map(x => mark(x, "xleft")) + i.y.map(x => mark(x, "yright")).left.map(x => mark(x, "yleft")) + } + val (_, annos) = getFirrtlAndAnnos(new Top) + annos should contain(MarkAnnotation("~Top|Top/i:HasEither>x".rt, "xright")) + annos should contain(MarkAnnotation("~Top|Top/i:HasEither>y".rt, "yleft")) + } } describe("4: toInstance") { it("4.0: should work on modules") { @@ -398,7 +407,7 @@ class InstanceSpec extends ChiselFunSpec with Utils { val (_, annos) = getFirrtlAndAnnos(new Top) annos should contain(MarkAnnotation("~Top|Top/i:AddTwo/i1:AddOne".it, "blah")) } - it("5.6: should work for absolute targets on definition to have correct circuit name"){ + it("5.6: should work for absolute targets on definition to have correct circuit name") { class Top extends Module { val definition = Definition(new AddOneWithAbsoluteAnnotation) val i0 = Instance(definition) @@ -437,10 +446,12 @@ class InstanceSpec extends ChiselFunSpec with Utils { ) val (chirrtl, annos) = getFirrtlAndAnnos(new Top) for (e <- expected.map(MarkAnnotation.tupled)) { - annos should contain (e) + annos should contain(e) } } - it("6.1 An @instantiable Module that implements an @instantiable trait should be able to use extension methods from both") { + it( + "6.1 An @instantiable Module that implements an @instantiable trait should be able to use extension methods from both" + ) { class Top extends Module { val i: Instance[ModuleWithCommonIntf] = Instance(Definition(new ModuleWithCommonIntf)) mark(i.io.in, "gotcha") @@ -454,7 +465,7 @@ class InstanceSpec extends ChiselFunSpec with Utils { ) val (chirrtl, annos) = getFirrtlAndAnnos(new Top) for (e <- expected.map(MarkAnnotation.tupled)) { - annos should contain (e) + annos should contain(e) } } it("6.2 A BlackBox that implements an @instantiable trait should be instantiable as that trait") { @@ -469,7 +480,7 @@ class InstanceSpec extends ChiselFunSpec with Utils { ) val (chirrtl, annos) = getFirrtlAndAnnos(new Top) for (e <- expected.map(MarkAnnotation.tupled)) { - annos should contain (e) + annos should contain(e) } } it("6.3 It should be possible to have Vectors of @instantiable traits mixing concrete subclasses") { @@ -491,7 +502,7 @@ class InstanceSpec extends ChiselFunSpec with Utils { ) val (chirrtl, annos) = getFirrtlAndAnnos(new Top) for (e <- expected.map(MarkAnnotation.tupled)) { - annos should contain (e) + annos should contain(e) } } } @@ -530,10 +541,10 @@ class InstanceSpec extends ChiselFunSpec with Utils { val (chirrtl, annos) = getFirrtlAndAnnos(new Top) val text = chirrtl.serialize for (line <- expectedLines) { - text should include (line) + text should include(line) } for (e <- expectedAnnos.map(MarkAnnotation.tupled)) { - annos should contain (e) + annos should contain(e) } } @@ -578,15 +589,15 @@ class InstanceSpec extends ChiselFunSpec with Utils { "bar.valid <= i.b.valid", "i.b.ready <= bar.ready", "bar.bits.fizz <= i.b.fizz", - "bar.bits.buzz <= i.b.buzz", + "bar.bits.buzz <= i.b.buzz" ) val (chirrtl, annos) = getFirrtlAndAnnos(new Top) val text = chirrtl.serialize for (line <- expectedLines) { - text should include (line) + text should include(line) } for (e <- expectedAnnos.map(MarkAnnotation.tupled)) { - annos should contain (e) + annos should contain(e) } } @@ -612,7 +623,7 @@ class InstanceSpec extends ChiselFunSpec with Utils { } val expected = List( "~Top|Top/i:MyModule>a".rt -> "in", - "~Top|Top/i:MyModule>b.foo".rt -> "out_bar", + "~Top|Top/i:MyModule>b.foo".rt -> "out_bar" ) val lines = List( "i.a <= foo", @@ -621,10 +632,10 @@ class InstanceSpec extends ChiselFunSpec with Utils { val (chirrtl, annos) = getFirrtlAndAnnos(new Top) val text = chirrtl.serialize for (line <- lines) { - text should include (line) + text should include(line) } for (e <- expected.map(MarkAnnotation.tupled)) { - annos should contain (e) + annos should contain(e) } } @@ -647,7 +658,7 @@ class InstanceSpec extends ChiselFunSpec with Utils { val expected = List( // Not 1:1 so will get split out "~Top|Top/i:MyModule>a".rt -> "i.ports", - "~Top|Top/i:MyModule>b".rt -> "i.ports", + "~Top|Top/i:MyModule>b".rt -> "i.ports" ) val lines = List( "i.a <= foo", @@ -656,10 +667,10 @@ class InstanceSpec extends ChiselFunSpec with Utils { val (chirrtl, annos) = getFirrtlAndAnnos(new Top) val text = chirrtl.serialize for (line <- lines) { - text should include (line) + text should include(line) } for (e <- expected.map(MarkAnnotation.tupled)) { - annos should contain (e) + annos should contain(e) } } } @@ -682,11 +693,10 @@ class InstanceSpec extends ChiselFunSpec with Utils { val expected = List( "~Top|HasCMAR/c:AggregatePortModule>io".rt -> "c.io", "~Top|HasCMAR/c:AggregatePortModule>io.out".rt -> "c.io.out" - ) val (_, annos) = getFirrtlAndAnnos(new Top) for (e <- expected.map(MarkAnnotation.tupled)) { - annos should contain (e) + annos should contain(e) } } it("8.1: it should support @public on a CMAR Record in Instances") { @@ -706,11 +716,10 @@ class InstanceSpec extends ChiselFunSpec with Utils { val expected = List( "~Top|Top/i:HasCMAR/c:AggregatePortModule>io".rt -> "i.c.io", "~Top|Top/i:HasCMAR/c:AggregatePortModule>io.out".rt -> "i.c.io.out" - ) val (_, annos) = getFirrtlAndAnnos(new Top) for (e <- expected.map(MarkAnnotation.tupled)) { - annos should contain (e) + annos should contain(e) } } } @@ -754,15 +763,27 @@ class InstanceSpec extends ChiselFunSpec with Utils { } getFirrtlAndAnnos(new Top) } + it("9.3 it should ignore type parameters (even though it would be nice if it didn't)") { + class Top extends Module { + val d0: Definition[Module] = Definition(new HasTypeParams(Bool())) + require(d0.isA[HasTypeParams[Bool]]) + require(d0.isA[HasTypeParams[_]]) + require(d0.isA[HasTypeParams[UInt]]) + require(!d0.isA[HasBlah]) + } + getFirrtlAndAnnos(new Top) + } } describe("10: Select APIs") { it("10.0: instancesOf") { val aspect = aop.inspecting.InspectingAspect({ m: AddTwoMixedModules => val targets = aop.Select.instancesOf[AddOne](m.toDefinition).map { i: Instance[AddOne] => i.toTarget } - targets should be (Seq( - "~AddTwoMixedModules|AddTwoMixedModules/i0:AddOne".it, - "~AddTwoMixedModules|AddTwoMixedModules/i1:AddOne_1".it, - )) + targets should be( + Seq( + "~AddTwoMixedModules|AddTwoMixedModules/i0:AddOne".it, + "~AddTwoMixedModules|AddTwoMixedModules/i1:AddOne_1".it + ) + ) }) getFirrtlAndAnnos(new AddTwoMixedModules, Seq(aspect)) } @@ -771,14 +792,18 @@ class InstanceSpec extends ChiselFunSpec with Utils { val insts = aop.Select.instancesIn(m.toDefinition) val abs = insts.map { i: Instance[BaseModule] => i.toAbsoluteTarget } val rel = insts.map { i: Instance[BaseModule] => i.toTarget } - abs should be (Seq( - "~AddTwoMixedModules|AddTwoMixedModules/i0:AddOne".it, - "~AddTwoMixedModules|AddTwoMixedModules/i1:AddOne_1".it, - )) - rel should be (Seq( - "~AddTwoMixedModules|AddTwoMixedModules/i0:AddOne".it, - "~AddTwoMixedModules|AddTwoMixedModules/i1:AddOne_1".it, - )) + abs should be( + Seq( + "~AddTwoMixedModules|AddTwoMixedModules/i0:AddOne".it, + "~AddTwoMixedModules|AddTwoMixedModules/i1:AddOne_1".it + ) + ) + rel should be( + Seq( + "~AddTwoMixedModules|AddTwoMixedModules/i0:AddOne".it, + "~AddTwoMixedModules|AddTwoMixedModules/i1:AddOne_1".it + ) + ) }) getFirrtlAndAnnos(new AddTwoMixedModules, Seq(aspect)) } @@ -787,48 +812,58 @@ class InstanceSpec extends ChiselFunSpec with Utils { val insts = aop.Select.allInstancesOf[AddOne](m.toDefinition) val abs = insts.map { i: Instance[AddOne] => i.in.toAbsoluteTarget } val rel = insts.map { i: Instance[AddOne] => i.in.toTarget } - rel should be (Seq( - "~AddFour|AddFour/i0:AddTwoMixedModules/i0:AddOne>in".rt, - "~AddFour|AddFour/i0:AddTwoMixedModules/i1:AddOne_1>in".rt, - "~AddFour|AddFour/i1:AddTwoMixedModules/i0:AddOne>in".rt, - "~AddFour|AddFour/i1:AddTwoMixedModules/i1:AddOne_1>in".rt, - )) - abs should be (Seq( - "~AddFour|AddFour/i0:AddTwoMixedModules/i0:AddOne>in".rt, - "~AddFour|AddFour/i0:AddTwoMixedModules/i1:AddOne_1>in".rt, - "~AddFour|AddFour/i1:AddTwoMixedModules/i0:AddOne>in".rt, - "~AddFour|AddFour/i1:AddTwoMixedModules/i1:AddOne_1>in".rt, - )) + rel should be( + Seq( + "~AddFour|AddFour/i0:AddTwoMixedModules/i0:AddOne>in".rt, + "~AddFour|AddFour/i0:AddTwoMixedModules/i1:AddOne_1>in".rt, + "~AddFour|AddFour/i1:AddTwoMixedModules/i0:AddOne>in".rt, + "~AddFour|AddFour/i1:AddTwoMixedModules/i1:AddOne_1>in".rt + ) + ) + abs should be( + Seq( + "~AddFour|AddFour/i0:AddTwoMixedModules/i0:AddOne>in".rt, + "~AddFour|AddFour/i0:AddTwoMixedModules/i1:AddOne_1>in".rt, + "~AddFour|AddFour/i1:AddTwoMixedModules/i0:AddOne>in".rt, + "~AddFour|AddFour/i1:AddTwoMixedModules/i1:AddOne_1>in".rt + ) + ) }) getFirrtlAndAnnos(new AddFour, Seq(aspect)) } it("10.3: definitionsOf") { val aspect = aop.inspecting.InspectingAspect({ m: AddTwoMixedModules => val targets = aop.Select.definitionsOf[AddOne](m.toDefinition).map { i: Definition[AddOne] => i.in.toTarget } - targets should be (Seq( - "~AddTwoMixedModules|AddOne>in".rt, - "~AddTwoMixedModules|AddOne_1>in".rt, - )) + targets should be( + Seq( + "~AddTwoMixedModules|AddOne>in".rt, + "~AddTwoMixedModules|AddOne_1>in".rt + ) + ) }) getFirrtlAndAnnos(new AddTwoMixedModules, Seq(aspect)) } it("10.4: definitionsIn") { val aspect = aop.inspecting.InspectingAspect({ m: AddTwoMixedModules => val targets = aop.Select.definitionsIn(m.toDefinition).map { i: Definition[BaseModule] => i.toTarget } - targets should be (Seq( - "~AddTwoMixedModules|AddOne".mt, - "~AddTwoMixedModules|AddOne_1".mt, - )) + targets should be( + Seq( + "~AddTwoMixedModules|AddOne".mt, + "~AddTwoMixedModules|AddOne_1".mt + ) + ) }) getFirrtlAndAnnos(new AddTwoMixedModules, Seq(aspect)) } it("10.5: allDefinitionsOf") { val aspect = aop.inspecting.InspectingAspect({ m: AddFour => val targets = aop.Select.allDefinitionsOf[AddOne](m.toDefinition).map { i: Definition[AddOne] => i.in.toTarget } - targets should be (Seq( - "~AddFour|AddOne>in".rt, - "~AddFour|AddOne_1>in".rt, - )) + targets should be( + Seq( + "~AddFour|AddOne>in".rt, + "~AddFour|AddOne_1>in".rt + ) + ) }) getFirrtlAndAnnos(new AddFour, Seq(aspect)) } @@ -850,6 +885,141 @@ class InstanceSpec extends ChiselFunSpec with Utils { }) intercept[Exception] { getFirrtlAndAnnos(new AddFour, Seq(aspect)) } } + it("10.9: allInstancesOf.ios") { + val aspect = aop.inspecting.InspectingAspect({ m: AddFour => + val abs = aop.Select.allInstancesOf[AddOne](m.toDefinition).flatMap { i: Instance[AddOne] => + aop.Select.ios(i).map(_.toAbsoluteTarget) + } + val rel = aop.Select.allInstancesOf[AddOne](m.toDefinition).flatMap { i: Instance[AddOne] => + aop.Select.ios(i).map(_.toTarget) + } + abs should be( + Seq( + "~AddFour|AddFour/i0:AddTwoMixedModules/i0:AddOne>clock".rt, + "~AddFour|AddFour/i0:AddTwoMixedModules/i0:AddOne>reset".rt, + "~AddFour|AddFour/i0:AddTwoMixedModules/i0:AddOne>in".rt, + "~AddFour|AddFour/i0:AddTwoMixedModules/i0:AddOne>out".rt, + "~AddFour|AddFour/i0:AddTwoMixedModules/i1:AddOne_1>clock".rt, + "~AddFour|AddFour/i0:AddTwoMixedModules/i1:AddOne_1>reset".rt, + "~AddFour|AddFour/i0:AddTwoMixedModules/i1:AddOne_1>in".rt, + "~AddFour|AddFour/i0:AddTwoMixedModules/i1:AddOne_1>out".rt, + "~AddFour|AddFour/i1:AddTwoMixedModules/i0:AddOne>clock".rt, + "~AddFour|AddFour/i1:AddTwoMixedModules/i0:AddOne>reset".rt, + "~AddFour|AddFour/i1:AddTwoMixedModules/i0:AddOne>in".rt, + "~AddFour|AddFour/i1:AddTwoMixedModules/i0:AddOne>out".rt, + "~AddFour|AddFour/i1:AddTwoMixedModules/i1:AddOne_1>clock".rt, + "~AddFour|AddFour/i1:AddTwoMixedModules/i1:AddOne_1>reset".rt, + "~AddFour|AddFour/i1:AddTwoMixedModules/i1:AddOne_1>in".rt, + "~AddFour|AddFour/i1:AddTwoMixedModules/i1:AddOne_1>out".rt + ) + ) + + rel should be( + Seq( + "~AddFour|AddFour/i0:AddTwoMixedModules/i0:AddOne>clock".rt, + "~AddFour|AddFour/i0:AddTwoMixedModules/i0:AddOne>reset".rt, + "~AddFour|AddFour/i0:AddTwoMixedModules/i0:AddOne>in".rt, + "~AddFour|AddFour/i0:AddTwoMixedModules/i0:AddOne>out".rt, + "~AddFour|AddFour/i0:AddTwoMixedModules/i1:AddOne_1>clock".rt, + "~AddFour|AddFour/i0:AddTwoMixedModules/i1:AddOne_1>reset".rt, + "~AddFour|AddFour/i0:AddTwoMixedModules/i1:AddOne_1>in".rt, + "~AddFour|AddFour/i0:AddTwoMixedModules/i1:AddOne_1>out".rt, + "~AddFour|AddFour/i1:AddTwoMixedModules/i0:AddOne>clock".rt, + "~AddFour|AddFour/i1:AddTwoMixedModules/i0:AddOne>reset".rt, + "~AddFour|AddFour/i1:AddTwoMixedModules/i0:AddOne>in".rt, + "~AddFour|AddFour/i1:AddTwoMixedModules/i0:AddOne>out".rt, + "~AddFour|AddFour/i1:AddTwoMixedModules/i1:AddOne_1>clock".rt, + "~AddFour|AddFour/i1:AddTwoMixedModules/i1:AddOne_1>reset".rt, + "~AddFour|AddFour/i1:AddTwoMixedModules/i1:AddOne_1>in".rt, + "~AddFour|AddFour/i1:AddTwoMixedModules/i1:AddOne_1>out".rt + ) + ) + }) + getFirrtlAndAnnos(new AddFour, Seq(aspect)) + } + it("10.10: allDefinitionsOf.ios") { + val aspect = aop.inspecting.InspectingAspect({ m: AddFour => + val abs = aop.Select.allDefinitionsOf[AddOne](m.toDefinition).flatMap { i: Definition[AddOne] => + aop.Select.ios(i).map(_.toAbsoluteTarget) + } + val rel = aop.Select.allDefinitionsOf[AddOne](m.toDefinition).flatMap { i: Definition[AddOne] => + aop.Select.ios(i).map(_.toTarget) + } + abs should be( + Seq( + "~AddFour|AddOne>clock".rt, + "~AddFour|AddOne>reset".rt, + "~AddFour|AddOne>in".rt, + "~AddFour|AddOne>out".rt, + "~AddFour|AddOne_1>clock".rt, + "~AddFour|AddOne_1>reset".rt, + "~AddFour|AddOne_1>in".rt, + "~AddFour|AddOne_1>out".rt + ) + ) + + rel should be( + Seq( + "~AddFour|AddOne>clock".rt, + "~AddFour|AddOne>reset".rt, + "~AddFour|AddOne>in".rt, + "~AddFour|AddOne>out".rt, + "~AddFour|AddOne_1>clock".rt, + "~AddFour|AddOne_1>reset".rt, + "~AddFour|AddOne_1>in".rt, + "~AddFour|AddOne_1>out".rt + ) + ) + + }) + getFirrtlAndAnnos(new AddFour, Seq(aspect)) + } + it("10.11 Select.instancesIn for typed BaseModules") { + val aspect = aop.inspecting.InspectingAspect({ m: HasMultipleTypeParamsInside => + val targets = aop.Select.instancesIn(m.toDefinition).map { i: Instance[BaseModule] => i.toTarget } + targets should be( + Seq( + "~HasMultipleTypeParamsInside|HasMultipleTypeParamsInside/i00:HasTypeParams".it, + "~HasMultipleTypeParamsInside|HasMultipleTypeParamsInside/i01:HasTypeParams".it, + "~HasMultipleTypeParamsInside|HasMultipleTypeParamsInside/i10:HasTypeParams_1".it, + "~HasMultipleTypeParamsInside|HasMultipleTypeParamsInside/i11:HasTypeParams_1".it + ) + ) + }) + getFirrtlAndAnnos(new HasMultipleTypeParamsInside, Seq(aspect)) + } + it("10.12 Select.instancesOf for typed BaseModules if type is ignored") { + val aspect = aop.inspecting.InspectingAspect({ m: HasMultipleTypeParamsInside => + val targets = + aop.Select.instancesOf[HasTypeParams[_]](m.toDefinition).map { i: Instance[HasTypeParams[_]] => i.toTarget } + targets should be( + Seq( + "~HasMultipleTypeParamsInside|HasMultipleTypeParamsInside/i00:HasTypeParams".it, + "~HasMultipleTypeParamsInside|HasMultipleTypeParamsInside/i01:HasTypeParams".it, + "~HasMultipleTypeParamsInside|HasMultipleTypeParamsInside/i10:HasTypeParams_1".it, + "~HasMultipleTypeParamsInside|HasMultipleTypeParamsInside/i11:HasTypeParams_1".it + ) + ) + }) + getFirrtlAndAnnos(new HasMultipleTypeParamsInside, Seq(aspect)) + } + it( + "10.13 Select.instancesOf for typed BaseModules even type is specified wrongly (should be ignored, even though we wish it weren't)" + ) { + val aspect = aop.inspecting.InspectingAspect({ m: HasMultipleTypeParamsInside => + val targets = aop.Select.instancesOf[HasTypeParams[SInt]](m.toDefinition).map { i: Instance[HasTypeParams[_]] => + i.toTarget + } + targets should be( + Seq( + "~HasMultipleTypeParamsInside|HasMultipleTypeParamsInside/i00:HasTypeParams".it, + "~HasMultipleTypeParamsInside|HasMultipleTypeParamsInside/i01:HasTypeParams".it, + "~HasMultipleTypeParamsInside|HasMultipleTypeParamsInside/i10:HasTypeParams_1".it, + "~HasMultipleTypeParamsInside|HasMultipleTypeParamsInside/i11:HasTypeParams_1".it + ) + ) + }) + getFirrtlAndAnnos(new HasMultipleTypeParamsInside, Seq(aspect)) + } } } - diff --git a/src/test/scala/chiselTests/naming/NamePluginSpec.scala b/src/test/scala/chiselTests/naming/NamePluginSpec.scala index 3a539bd4..18359fd2 100644 --- a/src/test/scala/chiselTests/naming/NamePluginSpec.scala +++ b/src/test/scala/chiselTests/naming/NamePluginSpec.scala @@ -12,20 +12,20 @@ class NamePluginSpec extends ChiselFlatSpec with Utils { "Scala plugin" should "name internally scoped components" in { class Test extends Module { - { val mywire = Wire(UInt(3.W))} + { val mywire = Wire(UInt(3.W)) } } - aspectTest(() => new Test) { - top: Test => Select.wires(top).head.toTarget.ref should be("mywire") + aspectTest(() => new Test) { top: Test => + Select.wires(top).head.toTarget.ref should be("mywire") } } "Scala plugin" should "name internally scoped instances" in { - class Inner extends Module { } + class Inner extends Module {} class Test extends Module { { val myinstance = Module(new Inner) } } - aspectTest(() => new Test) { - top: Test => Select.instances(top).head.instanceName should be("myinstance") + aspectTest(() => new Test) { top: Test => + Select.instances(top).head.instanceName should be("myinstance") } } @@ -41,8 +41,8 @@ class NamePluginSpec extends ChiselFlatSpec with Utils { builder() } } - aspectTest(() => new Test) { - top: Test => Select.wires(top).map(_.instanceName) should be (List("first_wire", "second_wire")) + aspectTest(() => new Test) { top: Test => + Select.wires(top).map(_.instanceName) should be(List("first_wire", "second_wire")) } } @@ -64,8 +64,8 @@ class NamePluginSpec extends ChiselFlatSpec with Utils { } } } - aspectTest(() => new Test) { - top: Test => Select.wires(top).map(_.instanceName) should be (List("x1_first_wire1", "x1", "x2_second_wire1", "x2")) + aspectTest(() => new Test) { top: Test => + Select.wires(top).map(_.instanceName) should be(List("x1_first_wire1", "x1", "x2_second_wire1", "x2")) } } @@ -79,13 +79,11 @@ class NamePluginSpec extends ChiselFlatSpec with Utils { { val blah = builder() } } - aspectTest(() => new Test) { - top: Test => - Select.wires(top).map(_.instanceName) should be (List("blah")) + aspectTest(() => new Test) { top: Test => + Select.wires(top).map(_.instanceName) should be(List("blah")) } } - "Naming on iterables" should "work" in { class Test extends Module { @@ -100,9 +98,8 @@ class NamePluginSpec extends ChiselFlatSpec with Utils { } } } - aspectTest(() => new Test) { - top: Test => - Select.wires(top).map(_.instanceName) should be (List("blah_0", "blah_1")) + aspectTest(() => new Test) { top: Test => + Select.wires(top).map(_.instanceName) should be(List("blah_0", "blah_1")) } } @@ -122,15 +119,15 @@ class NamePluginSpec extends ChiselFlatSpec with Utils { } } } - aspectTest(() => new Test) { - top: Test => - Select.wires(top).map(_.instanceName) should be ( - List( - "blah_0_0", - "blah_0_1", - "blah_1_0", - "blah_1_1" - )) + aspectTest(() => new Test) { top: Test => + Select.wires(top).map(_.instanceName) should be( + List( + "blah_0_0", + "blah_0_1", + "blah_1_0", + "blah_1_1" + ) + ) } } @@ -146,9 +143,8 @@ class NamePluginSpec extends ChiselFlatSpec with Utils { { val blah = builder() } } - aspectTest(() => new Test) { - top: Test => - Select.wires(top).map(_.instanceName) should be (List("a", "b")) + aspectTest(() => new Test) { top: Test => + Select.wires(top).map(_.instanceName) should be(List("a", "b")) } } @@ -160,9 +156,8 @@ class NamePluginSpec extends ChiselFlatSpec with Utils { } } - aspectTest(() => new Test) { - top: Test => - Select.ios(top).map(_.instanceName) should be (List("a")) + aspectTest(() => new Test) { top: Test => + Select.ios(top).map(_.instanceName) should be(List("a")) } } @@ -174,9 +169,8 @@ class NamePluginSpec extends ChiselFlatSpec with Utils { } } - aspectTest(() => new Test) { - top: Test => - Select.wires(top).map(_.instanceName) should be (List("a")) + aspectTest(() => new Test) { top: Test => + Select.wires(top).map(_.instanceName) should be(List("a")) } } @@ -193,9 +187,8 @@ class NamePluginSpec extends ChiselFlatSpec with Utils { } } - aspectTest(() => new Test) { - top: Test => - Select.ios(top).map(_.instanceName) should be (List("out")) + aspectTest(() => new Test) { top: Test => + Select.ios(top).map(_.instanceName) should be(List("out")) } } @@ -212,9 +205,8 @@ class NamePluginSpec extends ChiselFlatSpec with Utils { } } - aspectTest(() => new Test) { - top: Test => - Select.wires(top).map(_.instanceName) should be (List("fizz")) + aspectTest(() => new Test) { top: Test => + Select.wires(top).map(_.instanceName) should be(List("fizz")) } } @@ -226,13 +218,11 @@ class NamePluginSpec extends ChiselFlatSpec with Utils { } } - aspectTest(() => new Test) { - top: Test => - Select.ios(top).map(_.instanceName) should be (List("a")) + aspectTest(() => new Test) { top: Test => + Select.ios(top).map(_.instanceName) should be(List("a")) } } - "autoSeed" should "override automatic naming for non-IO" in { class Test extends Module { { @@ -241,9 +231,8 @@ class NamePluginSpec extends ChiselFlatSpec with Utils { } } - aspectTest(() => new Test) { - top: Test => - Select.wires(top).map(_.instanceName) should be (List("b")) + aspectTest(() => new Test) { top: Test => + Select.wires(top).map(_.instanceName) should be(List("b")) } } @@ -254,9 +243,8 @@ class NamePluginSpec extends ChiselFlatSpec with Utils { } } - aspectTest(() => new Test) { - top: Test => - Select.wires(top).map(_.instanceName) should be (List("a", "b")) + aspectTest(() => new Test) { top: Test => + Select.wires(top).map(_.instanceName) should be(List("a", "b")) } } @@ -268,9 +256,8 @@ class NamePluginSpec extends ChiselFlatSpec with Utils { } } - aspectTest(() => new Test) { - top: Test => - Select.wires(top).map(_.instanceName) should be (List("x", "b")) + aspectTest(() => new Test) { top: Test => + Select.wires(top).map(_.instanceName) should be(List("x", "b")) } } @@ -283,9 +270,8 @@ class NamePluginSpec extends ChiselFlatSpec with Utils { } } - aspectTest(() => new Test) { - top: Test => - Select.wires(top).map(_.instanceName) should be (List("a", "b")) + aspectTest(() => new Test) { top: Test => + Select.wires(top).map(_.instanceName) should be(List("a", "b")) } } @@ -302,9 +288,8 @@ class NamePluginSpec extends ChiselFlatSpec with Utils { } } - aspectTest(() => new Test) { - top: Test => - Select.wires(top).map(_.instanceName) should be (List("w", "a", "_WIRE")) + aspectTest(() => new Test) { top: Test => + Select.wires(top).map(_.instanceName) should be(List("w", "a", "_WIRE")) } } @@ -332,9 +317,8 @@ class NamePluginSpec extends ChiselFlatSpec with Utils { } } - aspectTest(() => new Test) { - top: Test => Select.wires(top).map(_.instanceName) should be (List("a_b_c", "a_b", "a")) + aspectTest(() => new Test) { top: Test => + Select.wires(top).map(_.instanceName) should be(List("a_b_c", "a_b", "a")) } } } - diff --git a/src/test/scala/chiselTests/naming/PrefixSpec.scala b/src/test/scala/chiselTests/naming/PrefixSpec.scala index 0712692d..f9a78f0e 100644 --- a/src/test/scala/chiselTests/naming/PrefixSpec.scala +++ b/src/test/scala/chiselTests/naming/PrefixSpec.scala @@ -28,8 +28,8 @@ class PrefixSpec extends ChiselPropSpec with Utils { } } } - aspectTest(() => new Test) { - top: Test => Select.wires(top).map(_.instanceName) should be (List("x1_first_wire1", "x1", "x2_second_wire1", "x2")) + aspectTest(() => new Test) { top: Test => + Select.wires(top).map(_.instanceName) should be(List("x1_first_wire1", "x1", "x2_second_wire1", "x2")) } } @@ -50,20 +50,19 @@ class PrefixSpec extends ChiselPropSpec with Utils { { val x1 = builder() } { val x2 = builder() } } - aspectTest(() => new Test) { - top: Test => - Select.wires(top).map(_.instanceName) should be ( - List( - "x1_wire1", - "x1_wire2", - "x1_foo_wire1", - "x1", - "x2_wire1", - "x2_wire2", - "x2_foo_wire1", - "x2" - ) + aspectTest(() => new Test) { top: Test => + Select.wires(top).map(_.instanceName) should be( + List( + "x1_wire1", + "x1_wire2", + "x1_foo_wire1", + "x1", + "x2_wire1", + "x2_wire2", + "x2_foo_wire1", + "x2" ) + ) } } @@ -85,9 +84,8 @@ class PrefixSpec extends ChiselPropSpec with Utils { } } } - aspectTest(() => new Test) { - top: Test => - Select.wires(top).map(_.instanceName) should be (List("x1", "x1_wire", "x2", "x2_wire")) + aspectTest(() => new Test) { top: Test => + Select.wires(top).map(_.instanceName) should be(List("x1", "x1_wire", "x2", "x2_wire")) } } @@ -105,9 +103,8 @@ class PrefixSpec extends ChiselPropSpec with Utils { val JACOB = builder() } } - aspectTest(() => new Test) { - top: Test => - Select.wires(top).map(_.instanceName) should be (List("ADAM_a", "ADAM", "JACOB_a", "JACOB")) + aspectTest(() => new Test) { top: Test => + Select.wires(top).map(_.instanceName) should be(List("ADAM_a", "ADAM", "JACOB_a", "JACOB")) } } @@ -122,9 +119,8 @@ class PrefixSpec extends ChiselPropSpec with Utils { { val noprefix = builder() } } - aspectTest(() => new Test) { - top: Test => - Select.wires(top).map(_.instanceName) should be (List("a", "noprefix")) + aspectTest(() => new Test) { top: Test => + Select.wires(top).map(_.instanceName) should be(List("a", "noprefix")) } } @@ -139,12 +135,13 @@ class PrefixSpec extends ChiselPropSpec with Utils { { val blah = builder() } } - aspectTest(() => new Test) { - top: Test => - Select.ops(top).map(x => (x._1, x._2.instanceName)) should be (List( + aspectTest(() => new Test) { top: Test => + Select.ops(top).map(x => (x._1, x._2.instanceName)) should be( + List( ("mul", "_blah_T"), ("add", "blah") - )) + ) + ) } } @@ -162,9 +159,8 @@ class PrefixSpec extends ChiselPropSpec with Utils { } } } - aspectTest(() => new Test) { - top: Test => - Select.wires(Select.instances(top).head).map(_.instanceName) should be (List("wire")) + aspectTest(() => new Test) { top: Test => + Select.wires(Select.instances(top).head).map(_.instanceName) should be(List("wire")) } } @@ -182,9 +178,8 @@ class PrefixSpec extends ChiselPropSpec with Utils { val child = Module(module) } } - aspectTest(() => new Test) { - top: Test => - Select.wires(Select.instances(top).head).map(_.instanceName) should be (List("wire")) + aspectTest(() => new Test) { top: Test => + Select.wires(Select.instances(top).head).map(_.instanceName) should be(List("wire")) } } @@ -204,13 +199,11 @@ class PrefixSpec extends ChiselPropSpec with Utils { val child = Module(module) } } - aspectTest(() => new Test) { - top: Test => - Select.ios(Select.instances(top).head).map(_.instanceName) should be (List("clock", "reset", "io")) + aspectTest(() => new Test) { top: Test => + Select.ios(Select.instances(top).head).map(_.instanceName) should be(List("clock", "reset", "io")) } } - property("Prefixing should not be caused by nested Iterable[Iterable[Any]]") { class Test extends Module { { @@ -220,9 +213,8 @@ class PrefixSpec extends ChiselPropSpec with Utils { } } } - aspectTest(() => new Test) { - top: Test => - Select.wires(top).map(_.instanceName) should be (List("wire")) + aspectTest(() => new Test) { top: Test => + Select.wires(top).map(_.instanceName) should be(List("wire")) } } @@ -235,9 +227,8 @@ class PrefixSpec extends ChiselPropSpec with Utils { } } } - aspectTest(() => new Test) { - top: Test => - Select.wires(top).map(_.instanceName) should be (List("iia_wire")) + aspectTest(() => new Test) { top: Test => + Select.wires(top).map(_.instanceName) should be(List("iia_wire")) } } @@ -250,10 +241,9 @@ class PrefixSpec extends ChiselPropSpec with Utils { } } } - aspectTest(() => new Test) { - top: Test => - Select.wires(top).map(_.instanceName) should be (List("mywire")) - Select.wires(top).map(_.instanceName) shouldNot be (List("wire_mywire")) + aspectTest(() => new Test) { top: Test => + Select.wires(top).map(_.instanceName) should be(List("mywire")) + Select.wires(top).map(_.instanceName) shouldNot be(List("wire_mywire")) } } @@ -268,8 +258,8 @@ class PrefixSpec extends ChiselPropSpec with Utils { } } } - aspectTest(() => new Test) { - top: Test => Select.wires(top).map(_.instanceName) should be (List("wire_mywire", "mywire2")) + aspectTest(() => new Test) { top: Test => + Select.wires(top).map(_.instanceName) should be(List("wire_mywire", "mywire2")) } } @@ -288,15 +278,16 @@ class PrefixSpec extends ChiselPropSpec with Utils { wire.vec(1.U) := RegNext(3.U) } } - aspectTest(() => new Test) { - top: Test => - Select.registers(top).map(_.instanceName) should be (List( + aspectTest(() => new Test) { top: Test => + Select.registers(top).map(_.instanceName) should be( + List( "wire_x_REG", "wire_y_REG", "wire_vec_0_REG", "wire_vec_REG", "wire_vec_1_REG" - )) + ) + ) } } @@ -312,14 +303,17 @@ class PrefixSpec extends ChiselPropSpec with Utils { child.in := RegNext(3.U) } } - aspectTest(() => new Test) { - top: Test => - Select.registers(top).map(_.instanceName) should be (List( + aspectTest(() => new Test) { top: Test => + Select.registers(top).map(_.instanceName) should be( + List( "child_in_REG" - )) - Select.registers(Select.instances(top).head).map(_.instanceName) should be (List( + ) + ) + Select.registers(Select.instances(top).head).map(_.instanceName) should be( + List( "out_REG" - )) + ) + ) } } @@ -335,14 +329,17 @@ class PrefixSpec extends ChiselPropSpec with Utils { child.in <> RegNext(3.U) } } - aspectTest(() => new Test) { - top: Test => - Select.registers(top).map(_.instanceName) should be (List( + aspectTest(() => new Test) { top: Test => + Select.registers(top).map(_.instanceName) should be( + List( "child_in_REG" - )) - Select.registers(Select.instances(top).head).map(_.instanceName) should be (List( + ) + ) + Select.registers(Select.instances(top).head).map(_.instanceName) should be( + List( "out_REG" - )) + ) + ) } } @@ -357,9 +354,8 @@ class PrefixSpec extends ChiselPropSpec with Utils { } } } - aspectTest(() => new Test) { - top: Test => - Select.wires(top).map(_.instanceName) should be (List("foo_x", "foo_x_w")) + aspectTest(() => new Test) { top: Test => + Select.wires(top).map(_.instanceName) should be(List("foo_x", "foo_x_w")) } } @@ -374,13 +370,11 @@ class PrefixSpec extends ChiselPropSpec with Utils { } } } - aspectTest(() => new Test) { - top: Test => - Select.wires(top).map(_.instanceName) should be (List("foo_x", "foo_x_bar_w")) + aspectTest(() => new Test) { top: Test => + Select.wires(top).map(_.instanceName) should be(List("foo_x", "foo_x_bar_w")) } } - property("Prefixing with wires in recursive functions should grow linearly") { class Test extends Module { def func(bools: Seq[Bool]): Bool = { @@ -394,9 +388,8 @@ class PrefixSpec extends ChiselPropSpec with Utils { val in = IO(Input(Vec(4, Bool()))) val x = func(in) } - aspectTest(() => new Test) { - top: Test => - Select.wires(top).map(_.instanceName) should be (List("x", "x_w_w", "x_w_w_w", "x_w_w_w_w")) + aspectTest(() => new Test) { top: Test => + Select.wires(top).map(_.instanceName) should be(List("x", "x_w_w", "x_w_w_w", "x_w_w_w_w")) } } diff --git a/src/test/scala/chiselTests/stage/ChiselAnnotationsSpec.scala b/src/test/scala/chiselTests/stage/ChiselAnnotationsSpec.scala index 2d804562..9dac820c 100644 --- a/src/test/scala/chiselTests/stage/ChiselAnnotationsSpec.scala +++ b/src/test/scala/chiselTests/stage/ChiselAnnotationsSpec.scala @@ -27,41 +27,41 @@ class ChiselAnnotation class ChiselAnnotationsSpec extends AnyFlatSpec with Matchers { - behavior of "ChiselGeneratorAnnotation elaboration" + behavior.of("ChiselGeneratorAnnotation elaboration") it should "elaborate to a ChiselCircuitAnnotation" in { val annotation = ChiselGeneratorAnnotation(() => new ChiselAnnotationsSpecFoo) val res = annotation.elaborate - res(0) shouldBe a [ChiselCircuitAnnotation] - res(1) shouldBe a [DesignAnnotation[ChiselAnnotationsSpecFoo]] + res(0) shouldBe a[ChiselCircuitAnnotation] + res(1) shouldBe a[DesignAnnotation[ChiselAnnotationsSpecFoo]] } it should "throw an exception if elaboration fails" in { val annotation = ChiselGeneratorAnnotation(() => new ChiselAnnotationsSpecQux) - intercept [ChiselException] { annotation.elaborate } + intercept[ChiselException] { annotation.elaborate } } - behavior of "ChiselGeneratorAnnotation when stringly constructing from Module names" + behavior.of("ChiselGeneratorAnnotation when stringly constructing from Module names") it should "elaborate from a String" in { val annotation = ChiselGeneratorAnnotation("chiselTests.stage.ChiselAnnotationsSpecFoo") val res = annotation.elaborate - res(0) shouldBe a [ChiselCircuitAnnotation] - res(1) shouldBe a [DesignAnnotation[ChiselAnnotationsSpecFoo]] + res(0) shouldBe a[ChiselCircuitAnnotation] + res(1) shouldBe a[DesignAnnotation[ChiselAnnotationsSpecFoo]] } it should "throw an exception if elaboration from a String refers to nonexistant class" in { val bar = "chiselTests.stage.ChiselAnnotationsSpecBar" val annotation = ChiselGeneratorAnnotation(bar) - intercept [OptionsException] { annotation.elaborate } - .getMessage should startWith (s"Unable to locate module '$bar'") + intercept[OptionsException] { annotation.elaborate }.getMessage should startWith(s"Unable to locate module '$bar'") } it should "throw an exception if elaboration from a String refers to an anonymous class" in { val baz = "chiselTests.stage.ChiselAnnotationsSpecBaz" val annotation = ChiselGeneratorAnnotation(baz) - intercept [OptionsException] { annotation.elaborate } - .getMessage should startWith (s"Unable to create instance of module '$baz'") + intercept[OptionsException] { annotation.elaborate }.getMessage should startWith( + s"Unable to create instance of module '$baz'" + ) } } diff --git a/src/test/scala/chiselTests/stage/ChiselMainSpec.scala b/src/test/scala/chiselTests/stage/ChiselMainSpec.scala index 1634e765..e8773111 100644 --- a/src/test/scala/chiselTests/stage/ChiselMainSpec.scala +++ b/src/test/scala/chiselTests/stage/ChiselMainSpec.scala @@ -44,13 +44,15 @@ object ChiselMainSpec { } } -case class TestClassAspect() extends InspectorAspect[RawModule] ({ - _: RawModule => println("Ran inspectingAspect") -}) +case class TestClassAspect() + extends InspectorAspect[RawModule]({ _: RawModule => + println("Ran inspectingAspect") + }) -case object TestObjectAspect extends InspectorAspect[RawModule] ({ - _: RawModule => println("Ran inspectingAspect") -}) +case object TestObjectAspect + extends InspectorAspect[RawModule]({ _: RawModule => + println("Ran inspectingAspect") + }) class ChiselMainSpec extends AnyFeatureSpec with GivenWhenThen with Matchers with chiselTests.Utils { @@ -68,14 +70,14 @@ class ChiselMainSpec extends AnyFeatureSpec with GivenWhenThen with Matchers wit } case class ChiselMainTest( - args: Array[String], - generator: Option[Class[_ <: RawModule]] = None, - files: Seq[String] = Seq.empty, - stdout: Seq[Either[String, String]] = Seq.empty, - stderr: Seq[Either[String, String]] = Seq.empty, - result: Int = 0, + args: Array[String], + generator: Option[Class[_ <: RawModule]] = None, + files: Seq[String] = Seq.empty, + stdout: Seq[Either[String, String]] = Seq.empty, + stderr: Seq[Either[String, String]] = Seq.empty, + result: Int = 0, fileChecks: Map[String, File => Unit] = Map.empty) { - def testName: String = "args" + args.mkString("_") + def testName: String = "args" + args.mkString("_") def argsString: String = args.mkString(" ") } @@ -89,14 +91,13 @@ class ChiselMainSpec extends AnyFeatureSpec with GivenWhenThen with Matchers wit * @tparam the type of exception that should occur */ case class ChiselMainExceptionTest[A <: Throwable]( - args: Array[String], - generator: Option[Class[_ <: RawModule]] = None, - message: Seq[Either[String, String]] = Seq.empty, - stdout: Seq[Either[String, String]] = Seq.empty, - stderr: Seq[Either[String, String]] = Seq.empty, - stackTrace: Seq[Either[String, String]] = Seq.empty - ) { - def testName: String = "args" + args.mkString("_") + args: Array[String], + generator: Option[Class[_ <: RawModule]] = None, + message: Seq[Either[String, String]] = Seq.empty, + stdout: Seq[Either[String, String]] = Seq.empty, + stderr: Seq[Either[String, String]] = Seq.empty, + stackTrace: Seq[Either[String, String]] = Seq.empty) { + def testName: String = "args" + args.mkString("_") def argsString: String = args.mkString(" ") } @@ -105,12 +106,12 @@ class ChiselMainSpec extends AnyFeatureSpec with GivenWhenThen with Matchers wit val f = new ChiselMainFixture val td = new TargetDirectoryFixture(p.testName) - p.files.foreach( f => new File(td.buildDir + s"/$f").delete() ) + p.files.foreach(f => new File(td.buildDir + s"/$f").delete()) When(s"""the user tries to compile with '${p.argsString}'""") val module: Array[String] = (if (p.generator.nonEmpty) { Array("--module", p.generator.get.getName) } - else { Array.empty[String] }) + else { Array.empty[String] }) f.stage.main(Array("-td", td.buildDir.toString) ++ module ++ p.args) val (stdout, stderr, result) = grabStdOutErr { @@ -122,25 +123,25 @@ class ChiselMainSpec extends AnyFeatureSpec with GivenWhenThen with Matchers wit p.stdout.foreach { case Right(a) => Then(s"""STDOUT should include "$a"""") - stdout should include (a) + stdout should include(a) case Left(a) => Then(s"""STDOUT should not include "$a"""") - stdout should not include (a) + (stdout should not).include(a) } p.stderr.foreach { case Right(a) => Then(s"""STDERR should include "$a"""") - stderr should include (a) + stderr should include(a) case Left(a) => Then(s"""STDERR should not include "$a"""") - stderr should not include (a) + (stderr should not).include(a) } p.result match { case 0 => And(s"the exit code should be 0") - result shouldBe a [Right[_,_]] + result shouldBe a[Right[_, _]] case a => And(s"the exit code should be $a") result shouldBe (Left(a)) @@ -167,7 +168,7 @@ class ChiselMainSpec extends AnyFeatureSpec with GivenWhenThen with Matchers wit When(s"""the user tries to compile with '${p.argsString}'""") val module: Array[String] = (if (p.generator.nonEmpty) { Array("--module", p.generator.get.getName) } - else { Array.empty[String] }) + else { Array.empty[String] }) val (stdout, stderr, result) = grabStdOutErr { catchStatus { @@ -178,7 +179,7 @@ class ChiselMainSpec extends AnyFeatureSpec with GivenWhenThen with Matchers wit } Then("the expected exception was thrown") - result should be a ('right) + (result should be).a('right) val exception = result.right.get info(s""" - Exception was a "${exception.getClass.getName}"""") @@ -186,38 +187,38 @@ class ChiselMainSpec extends AnyFeatureSpec with GivenWhenThen with Matchers wit p.message.foreach { case Right(a) => Then(s"""STDOUT should include "$a"""") - message should include (a) + message should include(a) case Left(a) => Then(s"""STDOUT should not include "$a"""") - message should not include (a) + (message should not).include(a) } p.stdout.foreach { case Right(a) => Then(s"""STDOUT should include "$a"""") - stdout should include (a) + stdout should include(a) case Left(a) => Then(s"""STDOUT should not include "$a"""") - stdout should not include (a) + (stdout should not).include(a) } p.stderr.foreach { case Right(a) => Then(s"""STDERR should include "$a"""") - stderr should include (a) + stderr should include(a) case Left(a) => Then(s"""STDERR should not include "$a"""") - stderr should not include (a) + (stderr should not).include(a) } val stackTraceString = exception.getStackTrace.mkString("\n") p.stackTrace.foreach { case Left(a) => And(s"""the stack does not include "$a"""") - stackTraceString should not include (a) + (stackTraceString should not).include(a) case Right(a) => And(s"""the stack trace includes "$a"""") - stackTraceString should include (a) + stackTraceString should include(a) } } @@ -227,9 +228,7 @@ class ChiselMainSpec extends AnyFeatureSpec with GivenWhenThen with Matchers wit info("I compile a design") Feature("show elaborating message") { runStageExpectFiles( - ChiselMainTest(args = Array("-X", "high"), - generator = Some(classOf[SameTypesModule]) - ) + ChiselMainTest(args = Array("-X", "high"), generator = Some(classOf[SameTypesModule])) ) } @@ -268,46 +267,58 @@ class ChiselMainSpec extends AnyFeatureSpec with GivenWhenThen with Matchers wit args = Array("-X", "low"), generator = Some(classOf[BuilderErrorModule]), message = Seq(Right("Fatal errors during hardware elaboration")), - stdout = Seq(Right("ChiselMainSpec.scala:43: Invalid bit range (3,-1) in class chiselTests.stage.ChiselMainSpec$BuilderErrorModule")) + stdout = Seq( + Right( + "ChiselMainSpec.scala:43: Invalid bit range (3,-1) in class chiselTests.stage.ChiselMainSpec$BuilderErrorModule" + ) + ) ) ).foreach(runStageExpectException) } Feature("Specifying a custom output file") { - runStageExpectFiles(ChiselMainTest( - args = Array("--chisel-output-file", "Foo", "--no-run-firrtl"), - generator = Some(classOf[SameTypesModule]), - files = Seq("Foo.fir"), - fileChecks = Map( - "Foo.fir" -> { file => - And("It should be valid FIRRTL") - Parser.parse(Source.fromFile(file).mkString) - } + runStageExpectFiles( + ChiselMainTest( + args = Array("--chisel-output-file", "Foo", "--no-run-firrtl"), + generator = Some(classOf[SameTypesModule]), + files = Seq("Foo.fir"), + fileChecks = Map( + "Foo.fir" -> { file => + And("It should be valid FIRRTL") + Parser.parse(Source.fromFile(file).mkString) + } + ) ) - )) - runStageExpectFiles(ChiselMainTest( - args = Array("--chisel-output-file", "Foo.pb", "--no-run-firrtl"), - generator = Some(classOf[SameTypesModule]), - files = Seq("Foo.pb"), - fileChecks = Map( - "Foo.pb" -> { file => - And("It should be valid ProtoBuf") - firrtl.proto.FromProto.fromFile(file.toString) - } + ) + runStageExpectFiles( + ChiselMainTest( + args = Array("--chisel-output-file", "Foo.pb", "--no-run-firrtl"), + generator = Some(classOf[SameTypesModule]), + files = Seq("Foo.pb"), + fileChecks = Map( + "Foo.pb" -> { file => + And("It should be valid ProtoBuf") + firrtl.proto.FromProto.fromFile(file.toString) + } + ) ) - )) + ) } info("As an aspect writer") info("I write an aspect") Feature("Running aspects via the command line") { Seq( - ChiselMainTest(args = Array( "-X", "high", "--with-aspect", "chiselTests.stage.TestClassAspect" ), + ChiselMainTest( + args = Array("-X", "high", "--with-aspect", "chiselTests.stage.TestClassAspect"), generator = Some(classOf[SameTypesModule]), - stdout = Seq(Right("Ran inspectingAspect"))), - ChiselMainTest(args = Array( "-X", "high", "--with-aspect", "chiselTests.stage.TestObjectAspect" ), + stdout = Seq(Right("Ran inspectingAspect")) + ), + ChiselMainTest( + args = Array("-X", "high", "--with-aspect", "chiselTests.stage.TestObjectAspect"), generator = Some(classOf[SameTypesModule]), - stdout = Seq(Right("Ran inspectingAspect"))) + stdout = Seq(Right("Ran inspectingAspect")) + ) ).foreach(runStageExpectFiles) } diff --git a/src/test/scala/chiselTests/stage/ChiselOptionsViewSpec.scala b/src/test/scala/chiselTests/stage/ChiselOptionsViewSpec.scala index 99c0f7c0..b164ff20 100644 --- a/src/test/scala/chiselTests/stage/ChiselOptionsViewSpec.scala +++ b/src/test/scala/chiselTests/stage/ChiselOptionsViewSpec.scala @@ -2,7 +2,6 @@ package chiselTests.stage - import firrtl.options.Viewer.view import firrtl.RenameMap @@ -13,7 +12,7 @@ import org.scalatest.matchers.should.Matchers class ChiselOptionsViewSpec extends AnyFlatSpec with Matchers { - behavior of ChiselOptionsView.getClass.getName + behavior.of(ChiselOptionsView.getClass.getName) it should "construct a view from an AnnotationSeq" in { val bar = Circuit("bar", Seq.empty, Seq.empty, RenameMap()) @@ -26,16 +25,16 @@ class ChiselOptionsViewSpec extends AnyFlatSpec with Matchers { val out = view[ChiselOptions](annotations) info("runFirrtlCompiler was set to false") - out.runFirrtlCompiler should be (false) + out.runFirrtlCompiler should be(false) info("printFullStackTrace was set to true") - out.printFullStackTrace should be (true) + out.printFullStackTrace should be(true) info("outputFile was set to 'foo'") - out.outputFile should be (Some("foo")) + out.outputFile should be(Some("foo")) info("chiselCircuit was set to circuit 'bar'") - out.chiselCircuit should be (Some(bar)) + out.chiselCircuit should be(Some(bar)) } diff --git a/src/test/scala/chiselTests/stage/ChiselStageSpec.scala b/src/test/scala/chiselTests/stage/ChiselStageSpec.scala index 7b6a2d39..e88a2385 100644 --- a/src/test/scala/chiselTests/stage/ChiselStageSpec.scala +++ b/src/test/scala/chiselTests/stage/ChiselStageSpec.scala @@ -44,44 +44,44 @@ class ChiselStageSpec extends AnyFlatSpec with Matchers with Utils { val stage = new ChiselStage } - behavior of "ChiselStage$.emitChirrtl" + behavior.of("ChiselStage$.emitChirrtl") it should "return a CHIRRTL string" in { - ChiselStage.emitChirrtl(new Foo) should include ("infer mport") + ChiselStage.emitChirrtl(new Foo) should include("infer mport") } - behavior of "ChiselStage$.emitFirrtl" + behavior.of("ChiselStage$.emitFirrtl") it should "return a High FIRRTL string" in { - ChiselStage.emitFirrtl(new Foo) should include ("mem memory") + ChiselStage.emitFirrtl(new Foo) should include("mem memory") } it should "return a flattened FIRRTL string with '-e high'" in { val args = Array("-e", "high", "-td", createTestDirectory(this.getClass.getSimpleName).toString) (new ChiselStage) - .emitFirrtl(new Foo, args) should include ("module Bar") + .emitFirrtl(new Foo, args) should include("module Bar") } - behavior of "ChiselStage$.emitVerilog" + behavior.of("ChiselStage$.emitVerilog") it should "return a Verilog string" in { - ChiselStage.emitVerilog(new Foo) should include ("endmodule") + ChiselStage.emitVerilog(new Foo) should include("endmodule") } it should "return a flattened Verilog string with '-e verilog'" in { val args = Array("-e", "verilog", "-td", createTestDirectory(this.getClass.getSimpleName).toString) (new ChiselStage) - .emitVerilog(new Foo, args) should include ("module Bar") + .emitVerilog(new Foo, args) should include("module Bar") } - behavior of "ChiselStage$.elaborate" + behavior.of("ChiselStage$.elaborate") ignore should "generate a Chisel circuit from a Chisel module" in { info("no files were written") catchWrites { ChiselStage.elaborate(new Foo) } shouldBe a[Right[_, _]] } - behavior of "ChiselStage$.convert" + behavior.of("ChiselStage$.convert") ignore should "generate a CHIRRTL circuit from a Chisel module" in { info("no files were written") @@ -95,7 +95,7 @@ class ChiselStageSpec extends AnyFlatSpec with Matchers with Utils { } shouldBe a[Right[_, _]] } - behavior of "ChiselStage$.emitChirrtl" + behavior.of("ChiselStage$.emitChirrtl") ignore should "generate a CHIRRTL string from a Chisel module" in { val wrapped = catchWrites { ChiselStage.emitChirrtl(new Foo) } @@ -104,10 +104,10 @@ class ChiselStageSpec extends AnyFlatSpec with Matchers with Utils { wrapped shouldBe a[Right[_, _]] info("returned string looks like FIRRTL") - wrapped.right.get should include ("circuit") + wrapped.right.get should include("circuit") } - behavior of "ChiselStage$.emitFirrtl" + behavior.of("ChiselStage$.emitFirrtl") ignore should "generate a FIRRTL string from a Chisel module" in { val wrapped = catchWrites { ChiselStage.emitFirrtl(new Foo) } @@ -116,10 +116,10 @@ class ChiselStageSpec extends AnyFlatSpec with Matchers with Utils { wrapped shouldBe a[Right[_, _]] info("returned string looks like FIRRTL") - wrapped.right.get should include ("circuit") + wrapped.right.get should include("circuit") } - behavior of "ChiselStage$.emitVerilog" + behavior.of("ChiselStage$.emitVerilog") ignore should "generate a Verilog string from a Chisel module" in { val wrapped = catchWrites { ChiselStage.emitVerilog(new Foo) } @@ -128,10 +128,10 @@ class ChiselStageSpec extends AnyFlatSpec with Matchers with Utils { wrapped shouldBe a[Right[_, _]] info("returned string looks like Verilog") - wrapped.right.get should include ("endmodule") + wrapped.right.get should include("endmodule") } - behavior of "ChiselStage$.emitSystemVerilog" + behavior.of("ChiselStage$.emitSystemVerilog") ignore should "generate a SystemvVerilog string from a Chisel module" in { val wrapped = catchWrites { ChiselStage.emitSystemVerilog(new Foo) } @@ -139,10 +139,10 @@ class ChiselStageSpec extends AnyFlatSpec with Matchers with Utils { wrapped shouldBe a[Right[_, _]] info("returned string looks like Verilog") - wrapped.right.get should include ("endmodule") + wrapped.right.get should include("endmodule") } - behavior of "ChiselStage phase ordering" + behavior.of("ChiselStage phase ordering") it should "only run elaboration once" in new ChiselStageFixture { info("Phase order is:\n" + stage.phaseManager.prettyPrint(" ")) @@ -150,10 +150,10 @@ class ChiselStageSpec extends AnyFlatSpec with Matchers with Utils { val order = stage.phaseManager.flattenedTransformOrder.map(Dependency.fromTransform) info("Elaborate only runs once") - exactly (1, order) should be (Dependency[chisel3.stage.phases.Elaborate]) + exactly(1, order) should be(Dependency[chisel3.stage.phases.Elaborate]) } - behavior of "ChiselStage$ exception handling" + behavior.of("ChiselStage$ exception handling") it should "truncate a user exception" in { info("The user's java.lang.AssertionError was thrown") @@ -163,13 +163,13 @@ class ChiselStageSpec extends AnyFlatSpec with Matchers with Utils { val message = exception.getMessage info("The exception includes the user's message") - message should include ("User threw an exception") + message should include("User threw an exception") info("The stack trace is trimmed") - exception.getStackTrace.mkString("\n") should not include ("java") + (exception.getStackTrace.mkString("\n") should not).include("java") } - behavior of "ChiselStage exception handling" + behavior.of("ChiselStage exception handling") it should "truncate a user exception" in { info("The user's java.lang.AssertionError was thrown") @@ -181,14 +181,14 @@ class ChiselStageSpec extends AnyFlatSpec with Matchers with Utils { val message = exception.getMessage info("The exception includes the user's message") - message should include ("User threw an exception") + message should include("User threw an exception") val stackTrace = exception.getStackTrace.mkString("\n") info("The stack trace is trimmed") - stackTrace should not include ("java") + (stackTrace should not).include("java") info("The stack trace include information about running --full-stacktrace") - stackTrace should include ("--full-stacktrace") + stackTrace should include("--full-stacktrace") } it should """not truncate a user exception with "--full-stacktrace"""" in { @@ -201,10 +201,10 @@ class ChiselStageSpec extends AnyFlatSpec with Matchers with Utils { val message = exception.getMessage info("The exception includes the user's message") - message should include ("User threw an exception") + message should include("User threw an exception") info("The stack trace is not trimmed") - exception.getStackTrace.mkString("\n") should include ("java") + exception.getStackTrace.mkString("\n") should include("java") } } diff --git a/src/test/scala/chiselTests/stage/phases/AddImplicitOutputAnnotationFileSpec.scala b/src/test/scala/chiselTests/stage/phases/AddImplicitOutputAnnotationFileSpec.scala index 63ac7bbe..faf411ed 100644 --- a/src/test/scala/chiselTests/stage/phases/AddImplicitOutputAnnotationFileSpec.scala +++ b/src/test/scala/chiselTests/stage/phases/AddImplicitOutputAnnotationFileSpec.scala @@ -2,7 +2,6 @@ package chiselTests.stage.phases - import chisel3.RawModule import chisel3.stage.ChiselGeneratorAnnotation import chisel3.stage.phases.{AddImplicitOutputAnnotationFile, Elaborate} @@ -18,26 +17,25 @@ class AddImplicitOutputAnnotationFileSpec extends AnyFlatSpec with Matchers { class Fixture { val phase: Phase = new AddImplicitOutputAnnotationFile } - behavior of classOf[AddImplicitOutputAnnotationFile].toString + behavior.of(classOf[AddImplicitOutputAnnotationFile].toString) it should "not override an existing OutputAnnotationFileAnnotation" in new Fixture { - val annotations: AnnotationSeq = Seq( - ChiselGeneratorAnnotation(() => new Foo), - OutputAnnotationFileAnnotation("Bar") ) + val annotations: AnnotationSeq = + Seq(ChiselGeneratorAnnotation(() => new Foo), OutputAnnotationFileAnnotation("Bar")) - Seq( new Elaborate, phase ) + Seq(new Elaborate, phase) .foldLeft(annotations)((a, p) => p.transform(a)) - .collect{ case a: OutputAnnotationFileAnnotation => a.file } - .toSeq should be (Seq("Bar")) + .collect { case a: OutputAnnotationFileAnnotation => a.file } + .toSeq should be(Seq("Bar")) } it should "generate an OutputAnnotationFileAnnotation from a ChiselCircuitAnnotation" in new Fixture { - val annotations: AnnotationSeq = Seq( ChiselGeneratorAnnotation(() => new Foo) ) + val annotations: AnnotationSeq = Seq(ChiselGeneratorAnnotation(() => new Foo)) - Seq( new Elaborate, phase ) + Seq(new Elaborate, phase) .foldLeft(annotations)((a, p) => p.transform(a)) - .collect{ case a: OutputAnnotationFileAnnotation => a.file } - .toSeq should be (Seq("Foo")) + .collect { case a: OutputAnnotationFileAnnotation => a.file } + .toSeq should be(Seq("Foo")) } } diff --git a/src/test/scala/chiselTests/stage/phases/AddImplicitOutputFileSpec.scala b/src/test/scala/chiselTests/stage/phases/AddImplicitOutputFileSpec.scala index e8ba390e..20274e7a 100644 --- a/src/test/scala/chiselTests/stage/phases/AddImplicitOutputFileSpec.scala +++ b/src/test/scala/chiselTests/stage/phases/AddImplicitOutputFileSpec.scala @@ -2,7 +2,6 @@ package chiselTests.stage.phases - import chisel3.RawModule import chisel3.stage.{ChiselGeneratorAnnotation, ChiselOutputFileAnnotation} import chisel3.stage.phases.{AddImplicitOutputFile, Elaborate} @@ -19,32 +18,28 @@ class AddImplicitOutputFileSpec extends AnyFlatSpec with Matchers { class Fixture { val phase: Phase = new AddImplicitOutputFile } - behavior of classOf[AddImplicitOutputFile].toString + behavior.of(classOf[AddImplicitOutputFile].toString) it should "not override an existing ChiselOutputFileAnnotation" in new Fixture { - val annotations: AnnotationSeq = Seq( - ChiselGeneratorAnnotation(() => new Foo), - ChiselOutputFileAnnotation("Bar") ) + val annotations: AnnotationSeq = Seq(ChiselGeneratorAnnotation(() => new Foo), ChiselOutputFileAnnotation("Bar")) - Seq( new Elaborate, phase ) + Seq(new Elaborate, phase) .foldLeft(annotations)((a, p) => p.transform(a)) - .collect{ case a: ChiselOutputFileAnnotation => a.file } - .toSeq should be (Seq("Bar")) + .collect { case a: ChiselOutputFileAnnotation => a.file } + .toSeq should be(Seq("Bar")) } it should "generate a ChiselOutputFileAnnotation from a ChiselCircuitAnnotation" in new Fixture { - val annotations: AnnotationSeq = Seq( - ChiselGeneratorAnnotation(() => new Foo), - TargetDirAnnotation("test_run_dir") ) + val annotations: AnnotationSeq = Seq(ChiselGeneratorAnnotation(() => new Foo), TargetDirAnnotation("test_run_dir")) - Seq( new Elaborate, phase ) + Seq(new Elaborate, phase) .foldLeft(annotations)((a, p) => p.transform(a)) - .collect{ case a: ChiselOutputFileAnnotation => a.file } - .toSeq should be (Seq("Foo")) + .collect { case a: ChiselOutputFileAnnotation => a.file } + .toSeq should be(Seq("Foo")) } it should "do nothing to an empty annotation sequence" in new Fixture { - phase.transform(AnnotationSeq(Seq.empty)).toSeq should be (empty) + phase.transform(AnnotationSeq(Seq.empty)).toSeq should be(empty) } } diff --git a/src/test/scala/chiselTests/stage/phases/AddSerializationAnnotationsSpec.scala b/src/test/scala/chiselTests/stage/phases/AddSerializationAnnotationsSpec.scala index 8bca9ccd..57633eac 100644 --- a/src/test/scala/chiselTests/stage/phases/AddSerializationAnnotationsSpec.scala +++ b/src/test/scala/chiselTests/stage/phases/AddSerializationAnnotationsSpec.scala @@ -2,14 +2,13 @@ package chiselTests.stage.phases - import chisel3.RawModule import chisel3.stage.{ChiselGeneratorAnnotation, ChiselOutputFileAnnotation, CircuitSerializationAnnotation} import chisel3.stage.CircuitSerializationAnnotation._ -import chisel3.stage.phases.{AddSerializationAnnotations, AddImplicitOutputFile, Elaborate} +import chisel3.stage.phases.{AddImplicitOutputFile, AddSerializationAnnotations, Elaborate} import firrtl.AnnotationSeq -import firrtl.options.{Phase, PhaseManager, Dependency, TargetDirAnnotation} +import firrtl.options.{Dependency, Phase, PhaseManager, TargetDirAnnotation} import firrtl.options.Viewer.view import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers @@ -23,39 +22,34 @@ class AddSerializationAnnotationsSpec extends AnyFlatSpec with Matchers { val manager = new PhaseManager(Dependency[AddSerializationAnnotations] :: Nil) } - behavior of classOf[AddSerializationAnnotations].toString + behavior.of(classOf[AddSerializationAnnotations].toString) it should "default to FirrtlFileFormat" in new Fixture { - val annotations: AnnotationSeq = Seq( - ChiselGeneratorAnnotation(() => new Foo), - ChiselOutputFileAnnotation("Bar") ) + val annotations: AnnotationSeq = Seq(ChiselGeneratorAnnotation(() => new Foo), ChiselOutputFileAnnotation("Bar")) manager .transform(annotations) .collect { case CircuitSerializationAnnotation(_, filename, format) => (filename, format) } - .toSeq should be (Seq(("Bar", FirrtlFileFormat))) + .toSeq should be(Seq(("Bar", FirrtlFileFormat))) } it should "support ProtoBufFileFormat" in new Fixture { - val annotations: AnnotationSeq = Seq( - ChiselGeneratorAnnotation(() => new Foo), - ChiselOutputFileAnnotation("Bar.pb") ) + val annotations: AnnotationSeq = Seq(ChiselGeneratorAnnotation(() => new Foo), ChiselOutputFileAnnotation("Bar.pb")) manager .transform(annotations) .collect { case CircuitSerializationAnnotation(_, filename, format) => (filename, format) } - .toSeq should be (Seq(("Bar", ProtoBufFileFormat))) + .toSeq should be(Seq(("Bar", ProtoBufFileFormat))) } it should "support explicitly asking for FirrtlFileFormat" in new Fixture { - val annotations: AnnotationSeq = Seq( - ChiselGeneratorAnnotation(() => new Foo), - ChiselOutputFileAnnotation("Bar.pb.fir") ) + val annotations: AnnotationSeq = + Seq(ChiselGeneratorAnnotation(() => new Foo), ChiselOutputFileAnnotation("Bar.pb.fir")) manager .transform(annotations) .collect { case CircuitSerializationAnnotation(_, filename, format) => (filename, format) } - .toSeq should be (Seq(("Bar.pb", FirrtlFileFormat))) + .toSeq should be(Seq(("Bar.pb", FirrtlFileFormat))) } } diff --git a/src/test/scala/chiselTests/stage/phases/ChecksSpec.scala b/src/test/scala/chiselTests/stage/phases/ChecksSpec.scala index ba9e9254..3d42efdd 100644 --- a/src/test/scala/chiselTests/stage/phases/ChecksSpec.scala +++ b/src/test/scala/chiselTests/stage/phases/ChecksSpec.scala @@ -2,7 +2,6 @@ package chiselTests.stage.phases - import chisel3.stage.{ChiselOutputFileAnnotation, NoRunFirrtlCompilerAnnotation, PrintFullStackTraceAnnotation} import chisel3.stage.phases.Checks @@ -15,15 +14,15 @@ import org.scalatest.matchers.should.Matchers class ChecksSpec extends AnyFlatSpec with Matchers { def checkExceptionMessage(phase: Phase, annotations: AnnotationSeq, messageStart: String): Unit = - intercept[OptionsException]{ phase.transform(annotations) }.getMessage should startWith(messageStart) + intercept[OptionsException] { phase.transform(annotations) }.getMessage should startWith(messageStart) class Fixture { val phase: Phase = new Checks } - behavior of classOf[Checks].toString + behavior.of(classOf[Checks].toString) it should "do nothing on sane annotation sequences" in new Fixture { val a = Seq(NoRunFirrtlCompilerAnnotation, PrintFullStackTraceAnnotation) - phase.transform(a).toSeq should be (a) + phase.transform(a).toSeq should be(a) } it should "throw an OptionsException if more than one NoRunFirrtlCompilerAnnotation is specified" in new Fixture { diff --git a/src/test/scala/chiselTests/stage/phases/ConvertSpec.scala b/src/test/scala/chiselTests/stage/phases/ConvertSpec.scala index 8718f64b..46a2994b 100644 --- a/src/test/scala/chiselTests/stage/phases/ConvertSpec.scala +++ b/src/test/scala/chiselTests/stage/phases/ConvertSpec.scala @@ -2,7 +2,6 @@ package chiselTests.stage.phases - import chisel3._ import chisel3.experimental.{ChiselAnnotation, RunFirrtlTransform} import chisel3.stage.ChiselGeneratorAnnotation @@ -20,13 +19,13 @@ class ConvertSpecFirrtlTransform extends Transform with DependencyAPIMigration { override def optionalPrerequisites = Seq.empty override def optionalPrerequisiteOf = Seq.empty override def invalidates(a: Transform) = false - def execute(state: CircuitState): CircuitState = state + def execute(state: CircuitState): CircuitState = state } case class ConvertSpecFirrtlAnnotation(name: String) extends NoTargetAnnotation case class ConvertSpecChiselAnnotation(name: String) extends ChiselAnnotation with RunFirrtlTransform { - def toFirrtl: Annotation = ConvertSpecFirrtlAnnotation(name) + def toFirrtl: Annotation = ConvertSpecFirrtlAnnotation(name) def transformClass: Class[_ <: Transform] = classOf[ConvertSpecFirrtlTransform] } @@ -43,23 +42,24 @@ class ConvertSpec extends AnyFlatSpec with Matchers { class Fixture { val phase: Phase = new Convert } - behavior of classOf[Convert].toString + behavior.of(classOf[Convert].toString) it should "convert a Chisel Circuit to a FIRRTL Circuit" in new Fixture { val annos: AnnotationSeq = Seq(ChiselGeneratorAnnotation(() => new ConvertSpecFoo)) val annosx = Seq(new Elaborate, phase) - .foldLeft(annos)( (a, p) => p.transform(a) ) + .foldLeft(annos)((a, p) => p.transform(a)) info("FIRRTL circuit generated") - annosx.collect{ case a: FirrtlCircuitAnnotation => a.circuit.main }.toSeq should be (Seq("foo")) + annosx.collect { case a: FirrtlCircuitAnnotation => a.circuit.main }.toSeq should be(Seq("foo")) info("FIRRTL annotations generated") - annosx.collect{ case a: ConvertSpecFirrtlAnnotation => a.name }.toSeq should be (Seq("bar")) + annosx.collect { case a: ConvertSpecFirrtlAnnotation => a.name }.toSeq should be(Seq("bar")) info("FIRRTL transform annotations generated") - annosx.collect{ case a: RunFirrtlTransformAnnotation => a.transform.getClass} - .toSeq should be (Seq(classOf[ConvertSpecFirrtlTransform])) + annosx.collect { case a: RunFirrtlTransformAnnotation => a.transform.getClass }.toSeq should be( + Seq(classOf[ConvertSpecFirrtlTransform]) + ) } } diff --git a/src/test/scala/chiselTests/stage/phases/ElaborateSpec.scala b/src/test/scala/chiselTests/stage/phases/ElaborateSpec.scala index fce040d4..90bb229b 100644 --- a/src/test/scala/chiselTests/stage/phases/ElaborateSpec.scala +++ b/src/test/scala/chiselTests/stage/phases/ElaborateSpec.scala @@ -2,7 +2,6 @@ package chiselTests.stage.phases - import chisel3._ import chisel3.stage.{ChiselCircuitAnnotation, ChiselGeneratorAnnotation} import chisel3.stage.phases.Elaborate @@ -15,11 +14,10 @@ class ElaborateSpec extends AnyFlatSpec with Matchers { class Foo extends Module { override def desiredName: String = "Foo" - val io = IO( - new Bundle { - val in = Input(Bool()) - val out = Output(Bool()) - }) + val io = IO(new Bundle { + val in = Input(Bool()) + val out = Output(Bool()) + }) io.out := ~io.in } @@ -30,18 +28,17 @@ class ElaborateSpec extends AnyFlatSpec with Matchers { class Fixture { val phase: Phase = new Elaborate } - behavior of classOf[Elaborate].toString + behavior.of(classOf[Elaborate].toString) it should "expand ChiselGeneratorAnnotations into ChiselCircuitAnnotations and delete originals" in new Fixture { - val annotations = Seq( ChiselGeneratorAnnotation(() => new Foo), - ChiselGeneratorAnnotation(() => new Bar) ) + val annotations = Seq(ChiselGeneratorAnnotation(() => new Foo), ChiselGeneratorAnnotation(() => new Bar)) val out = phase.transform(annotations) info("original annotations removed") - out.collect{ case a: ChiselGeneratorAnnotation => a } should be (empty) + out.collect { case a: ChiselGeneratorAnnotation => a } should be(empty) info("circuits created with the expected names") - out.collect{ case a: ChiselCircuitAnnotation => a.circuit.name } should be (Seq("Foo", "Bar")) + out.collect { case a: ChiselCircuitAnnotation => a.circuit.name } should be(Seq("Foo", "Bar")) } } diff --git a/src/test/scala/chiselTests/stage/phases/EmitterSpec.scala b/src/test/scala/chiselTests/stage/phases/EmitterSpec.scala index 201f8eaf..9b7d4f42 100644 --- a/src/test/scala/chiselTests/stage/phases/EmitterSpec.scala +++ b/src/test/scala/chiselTests/stage/phases/EmitterSpec.scala @@ -2,7 +2,6 @@ package chiselTests.stage.phases - import chisel3.RawModule import chisel3.stage.{ChiselCircuitAnnotation, ChiselGeneratorAnnotation, ChiselOutputFileAnnotation} import chisel3.stage.phases.{Convert, Elaborate, Emitter} @@ -22,32 +21,31 @@ class EmitterSpec extends AnyFlatSpec with Matchers { class Fixture { val phase: Phase = new Emitter } - behavior of classOf[Emitter].toString + behavior.of(classOf[Emitter].toString) it should "do nothing if no ChiselOutputFileAnnotations are present" in new Fixture { val dir = new File("test_run_dir/EmitterSpec") - val annotations = (new Elaborate).transform(Seq( TargetDirAnnotation(dir.toString), - ChiselGeneratorAnnotation(() => new FooModule) )) + val annotations = + (new Elaborate).transform(Seq(TargetDirAnnotation(dir.toString), ChiselGeneratorAnnotation(() => new FooModule))) val annotationsx = phase.transform(annotations) val Seq(fooFile, barFile) = Seq("Foo.fir", "Bar.fir").map(f => new File(dir + "/" + f)) info(s"$fooFile does not exist") - fooFile should not (exist) + fooFile should not(exist) info("annotations are unmodified") - annotationsx.toSeq should be (annotations.toSeq) + annotationsx.toSeq should be(annotations.toSeq) } it should "emit a ChiselCircuitAnnotation to a specific file" in new Fixture { val dir = new File("test_run_dir/EmitterSpec") val circuit = (new Elaborate) .transform(Seq(ChiselGeneratorAnnotation(() => new BarModule))) - .collectFirst{ case a: ChiselCircuitAnnotation => a} + .collectFirst { case a: ChiselCircuitAnnotation => a } .get - val annotations = phase.transform(Seq( TargetDirAnnotation(dir.toString), - circuit, - ChiselOutputFileAnnotation("Baz") )) + val annotations = + phase.transform(Seq(TargetDirAnnotation(dir.toString), circuit, ChiselOutputFileAnnotation("Baz"))) val bazFile = new File(dir + "/Baz.fir") @@ -55,7 +53,7 @@ class EmitterSpec extends AnyFlatSpec with Matchers { bazFile should (exist) info("a deleted EmittedFirrtlCircuitAnnotation should be generated") - annotations.collect{ case a @ DeletedAnnotation(_, _: EmittedFirrtlCircuitAnnotation) => a }.size should be (1) + annotations.collect { case a @ DeletedAnnotation(_, _: EmittedFirrtlCircuitAnnotation) => a }.size should be(1) } } diff --git a/src/test/scala/chiselTests/util/BitPatSpec.scala b/src/test/scala/chiselTests/util/BitPatSpec.scala index 549e8bca..38ffc3ba 100644 --- a/src/test/scala/chiselTests/util/BitPatSpec.scala +++ b/src/test/scala/chiselTests/util/BitPatSpec.scala @@ -6,13 +6,12 @@ import chisel3.util.BitPat import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers - class BitPatSpec extends AnyFlatSpec with Matchers { - behavior of classOf[BitPat].toString + behavior.of(classOf[BitPat].toString) it should "convert a BitPat to readable form" in { val testPattern = "0" * 32 + "1" * 32 + "?" * 32 + "?01" * 32 - BitPat("b" + testPattern).toString should be (s"BitPat($testPattern)") + BitPat("b" + testPattern).toString should be(s"BitPat($testPattern)") } it should "convert a BitPat to raw form" in { @@ -21,15 +20,15 @@ class BitPatSpec extends AnyFlatSpec with Matchers { } it should "not fail if BitPat width is 0" in { - intercept[IllegalArgumentException]{BitPat("b")} + intercept[IllegalArgumentException] { BitPat("b") } } it should "concat BitPat via ##" in { - (BitPat.Y(4) ## BitPat.dontCare(3) ## BitPat.N(2)).toString should be (s"BitPat(1111???00)") + (BitPat.Y(4) ## BitPat.dontCare(3) ## BitPat.N(2)).toString should be(s"BitPat(1111???00)") } it should "throw when BitPat apply to a Hardware" in { - intercept[java.lang.IllegalArgumentException]{ + intercept[java.lang.IllegalArgumentException] { chisel3.stage.ChiselStage.emitChirrtl(new chisel3.Module { BitPat(chisel3.Reg(chisel3.Bool())) }) diff --git a/src/test/scala/chiselTests/util/BitSetSpec.scala b/src/test/scala/chiselTests/util/BitSetSpec.scala index 8120cc97..dd66ba40 100644 --- a/src/test/scala/chiselTests/util/BitSetSpec.scala +++ b/src/test/scala/chiselTests/util/BitSetSpec.scala @@ -6,14 +6,13 @@ import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers class BitSetSpec extends AnyFlatSpec with Matchers { - behavior of classOf[BitSet].toString + behavior.of(classOf[BitSet].toString) it should "reject unequal width when constructing a BitSet" in { intercept[IllegalArgumentException] { - BitSet.fromString( - """b0010 - |b00010 - |""".stripMargin) + BitSet.fromString("""b0010 + |b00010 + |""".stripMargin) } } @@ -21,7 +20,7 @@ class BitSetSpec extends AnyFlatSpec with Matchers { val aBitPat = BitPat("b10?") val bBitPat = BitPat("b1??") - aBitPat.subtract(bBitPat).isEmpty should be (true) + aBitPat.subtract(bBitPat).isEmpty should be(true) } it should "return nonempty subtraction result correctly" in { @@ -31,20 +30,19 @@ class BitSetSpec extends AnyFlatSpec with Matchers { val dBitPat = BitPat("b100") val diffBitPat = bBitPat.subtract(aBitPat) - bBitPat.cover(diffBitPat) should be (true) - diffBitPat.equals(cBitPat) should be (true) + bBitPat.cover(diffBitPat) should be(true) + diffBitPat.equals(cBitPat) should be(true) val largerdiffBitPat = bBitPat.subtract(dBitPat) - aBitPat.cover(dBitPat) should be (true) - largerdiffBitPat.cover(diffBitPat) should be (true) + aBitPat.cover(dBitPat) should be(true) + largerdiffBitPat.cover(diffBitPat) should be(true) } it should "be able to handle complex subtract between BitSet" in { - val aBitSet = BitSet.fromString( - """b?01?0 - |b11111 - |b00000 - |""".stripMargin) + val aBitSet = BitSet.fromString("""b?01?0 + |b11111 + |b00000 + |""".stripMargin) val bBitSet = BitSet.fromString( """b?1111 |b?0000 @@ -52,44 +50,41 @@ class BitSetSpec extends AnyFlatSpec with Matchers { ) val expected = BitPat("b?01?0") - expected.equals(aBitSet.subtract(bBitSet)) should be (true) + expected.equals(aBitSet.subtract(bBitSet)) should be(true) } it should "be generated from BitPat union" in { - val aBitSet = BitSet.fromString( - """b001?0 - |b000??""".stripMargin) + val aBitSet = BitSet.fromString("""b001?0 + |b000??""".stripMargin) val aBitPat = BitPat("b000??") val bBitPat = BitPat("b001?0") val cBitPat = BitPat("b00000") - aBitPat.cover(cBitPat) should be (true) - aBitSet.cover(bBitPat) should be (true) + aBitPat.cover(cBitPat) should be(true) + aBitSet.cover(bBitPat) should be(true) - aBitSet.equals(aBitPat.union(bBitPat)) should be (true) + aBitSet.equals(aBitPat.union(bBitPat)) should be(true) } it should "be generated from BitPat subtraction" in { - val aBitSet = BitSet.fromString( - """b001?0 - |b000??""".stripMargin) + val aBitSet = BitSet.fromString("""b001?0 + |b000??""".stripMargin) val aBitPat = BitPat("b00???") val bBitPat = BitPat("b001?1") - aBitSet.equals(aBitPat.subtract(bBitPat)) should be (true) + aBitSet.equals(aBitPat.subtract(bBitPat)) should be(true) } it should "union two BitSet together" in { - val aBitSet = BitSet.fromString( - """b001?0 - |b001?1 - |""".stripMargin) + val aBitSet = BitSet.fromString("""b001?0 + |b001?1 + |""".stripMargin) val bBitSet = BitSet.fromString( """b000?? |b01??? |""".stripMargin ) val cBitPat = BitPat("b0????") - cBitPat.equals(aBitSet.union(bBitSet)) should be (true) + cBitPat.equals(aBitSet.union(bBitSet)) should be(true) } it should "be decoded" in { @@ -100,19 +95,23 @@ class BitSetSpec extends AnyFlatSpec with Matchers { chisel3.stage.ChiselStage.emitSystemVerilog(new Module { val in = IO(Input(UInt(8.W))) val out = IO(Output(UInt(4.W))) - out := decoder.bitset(in, Seq( - BitSet.fromString( - "b000?????" + out := decoder.bitset( + in, + Seq( + BitSet.fromString( + "b000?????" + ), + BitSet.fromString( + """b0010???? + |b01?????? + |""".stripMargin + ), + BitSet.fromString( + "b11??????" + ) ), - BitSet.fromString( - """b0010???? - |b01?????? - |""".stripMargin - ), - BitSet.fromString( - "b11??????" - ) - ), true) + true + ) }) } diff --git a/src/test/scala/chiselTests/util/CatSpec.scala b/src/test/scala/chiselTests/util/CatSpec.scala index 79d2c027..a75c4ec0 100644 --- a/src/test/scala/chiselTests/util/CatSpec.scala +++ b/src/test/scala/chiselTests/util/CatSpec.scala @@ -12,7 +12,7 @@ import chiselTests.ChiselFlatSpec object CatSpec { class JackIsATypeSystemGod extends Module { - val in = IO(Input (Vec(0, UInt(8.W)))) + val in = IO(Input(Vec(0, UInt(8.W)))) val out = IO(Output(UInt(8.W))) out := Cat(in) @@ -24,7 +24,7 @@ class CatSpec extends ChiselFlatSpec { import CatSpec._ - behavior of "util.Cat" + behavior.of("util.Cat") it should "not fail to elaborate a zero-element Vec" in { @@ -41,7 +41,7 @@ class CatSpec extends ChiselFlatSpec { } val chirrtl = ChiselStage.emitChirrtl(new MyModule) for (name <- Seq("a", "b", "c", "d")) { - chirrtl should include (s"input $name : UInt<8>") + chirrtl should include(s"input $name : UInt<8>") } } @@ -54,11 +54,10 @@ class CatSpec extends ChiselFlatSpec { out := noPrefix(Cat(in)) } val chirrtl = ChiselStage.emitChirrtl(new MyModule) - chirrtl should include ("node lo_lo = cat(in[6], in[7])") - chirrtl should include ("node lo_hi = cat(in[4], in[5])") - chirrtl should include ("node hi_lo = cat(in[2], in[3])") - chirrtl should include ("node hi_hi = cat(in[0], in[1])") + chirrtl should include("node lo_lo = cat(in[6], in[7])") + chirrtl should include("node lo_hi = cat(in[4], in[5])") + chirrtl should include("node hi_lo = cat(in[2], in[3])") + chirrtl should include("node hi_hi = cat(in[0], in[1])") } - } diff --git a/src/test/scala/chiselTests/util/experimental/PlaSpec.scala b/src/test/scala/chiselTests/util/experimental/PlaSpec.scala index 8af5c936..156249a2 100644 --- a/src/test/scala/chiselTests/util/experimental/PlaSpec.scala +++ b/src/test/scala/chiselTests/util/experimental/PlaSpec.scala @@ -3,7 +3,7 @@ package chiselTests.util.experimental import chisel3._ import chisel3.stage.PrintFullStackTraceAnnotation import chisel3.testers.BasicTester -import chisel3.util.{BitPat, pla} +import chisel3.util.{pla, BitPat} import chiselTests.ChiselFlatSpec class PlaSpec extends ChiselFlatSpec { @@ -17,12 +17,17 @@ class PlaSpec extends ChiselFlatSpec { (BitPat("b100"), BitPat("b00010000")), (BitPat("b101"), BitPat("b00100000")), (BitPat("b110"), BitPat("b01000000")), - (BitPat("b111"), BitPat("b10000000")), + (BitPat("b111"), BitPat("b10000000")) ) - table.foreach { case (i, o) => - val (plaIn, plaOut) = pla(table) - plaIn := WireDefault(i.value.U(3.W)) - chisel3.assert(plaOut === o.value.U(8.W), "Input " + i.toString + " produced incorrect output BitPat(%b)", plaOut) + table.foreach { + case (i, o) => + val (plaIn, plaOut) = pla(table) + plaIn := WireDefault(i.value.U(3.W)) + chisel3.assert( + plaOut === o.value.U(8.W), + "Input " + i.toString + " produced incorrect output BitPat(%b)", + plaOut + ) } stop() }) @@ -38,12 +43,17 @@ class PlaSpec extends ChiselFlatSpec { (BitPat("b100"), BitPat("b00010000")), (BitPat("b101"), BitPat("b00100000")), (BitPat("b110"), BitPat("b01000000")), - (BitPat("b111"), BitPat("b10000000")), + (BitPat("b111"), BitPat("b10000000")) ) - table.foreach { case (i, o) => - val (plaIn, plaOut) = pla(table, BitPat("b11111111")) - plaIn := WireDefault(i.value.U(3.W)) - chisel3.assert(plaOut === ~o.value.U(8.W), "Input " + i.toString + " produced incorrect output BitPat(%b)", plaOut) + table.foreach { + case (i, o) => + val (plaIn, plaOut) = pla(table, BitPat("b11111111")) + plaIn := WireDefault(i.value.U(3.W)) + chisel3.assert( + plaOut === ~o.value.U(8.W), + "Input " + i.toString + " produced incorrect output BitPat(%b)", + plaOut + ) } stop() }) @@ -53,12 +63,13 @@ class PlaSpec extends ChiselFlatSpec { assertTesterPasses(new BasicTester { val table = Seq( (BitPat("b000"), BitPat("b?01")), - (BitPat("b111"), BitPat("b?01")), + (BitPat("b111"), BitPat("b?01")) ) - table.foreach { case (i, o) => - val (plaIn, plaOut) = pla(table) - plaIn := WireDefault(i.value.U(3.W)) - chisel3.assert(o === plaOut, "Input " + i.toString + " produced incorrect output BitPat(%b)", plaOut) + table.foreach { + case (i, o) => + val (plaIn, plaOut) = pla(table) + plaIn := WireDefault(i.value.U(3.W)) + chisel3.assert(o === plaOut, "Input " + i.toString + " produced incorrect output BitPat(%b)", plaOut) } stop() }) @@ -82,12 +93,17 @@ class PlaSpec extends ChiselFlatSpec { (BitPat("b1100"), BitPat("b0")), (BitPat("b1101"), BitPat("b1")), (BitPat("b1110"), BitPat("b1")), - (BitPat("b1111"), BitPat("b1")), + (BitPat("b1111"), BitPat("b1")) ) - table.foreach { case (i, o) => - val (plaIn, plaOut) = pla(table) - plaIn := WireDefault(i.value.U(4.W)) - chisel3.assert(plaOut === o.value.U(1.W), "Input " + i.toString + " produced incorrect output BitPat(%b)", plaOut) + table.foreach { + case (i, o) => + val (plaIn, plaOut) = pla(table) + plaIn := WireDefault(i.value.U(4.W)) + chisel3.assert( + plaOut === o.value.U(1.W), + "Input " + i.toString + " produced incorrect output BitPat(%b)", + plaOut + ) } stop() }) diff --git a/src/test/scala/chiselTests/util/experimental/TruthTableSpec.scala b/src/test/scala/chiselTests/util/experimental/TruthTableSpec.scala index 255effaf..2ef316bb 100644 --- a/src/test/scala/chiselTests/util/experimental/TruthTableSpec.scala +++ b/src/test/scala/chiselTests/util/experimental/TruthTableSpec.scala @@ -4,7 +4,7 @@ package chiselTests.util.experimental import chisel3._ import chisel3.util.BitPat -import chisel3.util.experimental.decode.{TruthTable, decoder} +import chisel3.util.experimental.decode.{decoder, TruthTable} import org.scalatest.flatspec.AnyFlatSpec class TruthTableSpec extends AnyFlatSpec { @@ -64,15 +64,14 @@ class TruthTableSpec extends AnyFlatSpec { "TruthTable" should "be reproducible" in { class Foo extends Module { - val io = IO(new Bundle{ + val io = IO(new Bundle { val in = Input(UInt(4.W)) val out = Output(UInt(16.W)) }) - val table = TruthTable( - (0 until 16).map{ - i => BitPat(i.U(4.W)) -> BitPat((1<<i).U(16.W)) + (0 until 16).map { i => + BitPat(i.U(4.W)) -> BitPat((1 << i).U(16.W)) }, BitPat.dontCare(16) ) diff --git a/src/test/scala/chiselTests/util/random/LFSRSpec.scala b/src/test/scala/chiselTests/util/random/LFSRSpec.scala index 975a3c93..d47c2d7d 100644 --- a/src/test/scala/chiselTests/util/random/LFSRSpec.scala +++ b/src/test/scala/chiselTests/util/random/LFSRSpec.scala @@ -23,7 +23,7 @@ class LFSRMaxPeriod(gen: => UInt) extends BasicTester { val (_, wrap) = Counter(started, math.pow(2.0, rv.getWidth).toInt - 1) - when (rv === seed && started) { + when(rv === seed && started) { chisel3.assert(wrap) stop() } @@ -49,7 +49,7 @@ class LFSRDistribution(gen: => UInt, cycles: Int = 10000) extends BasicTester { val (trial, done) = Counter(true.B, cycles) - val rollValue = die0 +& die1 // Note +& is critical because sum will need an extra bit. + val rollValue = die0 +& die1 // Note +& is critical because sum will need an extra bit. bins(rollValue) := bins(rollValue) + 1.U @@ -88,17 +88,17 @@ class LFSRResetTester(gen: => LFSR, lockUpValue: BigInt) extends BasicTester { lfsr.io.seed.bits := lockUpValue.U(lfsr.width.W).asBools lfsr.io.increment := true.B - when (count === 2.U) { + when(count === 2.U) { assert(lfsr.io.out.asUInt === lockUpValue.U, "LFSR is NOT locked up, but should be!") } lfsr.reset := count === 3.U - when (count === 4.U) { + when(count === 4.U) { assert(lfsr.io.out.asUInt =/= lockUpValue.U, "LFSR is locked up, but should not be after reset!") } - when (done) { + when(done) { stop() } @@ -110,29 +110,34 @@ class LFSRSpec extends ChiselFlatSpec with Utils { val testName = s"have a maximal period over a range of widths (${range.head} to ${range.last})" + s" using ${reduction.getClass}" it should testName in { - range - .foreach{ width => - LFSR.tapsMaxPeriod(width).foreach{ taps => - info(s"""width $width okay using taps: ${taps.mkString(", ")}""") - assertTesterPasses(new LFSRMaxPeriod(PRNG(gen(width, taps, reduction))), - annotations = TesterDriver.verilatorOnly) - } + range.foreach { width => + LFSR.tapsMaxPeriod(width).foreach { taps => + info(s"""width $width okay using taps: ${taps.mkString(", ")}""") + assertTesterPasses( + new LFSRMaxPeriod(PRNG(gen(width, taps, reduction))), + annotations = TesterDriver.verilatorOnly + ) } + } } } - behavior of "LFSR" + behavior.of("LFSR") it should "throw an exception if initialized to a seed of zero for XOR configuration" in { - { the [IllegalArgumentException] thrownBy extractCause[IllegalArgumentException] { - ChiselStage.elaborate(new FooLFSR(XOR, Some(0))) } - }.getMessage should include ("Seed cannot be zero") + { + the[IllegalArgumentException] thrownBy extractCause[IllegalArgumentException] { + ChiselStage.elaborate(new FooLFSR(XOR, Some(0))) + } + }.getMessage should include("Seed cannot be zero") } it should "throw an exception if initialized to a seed of all ones for XNOR configuration" in { - { the [IllegalArgumentException] thrownBy extractCause[IllegalArgumentException] { - ChiselStage.elaborate(new FooLFSR(XNOR, Some(15))) } - }.getMessage should include ("Seed cannot be all ones") + { + the[IllegalArgumentException] thrownBy extractCause[IllegalArgumentException] { + ChiselStage.elaborate(new FooLFSR(XNOR, Some(15))) + } + }.getMessage should include("Seed cannot be all ones") } it should "reset correctly without a seed for XOR configuration" in { @@ -143,34 +148,35 @@ class LFSRSpec extends ChiselFlatSpec with Utils { assertTesterPasses(new LFSRResetTester(new FooLFSR(XNOR, None), 15)) } - behavior of "MaximalPeriodGaloisLFSR" + behavior.of("MaximalPeriodGaloisLFSR") it should "throw an exception if no LFSR taps are known" in { - { the [IllegalArgumentException] thrownBy extractCause[IllegalArgumentException] { - ChiselStage.elaborate(new MaxPeriodGaloisLFSR(787)) } - }.getMessage should include ("No max period LFSR taps stored for requested width") + { + the[IllegalArgumentException] thrownBy extractCause[IllegalArgumentException] { + ChiselStage.elaborate(new MaxPeriodGaloisLFSR(787)) + } + }.getMessage should include("No max period LFSR taps stored for requested width") } - periodCheck((w: Int, t: Set[Int], r: LFSRReduce) => new GaloisLFSR(w, t, reduction=r), XOR, 2 to 16) - periodCheck((w: Int, t: Set[Int], r: LFSRReduce) => new GaloisLFSR(w, t, reduction=r), XNOR, 2 to 16) + periodCheck((w: Int, t: Set[Int], r: LFSRReduce) => new GaloisLFSR(w, t, reduction = r), XOR, 2 to 16) + periodCheck((w: Int, t: Set[Int], r: LFSRReduce) => new GaloisLFSR(w, t, reduction = r), XNOR, 2 to 16) ignore should "have a sane distribution for larger widths" in { - ((17 to 32) ++ Seq(64, 128, 256, 512, 1024, 2048, 4096)) - .foreach{ width => - info(s"width $width okay!") - assertTesterPasses(new LFSRDistribution(LFSR(width), math.pow(2, 22).toInt)) - } + ((17 to 32) ++ Seq(64, 128, 256, 512, 1024, 2048, 4096)).foreach { width => + info(s"width $width okay!") + assertTesterPasses(new LFSRDistribution(LFSR(width), math.pow(2, 22).toInt)) + } } - behavior of "MaximalPeriodFibonacciLFSR" + behavior.of("MaximalPeriodFibonacciLFSR") - periodCheck((w: Int, t: Set[Int], r: LFSRReduce) => new FibonacciLFSR(w, t, reduction=r), XOR, 2 to 16) - periodCheck((w: Int, t: Set[Int], r: LFSRReduce) => new FibonacciLFSR(w, t, reduction=r), XNOR, 2 to 16) + periodCheck((w: Int, t: Set[Int], r: LFSRReduce) => new FibonacciLFSR(w, t, reduction = r), XOR, 2 to 16) + periodCheck((w: Int, t: Set[Int], r: LFSRReduce) => new FibonacciLFSR(w, t, reduction = r), XNOR, 2 to 16) - behavior of "LFSR maximal period taps" + behavior.of("LFSR maximal period taps") it should "contain all the expected widths" in { - ((2 to 786) ++ Seq(1024, 2048, 4096)).foreach(LFSR.tapsMaxPeriod.keys should contain (_)) + ((2 to 786) ++ Seq(1024, 2048, 4096)).foreach(LFSR.tapsMaxPeriod.keys should contain(_)) } } diff --git a/src/test/scala/chiselTests/util/random/PRNGSpec.scala b/src/test/scala/chiselTests/util/random/PRNGSpec.scala index 71a8635c..36fdf9cb 100644 --- a/src/test/scala/chiselTests/util/random/PRNGSpec.scala +++ b/src/test/scala/chiselTests/util/random/PRNGSpec.scala @@ -28,15 +28,15 @@ class PRNGStepTest extends BasicTester { val (_, done) = Counter(true.B, 16) - when (count2 === 0.U) { + when(count2 === 0.U) { assert(a === b, "1-step and 2-step PRNGs did not agree! (0b%b != 0b%b)", a, b) } - when (count4 === 0.U) { + when(count4 === 0.U) { assert(a === c, "1-step and 4-step PRNGs did not agree!") } - when (done) { + when(done) { stop() } @@ -52,11 +52,11 @@ class PRNGUpdateSeedTest(updateSeed: Boolean, seed: BigInt, expected: BigInt) ex a.io.seed.valid := count === 2.U a.io.seed.bits := seed.U(a.width.W).asBools - when (count === 3.U) { + when(count === 3.U) { assert(a.io.out.asUInt === expected.U, "Output didn't match!") } - when (done) { + when(done) { stop() } @@ -64,18 +64,22 @@ class PRNGUpdateSeedTest(updateSeed: Boolean, seed: BigInt, expected: BigInt) ex class PRNGSpec extends ChiselFlatSpec with Utils { - behavior of "PRNG" + behavior.of("PRNG") it should "throw an exception if the step size is < 1" in { - { the [IllegalArgumentException] thrownBy extractCause[IllegalArgumentException] { - ChiselStage.elaborate(new CyclePRNG(0, Some(1), 1, true)) } - }.getMessage should include ("Width must be greater than zero!") + { + the[IllegalArgumentException] thrownBy extractCause[IllegalArgumentException] { + ChiselStage.elaborate(new CyclePRNG(0, Some(1), 1, true)) + } + }.getMessage should include("Width must be greater than zero!") } it should "throw an exception if the step size is <= 0" in { - { the [IllegalArgumentException] thrownBy extractCause[IllegalArgumentException] { - ChiselStage.elaborate(new CyclePRNG(1, Some(1), 0, true)) } - }.getMessage should include ("Step size must be greater than one!") + { + the[IllegalArgumentException] thrownBy extractCause[IllegalArgumentException] { + ChiselStage.elaborate(new CyclePRNG(1, Some(1), 0, true)) + } + }.getMessage should include("Step size must be greater than one!") } it should "handle non-unary steps" in { diff --git a/src/test/scala/cookbook/Bundle2UInt.scala b/src/test/scala/cookbook/Bundle2UInt.scala index 5bc1063a..21d06df7 100644 --- a/src/test/scala/cookbook/Bundle2UInt.scala +++ b/src/test/scala/cookbook/Bundle2UInt.scala @@ -24,7 +24,7 @@ class Bundle2UInt extends CookbookTester(1) { assert(uint === 0xc3.U) } -class Bundle2UIntSpec extends CookbookSpec { +class Bundle2UIntSpec extends CookbookSpec { "Bundle2UInt" should "work" in { assertTesterPasses { new Bundle2UInt } } diff --git a/src/test/scala/cookbook/CookbookSpec.scala b/src/test/scala/cookbook/CookbookSpec.scala index c1acc0de..7d6c9726 100644 --- a/src/test/scala/cookbook/CookbookSpec.scala +++ b/src/test/scala/cookbook/CookbookSpec.scala @@ -16,7 +16,7 @@ abstract class CookbookTester(length: Int) extends BasicTester { require(length >= 0, "Simulation length must be non-negative!") val (cycle, done) = Counter(true.B, length + 1) // + 1 cycle because done is actually wrap - when (done) { stop() } + when(done) { stop() } } abstract class CookbookSpec extends ChiselFlatSpec diff --git a/src/test/scala/cookbook/FSM.scala b/src/test/scala/cookbook/FSM.scala index 0c1173ec..66f3063f 100644 --- a/src/test/scala/cookbook/FSM.scala +++ b/src/test/scala/cookbook/FSM.scala @@ -26,21 +26,21 @@ class DetectTwoOnes extends Module { io.out := (state === State.sTwo1s) - switch (state) { - is (State.sNone) { - when (io.in) { + switch(state) { + is(State.sNone) { + when(io.in) { state := State.sOne1 } } - is (State.sOne1) { - when (io.in) { + is(State.sOne1) { + when(io.in) { state := State.sTwo1s - } .otherwise { + }.otherwise { state := State.sNone } } - is (State.sTwo1s) { - when (!io.in) { + is(State.sTwo1s) { + when(!io.in) { state := State.sNone } } @@ -53,7 +53,8 @@ class DetectTwoOnesTester extends CookbookTester(10) { // Inputs and expected results val inputs: Vec[Bool] = VecInit(false.B, true.B, false.B, true.B, true.B, true.B, false.B, true.B, true.B, false.B) - val expected: Vec[Bool] = VecInit(false.B, false.B, false.B, false.B, false.B, true.B, true.B, false.B, false.B, true.B) + val expected: Vec[Bool] = + VecInit(false.B, false.B, false.B, false.B, false.B, true.B, true.B, false.B, false.B, true.B) dut.io.in := inputs(cycle) assert(dut.io.out === expected(cycle)) diff --git a/src/test/scala/cookbook/RegOfVec.scala b/src/test/scala/cookbook/RegOfVec.scala index ba1ab359..ddb615c7 100644 --- a/src/test/scala/cookbook/RegOfVec.scala +++ b/src/test/scala/cookbook/RegOfVec.scala @@ -22,11 +22,11 @@ class RegOfVec extends CookbookTester(2) { val initRegOfVec = RegInit(VecInit(Seq.fill(4)(0.U(32.W)))) // Simple test (cycle comes from superclass) - when (cycle === 2.U) { assert(regOfVec(2) === 123.U) } + when(cycle === 2.U) { assert(regOfVec(2) === 123.U) } for (elt <- initRegOfVec) { assert(elt === 0.U) } } -class RegOfVecSpec extends CookbookSpec { +class RegOfVecSpec extends CookbookSpec { "RegOfVec" should "work" in { assertTesterPasses { new RegOfVec } } diff --git a/src/test/scala/cookbook/VecOfBool2UInt.scala b/src/test/scala/cookbook/VecOfBool2UInt.scala index 024eca89..ca1413dc 100644 --- a/src/test/scala/cookbook/VecOfBool2UInt.scala +++ b/src/test/scala/cookbook/VecOfBool2UInt.scala @@ -21,7 +21,7 @@ class VecOfBool2UInt extends CookbookTester(1) { assert(0xd.U === uint) } -class VecOfBool2UIntSpec extends CookbookSpec { +class VecOfBool2UIntSpec extends CookbookSpec { "VecOfBool2UInt" should "work" in { assertTesterPasses { new VecOfBool2UInt } } diff --git a/src/test/scala/examples/ImplicitStateVendingMachine.scala b/src/test/scala/examples/ImplicitStateVendingMachine.scala index 817240d5..36ac82ab 100644 --- a/src/test/scala/examples/ImplicitStateVendingMachine.scala +++ b/src/test/scala/examples/ImplicitStateVendingMachine.scala @@ -12,14 +12,14 @@ class ImplicitStateVendingMachine extends SimpleVendingMachine { val incValue = WireDefault(0.asUInt(3.W)) val doDispense = value >= 4.U // 4 * nickel as 1 == $0.20 - when (doDispense) { + when(doDispense) { value := 0.U // No change given - } .otherwise { + }.otherwise { value := value + incValue } - when (io.nickel) { incValue := 1.U } - when (io.dime) { incValue := 2.U } + when(io.nickel) { incValue := 1.U } + when(io.dime) { incValue := 2.U } io.dispense := doDispense } diff --git a/src/test/scala/examples/SimpleVendingMachine.scala b/src/test/scala/examples/SimpleVendingMachine.scala index dff60a4d..819669a3 100644 --- a/src/test/scala/examples/SimpleVendingMachine.scala +++ b/src/test/scala/examples/SimpleVendingMachine.scala @@ -9,8 +9,8 @@ import chisel3.util._ class SimpleVendingMachineIO extends Bundle { val nickel = Input(Bool()) - val dime = Input(Bool()) - val dispense = Output(Bool()) + val dime = Input(Bool()) + val dispense = Output(Bool()) } // Superclass for vending machines with very simple IO @@ -24,24 +24,24 @@ class FSMVendingMachine extends SimpleVendingMachine { val sIdle :: s5 :: s10 :: s15 :: sOk :: Nil = Enum(5) val state = RegInit(sIdle) - switch (state) { - is (sIdle) { - when (io.nickel) { state := s5 } - when (io.dime) { state := s10 } + switch(state) { + is(sIdle) { + when(io.nickel) { state := s5 } + when(io.dime) { state := s10 } } - is (s5) { - when (io.nickel) { state := s10 } - when (io.dime) { state := s15 } + is(s5) { + when(io.nickel) { state := s10 } + when(io.dime) { state := s15 } } - is (s10) { - when (io.nickel) { state := s15 } - when (io.dime) { state := sOk } + is(s10) { + when(io.nickel) { state := s15 } + when(io.dime) { state := sOk } } - is (s15) { - when (io.nickel) { state := sOk } - when (io.dime) { state := sOk } + is(s15) { + when(io.nickel) { state := sOk } + when(io.dime) { state := sOk } } - is (sOk) { + is(sOk) { state := sIdle } } @@ -73,11 +73,11 @@ class SimpleVendingMachineTester(mod: => SimpleVendingMachine) extends BasicTest val dut = Module(mod) val (cycle, done) = Counter(true.B, 10) - when (done) { stop(); stop() } // Stop twice because of Verilator + when(done) { stop(); stop() } // Stop twice because of Verilator val nickelInputs = VecInit(true.B, true.B, true.B, true.B, true.B, false.B, false.B, false.B, true.B, false.B) - val dimeInputs = VecInit(false.B, false.B, false.B, false.B, false.B, true.B, true.B, false.B, false.B, true.B) - val expected = VecInit(false.B, false.B, false.B, false.B, true.B , false.B, false.B, true.B, false.B, false.B) + val dimeInputs = VecInit(false.B, false.B, false.B, false.B, false.B, true.B, true.B, false.B, false.B, true.B) + val expected = VecInit(false.B, false.B, false.B, false.B, true.B, false.B, false.B, true.B, false.B, false.B) dut.io.nickel := nickelInputs(cycle) dut.io.dime := dimeInputs(cycle) @@ -89,7 +89,10 @@ class SimpleVendingMachineSpec extends ChiselFlatSpec { assertTesterPasses { new SimpleVendingMachineTester(new FSMVendingMachine) } } "An Verilog implementation of a vending machine" should "work" in { - assertTesterPasses(new SimpleVendingMachineTester(new VerilogVendingMachineWrapper), - List("/chisel3/VerilogVendingMachine.v"), annotations = TesterDriver.verilatorOnly) + assertTesterPasses( + new SimpleVendingMachineTester(new VerilogVendingMachineWrapper), + List("/chisel3/VerilogVendingMachine.v"), + annotations = TesterDriver.verilatorOnly + ) } } diff --git a/src/test/scala/examples/VendingMachineGenerator.scala b/src/test/scala/examples/VendingMachineGenerator.scala index 72bfdf53..4adae987 100644 --- a/src/test/scala/examples/VendingMachineGenerator.scala +++ b/src/test/scala/examples/VendingMachineGenerator.scala @@ -12,12 +12,14 @@ import VendingMachineUtils._ class VendingMachineIO(val legalCoins: Seq[Coin]) extends Bundle { require(legalCoins.size >= 1, "The vending machine must accept at least 1 coin!") // Order of coins by value - val coins: Seq[Coin] = legalCoins sortBy (_.value) + val coins: Seq[Coin] = legalCoins.sortBy(_.value) // Map of coin names to their relative position in value (ie. index in inputs) val indexMap: Map[String, Int] = coins.map(_.name).zipWithIndex.toMap - require(coins map (_.value % coins.head.value == 0) reduce (_ && _), - "All coins must be a multiple of the lowest value coin!") + require( + coins.map(_.value % coins.head.value == 0).reduce(_ && _), + "All coins must be a multiple of the lowest value coin!" + ) val inputs = Input(Vec(legalCoins.size, Bool())) val dispense = Output(Bool()) @@ -34,17 +36,17 @@ abstract class ParameterizedVendingMachine(legalCoins: Seq[Coin], val sodaCost: // Enforce one hot if (io.inputs.size > 1) { for (input <- io.inputs) { - when (input) { - assert(io.inputs.filterNot(_ == input).map(!_).reduce(_ && _), - "Only 1 coin can be input in a given cycle!") + when(input) { + assert(io.inputs.filterNot(_ == input).map(!_).reduce(_ && _), "Only 1 coin can be input in a given cycle!") } } } } class VendingMachineGenerator( - legalCoins: Seq[Coin], - sodaCost: Int) extends ParameterizedVendingMachine(legalCoins, sodaCost) { + legalCoins: Seq[Coin], + sodaCost: Int) + extends ParameterizedVendingMachine(legalCoins, sodaCost) { require(sodaCost > 0, "Sodas must actually cost something!") // All coin values are normalized to a multiple of the minimum coin value @@ -57,21 +59,22 @@ class VendingMachineGenerator( val incValue = WireDefault(0.asUInt(width)) val doDispense = value >= (sodaCost / minCoin).U - when (doDispense) { + when(doDispense) { value := 0.U // No change given - } .otherwise { + }.otherwise { value := value + incValue } for ((coin, index) <- io.coins.zipWithIndex) { - when (io.inputs(index)) { incValue := (coin.value / minCoin).U } + when(io.inputs(index)) { incValue := (coin.value / minCoin).U } } io.dispense := doDispense } class ParameterizedVendingMachineTester( - mod: => ParameterizedVendingMachine, - testLength: Int) extends BasicTester { + mod: => ParameterizedVendingMachine, + testLength: Int) + extends BasicTester { require(testLength > 0, "Test length must be positive!") // Construct the module @@ -81,24 +84,24 @@ class ParameterizedVendingMachineTester( // Inputs and expected results // Do random testing private val _rand = scala.util.Random - val inputs: Seq[Option[Coin]] = Seq.fill(testLength)(coins.lift(_rand.nextInt(coins.size + 1))) + val inputs: Seq[Option[Coin]] = Seq.fill(testLength)(coins.lift(_rand.nextInt(coins.size + 1))) val expected: Seq[Boolean] = getExpectedResults(inputs, dut.sodaCost) - val inputVec: Vec[UInt] = VecInit(inputs map { + val inputVec: Vec[UInt] = VecInit(inputs.map { case Some(coin) => (1 << dut.io.indexMap(coin.name)).asUInt(coins.size.W) - case None => 0.asUInt(coins.size.W) + case None => 0.asUInt(coins.size.W) }) - val expectedVec: Vec[Bool] = VecInit(expected map (_.B)) + val expectedVec: Vec[Bool] = VecInit(expected.map(_.B)) val (idx, done) = Counter(true.B, testLength + 1) - when (done) { stop(); stop() } // Two stops for Verilator + when(done) { stop(); stop() } // Two stops for Verilator dut.io.inputs := inputVec(idx).asBools assert(dut.io.dispense === expectedVec(idx)) } class VendingMachineGeneratorSpec extends ChiselFlatSpec { - behavior of "The vending machine generator" + behavior.of("The vending machine generator") it should "generate a vending machine that accepts only nickels and dimes and costs $0.20" in { val coins = Seq(Nickel, Dime) diff --git a/src/test/scala/examples/VendingMachineUtils.scala b/src/test/scala/examples/VendingMachineUtils.scala index 6847768a..8d5aea57 100644 --- a/src/test/scala/examples/VendingMachineUtils.scala +++ b/src/test/scala/examples/VendingMachineUtils.scala @@ -24,7 +24,7 @@ object VendingMachineUtils { for (input <- inputs) { val incValue = input match { case Some(coin) => coin.value - case None => 0 + case None => 0 } if (value >= sodaCost) { outputs.append(true) |
