From b169f6db95f9778cf8968cc1042b7f810f9d8123 Mon Sep 17 00:00:00 2001 From: mergify[bot] Date: Tue, 15 Nov 2022 05:28:10 +0000 Subject: fullModulePorts + Opaque Types Fix and Test (#2845) (#2846) (cherry picked from commit 49feb083c69066988ca0666ea4249a86570e2589) Co-authored-by: Megan Wachs --- core/src/main/scala/chisel3/Data.scala | 9 +++++++-- src/test/scala/chiselTests/RecordSpec.scala | 20 ++++++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/core/src/main/scala/chisel3/Data.scala b/core/src/main/scala/chisel3/Data.scala index 50093333..dddc0d5d 100644 --- a/core/src/main/scala/chisel3/Data.scala +++ b/core/src/main/scala/chisel3/Data.scala @@ -256,8 +256,13 @@ 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) => + if (r._isOpaqueType) { getPortNames(s"${name}", elt) } + else { 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) => diff --git a/src/test/scala/chiselTests/RecordSpec.scala b/src/test/scala/chiselTests/RecordSpec.scala index 3414ec8a..5a5bcf67 100644 --- a/src/test/scala/chiselTests/RecordSpec.scala +++ b/src/test/scala/chiselTests/RecordSpec.scala @@ -284,6 +284,26 @@ class RecordSpec extends ChiselFlatSpec with RecordSpecUtils with Utils { testStrings.foreach(x => assert(x == "~NestedRecordModule|InnerModule>io.foo")) } + they should "work correctly with DataMirror in nested OpaqueType Records" in { + var mod: NestedRecordModule = null + ChiselStage.elaborate { mod = new NestedRecordModule; mod } + val ports = chisel3.experimental.DataMirror.fullModulePorts(mod.inst) + val expectedPorts = Seq( + ("clock", mod.inst.clock), + ("reset", mod.inst.reset), + ("io", mod.inst.io), + ("io_bar", mod.inst.io.bar), + ("io_bar", mod.inst.io.bar.k), + ("io_bar", mod.inst.io.bar.k.k), + ("io_bar", mod.inst.io.bar.k.k.elements.head._2), + ("io_foo", mod.inst.io.foo), + ("io_foo", mod.inst.io.foo.k), + ("io_foo", mod.inst.io.foo.k.k), + ("io_foo", mod.inst.io.foo.k.k.elements.head._2) + ) + ports shouldBe expectedPorts + } + they should "work correctly when connecting nested OpaqueType elements" in { val nestedRecordChirrtl = ChiselStage.emitChirrtl { new NestedRecordModule } nestedRecordChirrtl should include("input in : UInt<8>") -- cgit v1.2.3 From c21f31d09f2511497cea5cb03bd6ddba440c55fe Mon Sep 17 00:00:00 2001 From: mergify[bot] Date: Tue, 29 Nov 2022 17:24:38 +0000 Subject: Implement compressed Namespace (backport #2856) (#2860) * Implement compressed Namespace (#2856) The namespace disambiguates requests for the same name with _. Rather than storing every disambiguated name in the underlying HashMap, it now only stores the base along with the "next available" index. This makes the logic for checking if a name is already contained in the namespace slightly more sophisticated because users can name things in a way that will collide with disambiguated names from a common substring. For example, in naming the sequence "foo", "foo", "foo_1", the 2nd "foo" takes the name "foo_1" so the following "foo_1" gets disambiguated to "foo_1_1". But since we compressed that original "foo_1" into the same HashMap entry as just "foo", we have to do a form of "prefix checking" whenever naming something that ends in "_". In practice, the saved memory allocations more than make up for the more complicated logic to disambiguate names because the common case is still fast. (cherry picked from commit 1654d87a02ca799bf12805a611a91e7524d49843) # Conflicts: # core/src/main/scala/chisel3/internal/Builder.scala * Resolve backport conflicts Co-authored-by: Jack Koenig --- core/src/main/scala/chisel3/internal/Builder.scala | 63 ++++++++++++++--- .../scala/chisel3/internal/NamespaceSpec.scala | 81 ++++++++++++++++++++++ 2 files changed, 136 insertions(+), 8 deletions(-) create mode 100644 src/test/scala/chisel3/internal/NamespaceSpec.scala diff --git a/core/src/main/scala/chisel3/internal/Builder.scala b/core/src/main/scala/chisel3/internal/Builder.scala index e3dfff09..d06b7992 100644 --- a/core/src/main/scala/chisel3/internal/Builder.scala +++ b/core/src/main/scala/chisel3/internal/Builder.scala @@ -17,18 +17,29 @@ import chisel3.internal.Builder.Prefix import logger.LazyLogging import scala.collection.mutable +import scala.annotation.tailrec private[chisel3] class Namespace(keywords: Set[String]) { + // This HashMap is compressed, not every name in the namespace is present here. + // If the same name is requested multiple times, it only takes 1 entry in the HashMap and the + // value is incremented for each time the name is requested. + // Names can be requested that collide with compressed sets of names, thus the algorithm for + // checking if a name is present in the Namespace is more complex than just checking the HashMap, + // see getIndex below. private val names = collection.mutable.HashMap[String, Long]() def copyTo(other: Namespace): Unit = names.foreach { case (s: String, l: Long) => other.names(s) = l } for (keyword <- keywords) names(keyword) = 1 - private def rename(n: String): String = { - val index = names(n) + @tailrec + private def rename(n: String, index: Long): String = { val tryName = s"${n}_${index}" - names(n) = index + 1 - if (this contains tryName) rename(n) else tryName + if (names.contains(tryName)) { + rename(n, index + 1) + } else { + names(n) = index + 1 + tryName + } } private def sanitize(s: String, leadingDigitOk: Boolean = false): String = { @@ -40,14 +51,50 @@ private[chisel3] class Namespace(keywords: Set[String]) { if (headOk) res else s"_$res" } - def contains(elem: String): Boolean = names.contains(elem) + /** Checks if `n` ends in `_\d+` and returns the substring before `_` if so, null otherwise */ + // TODO can and should this be folded in to sanitize? Same iteration as the forall? + private def prefix(n: String): Int = { + // This is micro-optimized because it runs on every single name + var i = n.size - 1 + while (i > 0 && n(i).isDigit) { + i -= 1 + } + // Will get i == 0 for all digits or _\d+ with empty prefix, those have no prefix so returning 0 is correct + if (i == n.size) 0 // no digits + else if (n(i) != '_') 0 // no _ + else i + } + + // Gets the current index for this name, None means it is not contained in the Namespace + private def getIndex(elem: String): Option[Long] = + names.get(elem).orElse { + // This exact name isn't contained, but if we end in _, we need to check our prefix + val maybePrefix = prefix(elem) + if (maybePrefix == 0) None + else { + // If we get a prefix collision and our index is taken, we start disambiguating with __1 + names + .get(elem.take(maybePrefix)) + .filter { prefixIdx => + val ourIdx = elem.drop(maybePrefix + 1).toInt + // The namespace starts disambiguating at _1 so _0 is a false collision case + ourIdx != 0 && prefixIdx > ourIdx + } + .map(_ => 1) + } + } + + def contains(elem: String): Boolean = getIndex(elem).isDefined // leadingDigitOk is for use in fields of Records def name(elem: String, leadingDigitOk: Boolean = false): String = { val sanitized = sanitize(elem, leadingDigitOk) - val result = if (this.contains(sanitized)) rename(sanitized) else sanitized - names(result) = 1 - result + getIndex(sanitized) match { + case Some(idx) => rename(sanitized, idx) + case None => + names(sanitized) = 1 + sanitized + } } } diff --git a/src/test/scala/chisel3/internal/NamespaceSpec.scala b/src/test/scala/chisel3/internal/NamespaceSpec.scala new file mode 100644 index 00000000..fd808ff0 --- /dev/null +++ b/src/test/scala/chisel3/internal/NamespaceSpec.scala @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: Apache-2.0 + +package chisel3.internal + +import org.scalatest.flatspec.AnyFlatSpec +import org.scalatest.matchers.should.Matchers._ + +class NamespaceSpec extends AnyFlatSpec { + behavior.of("Namespace") + + they should "support basic disambiguation" in { + val namespace = Namespace.empty + val name = namespace.name(_, false) + name("x") should be("x") + name("x") should be("x_1") + name("x") should be("x_2") + } + + they should "support explicit _# names before names" in { + val namespace = Namespace.empty + val name = namespace.name(_, false) + name("x_1") should be("x_1") + name("x_2") should be("x_2") + name("x") should be("x") + name("x") should be("x_3") + } + + they should "support explicit _# names in the middle of names" in { + val namespace = Namespace.empty + val name = namespace.name(_, false) + name("x") should be("x") + name("x") should be("x_1") + name("x_1") should be("x_1_1") + name("x_2") should be("x_2") + name("x") should be("x_3") + } + + // For some reason, multi-character names tickled a different failure mode than single character + they should "support explicit _# names in the middle of longer names" in { + val namespace = Namespace.empty + val name = namespace.name(_, false) + name("foo") should be("foo") + name("foo") should be("foo_1") + name("foo_1") should be("foo_1_1") + name("foo_2") should be("foo_2") + name("foo") should be("foo_3") + } + + they should "support collisions in recursively growing names" in { + val namespace = Namespace.empty + val name = namespace.name(_, false) + name("x") should be("x") + name("x") should be("x_1") + name("x_1") should be("x_1_1") + name("x_1") should be("x_1_2") + name("x_1_1") should be("x_1_1_1") + name("x_1_1") should be("x_1_1_2") + } + + they should "support collisions in recursively shrinking names" in { + val namespace = Namespace.empty + val name = namespace.name(_, false) + name("x_1_1") should be("x_1_1") + name("x_1_1") should be("x_1_1_1") + name("x_1") should be("x_1") + name("x_1") should be("x_1_2") + name("x") should be("x") + name("x") should be("x_2") + } + + // The namespace never generates names with _0 so it's actually a false collision case + they should "properly handle false collisions with signals ending in _0" in { + val namespace = Namespace.empty + val name = namespace.name(_, false) + name("x") should be("x") + name("x") should be("x_1") + name("x_0") should be("x_0") + name("x") should be("x_2") + name("x_0") should be("x_0_1") + } +} -- cgit v1.2.3 From fa11cd7b807656fd3ab8ef62530d77f669584239 Mon Sep 17 00:00:00 2001 From: mergify[bot] Date: Tue, 6 Dec 2022 05:12:50 +0000 Subject: Add versionScheme (PVP) to SBT publish settings (backport #2871) (#2874) * Add versionScheme (PVP) to SBT publish settings (#2871) This allows build tools to warn users about possible binary incompatibility issues when using dependencies that depend on mutually incompatible versions of Chisel. (cherry picked from commit 9f080d51d1e7bb9d44fb10da86fcaab68a21377b) # Conflicts: # build.sbt * Resolve backport conflicts Co-authored-by: Jack Koenig --- build.sbt | 1 + 1 file changed, 1 insertion(+) diff --git a/build.sbt b/build.sbt index 80fa8240..8ce457d4 100644 --- a/build.sbt +++ b/build.sbt @@ -41,6 +41,7 @@ lazy val commonSettings = Seq ( ) lazy val publishSettings = Seq ( + versionScheme := Some("pvp"), publishMavenStyle := true, publishArtifact in Test := false, pomIncludeRepository := { x => false }, -- cgit v1.2.3 From 41d0d4cd075130cb6b4e41a7c7b6183830b5b9bc Mon Sep 17 00:00:00 2001 From: mergify[bot] Date: Wed, 7 Dec 2022 00:41:55 +0000 Subject: Make PriorityMux stack safe (backport #2854) (#2855) * Make PriorityMux stack safe (#2854) It used to be implemented with recursion, now it's implemented with a stack safe reverse and foldLeft. Also there were no tests for PriorityMux so I added one which helps prove the change is functionally correct. (cherry picked from commit 269ce472e9aa0c242fc028871a1fd5b045c82f83) # Conflicts: # src/test/scala/chiselTests/util/PipeSpec.scala * Resolve backport conflicts Co-authored-by: Jack Koenig Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>--- core/src/main/scala/chisel3/SeqUtils.scala | 5 +- .../scala/chiselTests/util/PriorityMuxSpec.scala | 60 ++++++++++++++++++++++ 2 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 src/test/scala/chiselTests/util/PriorityMuxSpec.scala diff --git a/core/src/main/scala/chisel3/SeqUtils.scala b/core/src/main/scala/chisel3/SeqUtils.scala index b1136120..9d975349 100644 --- a/core/src/main/scala/chisel3/SeqUtils.scala +++ b/core/src/main/scala/chisel3/SeqUtils.scala @@ -64,7 +64,10 @@ private[chisel3] object SeqUtils { if (in.size == 1) { in.head._2 } else { - Mux(in.head._1, in.head._2, priorityMux(in.tail)) + val r = in.view.reverse + r.tail.foldLeft(r.head._2) { + case (alt, (sel, elt)) => Mux(sel, elt, alt) + } } } diff --git a/src/test/scala/chiselTests/util/PriorityMuxSpec.scala b/src/test/scala/chiselTests/util/PriorityMuxSpec.scala new file mode 100644 index 00000000..32cf2431 --- /dev/null +++ b/src/test/scala/chiselTests/util/PriorityMuxSpec.scala @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: Apache-2.0 + +package chiselTests.util + +import chisel3._ +import chisel3.util.{is, switch, Counter, PriorityMux} +import chisel3.testers.BasicTester +import chisel3.stage.ChiselStage.emitChirrtl + +import chiselTests.ChiselFlatSpec + +class PriorityMuxTester extends BasicTester { + + val sel = Wire(UInt(3.W)) + sel := 0.U // default + + val elts = Seq(5.U, 6.U, 7.U) + val muxed = PriorityMux(sel, elts) + + // Priority is given to lowest order bit + val tests = Seq( + 1.U -> elts(0), + 2.U -> elts(1), + 3.U -> elts(0), + 4.U -> elts(2), + 5.U -> elts(0), + 6.U -> elts(1), + 7.U -> elts(0) + ) + val (cycle, done) = Counter(0 until tests.size + 1) + + for (((in, out), idx) <- tests.zipWithIndex) { + when(cycle === idx.U) { + sel := in + assert(muxed === out) + } + } + + when(done) { + stop() + } +} + +class PriorityMuxSpec extends ChiselFlatSpec { + behavior.of("PriorityMux") + + it should "be functionally correct" in { + assertTesterPasses(new PriorityMuxTester) + } + + it should "be stack safe" in { + emitChirrtl(new RawModule { + val n = 1 << 15 + val in = IO(Input(Vec(n, UInt(8.W)))) + val sel = IO(Input(UInt(n.W))) + val out = IO(Output(UInt(8.W))) + out := PriorityMux(sel, in) + }) + } +} -- cgit v1.2.3 From 8fe876463e26d1b63e36a7ebf4a2bc62366cce81 Mon Sep 17 00:00:00 2001 From: mergify[bot] Date: Wed, 7 Dec 2022 21:30:51 +0000 Subject: [CI] Update Github Actions (backport #2876) (#2877) * [ci] Update Github Actions (#2876) * Switch from deprecated setup-scala to setup-java * Switch from deprecated set-output to $GITHUB_OUTPUT * Use $GITHUB_STEP_SUMMARY for reporting (cherry picked from commit b01dd3cb613a13da4befb66dd09a8c0ba1689b68) # Conflicts: # .github/workflows/test.yml * Resolve backport conflicts Co-authored-by: Jack Koenig --- .github/workflows/test.yml | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 69426662..a56fa85f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -16,14 +16,14 @@ jobs: strategy: matrix: system: ["ubuntu-20.04"] - jvm: ["adopt@1.8"] + jvm: ["8"] scala: ["2.13.10", "2.12.17"] espresso: ["2.4"] runs-on: ${{ matrix.system }} steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Install Tabby OSS Cad Suite (from YosysHQ) uses: YosysHQ/setup-oss-cad-suite@v1 @@ -39,11 +39,11 @@ jobs: espresso || true - name: Setup Scala - uses: olafurpg/setup-scala@v10 + uses: actions/setup-java@v3 with: + distribution: 'adopt' java-version: ${{ matrix.jvm }} - - name: Cache Scala - uses: coursier/cache-action@v5 + cache: 'sbt' - name: Use Treadle for Pull Requests if: github.event_name == 'pull_request' run: echo "CHISEL3_CI_USE_TREADLE=1" >> $GITHUB_ENV @@ -57,13 +57,13 @@ jobs: runs-on: ubuntu-20.04 steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Setup Scala - uses: olafurpg/setup-scala@v10 + uses: actions/setup-java@v3 with: - java-version: "adopt@1.11" - - name: Cache Scala - uses: coursier/cache-action@v5 + distribution: 'adopt' + java-version: '11' + cache: 'sbt' - name: Check Formatting run: sbt scalafmtCheckAll - name: Documentation @@ -74,7 +74,7 @@ jobs: runs-on: ubuntu-20.04 steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Install Tabby OSS Cad Suite (from YosysHQ) uses: YosysHQ/setup-oss-cad-suite@v1 with: @@ -87,11 +87,11 @@ jobs: sudo mv x86_64-linux-gnu-espresso /usr/local/bin/espresso espresso || true - name: Setup Scala - uses: olafurpg/setup-scala@v10 + uses: actions/setup-java@v3 with: - java-version: "adopt@1.11" - - name: Cache Scala - uses: coursier/cache-action@v5 + distribution: 'adopt' + java-version: '11' + cache: 'sbt' - name: Integration Tests run: sbt integrationTests/test @@ -108,7 +108,7 @@ jobs: success: ${{ steps.setoutput.outputs.success }} steps: - id: setoutput - run: echo "::set-output name=success::true" + run: echo "success=true" >> $GITHUB_OUTPUT # Related to check-tests above, this job _always_ runs (even if tests fail # and thus check-steps is skipped). This two sentinel job approach avoids an @@ -126,10 +126,10 @@ jobs: - run: | PASSED="${{ needs.check-tests.outputs.success }}" if [[ $PASSED == "true" ]]; then - echo "All tests passed!" + echo "### All tests passed! :rocket:" >> $GITHUB_STEP_SUMMARY exit 0 else - echo "One or more tests FAILED!" + echo "### One or more tests FAILED! :bangbang:" >> $GITHUB_STEP_SUMMARY exit 1 fi @@ -142,13 +142,13 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Setup Scala - uses: olafurpg/setup-scala@v10 + uses: actions/setup-java@v3 with: - java-version: adopt@1.8 - - name: Cache Scala - uses: coursier/cache-action@v5 + distribution: 'adopt' + java-version: '8' + cache: 'sbt' - name: Setup GPG (for Publish) uses: olafurpg/setup-gpg@v3 - name: Publish -- cgit v1.2.3 From 294bf10510b2dc55312be2e87f9bed556c68afc5 Mon Sep 17 00:00:00 2001 From: mergify[bot] Date: Thu, 8 Dec 2022 22:17:33 +0000 Subject: Replay changes on 3.5.x (#2865) Co-authored-by: Aditya Naik --- core/src/main/scala/chisel3/IO.scala | 41 ++++++++++++++++++++++ core/src/main/scala/chisel3/Module.scala | 38 ++------------------ .../main/scala/chisel3/experimental/package.scala | 2 +- 3 files changed, 45 insertions(+), 36 deletions(-) create mode 100644 core/src/main/scala/chisel3/IO.scala diff --git a/core/src/main/scala/chisel3/IO.scala b/core/src/main/scala/chisel3/IO.scala new file mode 100644 index 00000000..1a28db1e --- /dev/null +++ b/core/src/main/scala/chisel3/IO.scala @@ -0,0 +1,41 @@ +package chisel3 + +import chisel3.internal.requireIsChiselType // Fix ambiguous import +import chisel3.internal.Builder +import chisel3.internal.sourceinfo.SourceInfo + +object IO { + + /** Constructs a port for the current Module + * + * This must wrap the datatype used to set the io field of any Module. + * i.e. All concrete modules must have defined io in this form: + * [lazy] val io[: io type] = IO(...[: io type]) + * + * Items in [] are optional. + * + * The granted iodef must be a chisel type and not be bound to hardware. + * + * Also registers a Data as a port, also performing bindings. Cannot be called once ports are + * requested (so that all calls to ports will return the same information). + * Internal API. + */ + def apply[T <: Data](iodef: T): T = { + val module = Module.currentModule.get // Impossible to fail + require(!module.isClosed, "Can't add more ports after module close") + requireIsChiselType(iodef, "io type") + + // Clone the IO so we preserve immutability of data types + val iodefClone = + try { + iodef.cloneTypeFull + } catch { + // For now this is going to be just a deprecation so we don't suddenly break everyone's code + case e: AutoClonetypeException => + Builder.deprecated(e.getMessage, Some(s"${iodef.getClass}")) + iodef + } + module.bindIoInPlace(iodefClone) + iodefClone + } +} diff --git a/core/src/main/scala/chisel3/Module.scala b/core/src/main/scala/chisel3/Module.scala index e5c2a848..a2d5cec6 100644 --- a/core/src/main/scala/chisel3/Module.scala +++ b/core/src/main/scala/chisel3/Module.scala @@ -200,42 +200,10 @@ 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. - * i.e. All concrete modules must have defined io in this form: - * [lazy] val io[: io type] = IO(...[: io type]) - * - * Items in [] are optional. - * - * The granted iodef must be a chisel type and not be bound to hardware. - * - * Also registers a Data as a port, also performing bindings. Cannot be called once ports are - * requested (so that all calls to ports will return the same information). - * Internal API. - */ + @deprecated("chisel3.experimental.IO is deprecated, use chisel3.IO instead", "Chisel 3.5") def apply[T <: Data](iodef: T): T = { - val module = Module.currentModule.get // Impossible to fail - require(!module.isClosed, "Can't add more ports after module close") - requireIsChiselType(iodef, "io type") - - // Clone the IO so we preserve immutability of data types - val iodefClone = - try { - iodef.cloneTypeFull - } catch { - // For now this is going to be just a deprecation so we don't suddenly break everyone's code - case e: AutoClonetypeException => - Builder.deprecated(e.getMessage, Some(s"${iodef.getClass}")) - iodef - } - module.bindIoInPlace(iodefClone) - iodefClone + chisel3.IO.apply(iodef) } } } @@ -753,7 +721,7 @@ package experimental { * TODO(twigg): Specifically walk the Data definition to call out which nodes * are problematic. */ - protected def IO[T <: Data](iodef: T): T = chisel3.experimental.IO.apply(iodef) + protected def IO[T <: Data](iodef: T): T = chisel3.IO.apply(iodef) // // Internal Functions diff --git a/core/src/main/scala/chisel3/experimental/package.scala b/core/src/main/scala/chisel3/experimental/package.scala index 39131943..42ec9666 100644 --- a/core/src/main/scala/chisel3/experimental/package.scala +++ b/core/src/main/scala/chisel3/experimental/package.scala @@ -72,7 +72,7 @@ package object experimental { val ports: Seq[Data] = gen.elements.toSeq.reverse.map { case (name, data) => - val p = IO(coerceDirection(chiselTypeClone(data).asInstanceOf[Data])) + val p = chisel3.IO(coerceDirection(chiselTypeClone(data).asInstanceOf[Data])) p.suggestName(name) p -- cgit v1.2.3 From 044b062468c90a1084221e480463515c668e99df Mon Sep 17 00:00:00 2001 From: mergify[bot] Date: Sat, 10 Dec 2022 10:45:37 +0000 Subject: Fix string interpolation in `util.exprimental.decode.bitset` (#2882) (#2883) * Fix BitSet decoder API when errorBit=False When errorBit is set to False, the original code will return `Unit` which will be `()` in interpolated string. * Add testcases for both errorBit cases in BitSetSpec (cherry picked from commit 42416cb6c6a3019fc29b9d98cfea3e3bb4e42684) Co-authored-by: Ocean Shen <30361859+OceanS2000@users.noreply.github.com>--- .../chisel3/util/experimental/decode/decoder.scala | 6 +++-- src/test/scala/chiselTests/util/BitSetSpec.scala | 29 +++++++++++++++++++++- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/main/scala/chisel3/util/experimental/decode/decoder.scala b/src/main/scala/chisel3/util/experimental/decode/decoder.scala index 067dd6f8..ce2da3c0 100644 --- a/src/main/scala/chisel3/util/experimental/decode/decoder.scala +++ b/src/main/scala/chisel3/util/experimental/decode/decoder.scala @@ -107,8 +107,10 @@ 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}") - } ++ Seq(s"${if (errorBit) "1"}${"?" * bitSets.size}") + bs.terms.map(bp => + s"${bp.rawString}->${if (errorBit) "0" else ""}${"0" * (bitSets.size - i - 1)}1${"0" * i}" + ) + } ++ Seq(s"${if (errorBit) "1" ++ "0" * bitSets.size else "?" * bitSets.size}") }.mkString("\n") ) ) diff --git a/src/test/scala/chiselTests/util/BitSetSpec.scala b/src/test/scala/chiselTests/util/BitSetSpec.scala index dd66ba40..cf5f54cf 100644 --- a/src/test/scala/chiselTests/util/BitSetSpec.scala +++ b/src/test/scala/chiselTests/util/BitSetSpec.scala @@ -110,9 +110,36 @@ class BitSetSpec extends AnyFlatSpec with Matchers { "b11??????" ) ), - true + errorBit = true ) }) } + it should "be decoded with DontCare error" in { + import chisel3._ + import chisel3.util.experimental.decode.decoder + // [0 - 256] part into: [0 - 31], [32 - 47, 64 - 127], [192 - 255] + // "0011????" "10??????" is empty to error + 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?????" + ), + BitSet.fromString( + """b0010???? + |b01?????? + |""".stripMargin + ), + BitSet.fromString( + "b11??????" + ) + ), + errorBit = false + ) + }) + } } -- cgit v1.2.3 From fb6ff513f42187c600c57fcaed162110404e8cf6 Mon Sep 17 00:00:00 2001 From: mergify[bot] Date: Tue, 20 Dec 2022 00:20:33 +0000 Subject: Switch from YosysHQ action to reusable workflow (backport #2901) (#2902) * Switch from YosysHQ action to composite action (#2901) The YosysHQ Github Action for setting up the OSS CAD Suite is very flaky in CI so instead we can just wget and untar the suite ourselves. It also seems prudent to try out composite actions to avoid duplication of installation steps. (cherry picked from commit 75aeaed9efaf1ca35573775cd21ea3b5e89e9442) # Conflicts: # .github/workflows/test.yml * Resolve backport conflicts Co-authored-by: Jack Koenig --- .github/workflows/setup-oss-cad-suite/action.yml | 14 ++++++++++++++ .github/workflows/test.yml | 14 ++++---------- 2 files changed, 18 insertions(+), 10 deletions(-) create mode 100644 .github/workflows/setup-oss-cad-suite/action.yml diff --git a/.github/workflows/setup-oss-cad-suite/action.yml b/.github/workflows/setup-oss-cad-suite/action.yml new file mode 100644 index 00000000..9383d56b --- /dev/null +++ b/.github/workflows/setup-oss-cad-suite/action.yml @@ -0,0 +1,14 @@ +name: Setup OSS CAD Suite + +runs: + using: composite + steps: + - name: Install Tabby OSS Cad Suite + shell: bash + env: + VERSION: 2021-11-09 + run: | + ARTIFACT=oss-cad-suite-linux-x64-$(echo $VERSION | tr -d '-') + wget -q -O - https://github.com/YosysHQ/oss-cad-suite-build/releases/download/${VERSION}/${ARTIFACT}.tgz | tar -zx + echo "$(pwd)/oss-cad-suite/bin" >> $GITHUB_PATH + diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a56fa85f..fee7019e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -24,12 +24,8 @@ jobs: steps: - name: Checkout uses: actions/checkout@v3 - - - name: Install Tabby OSS Cad Suite (from YosysHQ) - uses: YosysHQ/setup-oss-cad-suite@v1 - with: - osscadsuite-version: '2021-11-09' - + - name: Install Tabby OSS Cad Suite + uses: ./.github/workflows/setup-oss-cad-suite - name: Install Espresso run: | cd /tmp @@ -75,10 +71,8 @@ jobs: steps: - name: Checkout uses: actions/checkout@v3 - - name: Install Tabby OSS Cad Suite (from YosysHQ) - uses: YosysHQ/setup-oss-cad-suite@v1 - with: - osscadsuite-version: '2021-11-09' + - name: Install Tabby OSS Cad Suite + uses: ./.github/workflows/setup-oss-cad-suite - name: Install Espresso run: | cd /tmp -- cgit v1.2.3 From b913a75beb10adf4421d22ae386cbb29d144b774 Mon Sep 17 00:00:00 2001 From: mergify[bot] Date: Tue, 20 Dec 2022 15:53:29 +0000 Subject: DRY out CI (backport #2903) (#2905) * DRY out CI (#2903) * Minor tweaks to setup-oss-cad-suite * Switch espresso installation to composite action * Switch circt installation to composite action (cherry picked from commit dbd5f48a884a236f95c8476d56e28ca911b64a8d) # Conflicts: # .github/workflows/test.yml * resolve backport conflicts Co-authored-by: Jack Koenig --- .github/workflows/install-espresso/action.yml | 25 ++++++++++++++++++++++++ .github/workflows/setup-oss-cad-suite/action.yml | 24 ++++++++++++++++++----- .github/workflows/test.yml | 17 ++++------------ 3 files changed, 48 insertions(+), 18 deletions(-) create mode 100644 .github/workflows/install-espresso/action.yml diff --git a/.github/workflows/install-espresso/action.yml b/.github/workflows/install-espresso/action.yml new file mode 100644 index 00000000..fb1d655a --- /dev/null +++ b/.github/workflows/install-espresso/action.yml @@ -0,0 +1,25 @@ +name: Install Espresso + +inputs: + version: + description: 'version to install' + required: false + default: '2.4' + +runs: + using: composite + steps: + - id: cache-espresso + uses: actions/cache@v3 + with: + path: /usr/local/bin/espresso + key: espresso-${{ runner.os }}-${{ inputs.version }} + + - shell: bash + if: steps.cache-espresso.outputs.cache-hit != 'true' + run: | + cd /tmp + wget -q https://github.com/chipsalliance/espresso/releases/download/v${{ inputs.version }}/x86_64-linux-gnu-espresso + chmod +x x86_64-linux-gnu-espresso + sudo mv x86_64-linux-gnu-espresso /usr/local/bin/espresso + espresso || true diff --git a/.github/workflows/setup-oss-cad-suite/action.yml b/.github/workflows/setup-oss-cad-suite/action.yml index 9383d56b..63d70e92 100644 --- a/.github/workflows/setup-oss-cad-suite/action.yml +++ b/.github/workflows/setup-oss-cad-suite/action.yml @@ -1,14 +1,28 @@ name: Setup OSS CAD Suite +inputs: + version: + description: 'version to install' + required: false + default: '2021-11-09' + runs: using: composite steps: - - name: Install Tabby OSS Cad Suite - shell: bash - env: - VERSION: 2021-11-09 + - id: cache-oss-cad-suite + uses: actions/cache@v3 + with: + path: oss-cad-suite + key: oss-cad-suite-${{ runner.os }}-${{ inputs.version }} + + - shell: bash + if: steps.cache-oss-cad-suite.outputs.cache-hit != 'true' run: | + VERSION=${{ inputs.version }} ARTIFACT=oss-cad-suite-linux-x64-$(echo $VERSION | tr -d '-') wget -q -O - https://github.com/YosysHQ/oss-cad-suite-build/releases/download/${VERSION}/${ARTIFACT}.tgz | tar -zx - echo "$(pwd)/oss-cad-suite/bin" >> $GITHUB_PATH + + # Add the CAD Suite to the PATH + - shell: bash + run: echo "$(pwd)/oss-cad-suite/bin" >> $GITHUB_PATH diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index fee7019e..dd129812 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -27,13 +27,9 @@ jobs: - name: Install Tabby OSS Cad Suite uses: ./.github/workflows/setup-oss-cad-suite - name: Install Espresso - run: | - cd /tmp - wget https://github.com/chipsalliance/espresso/releases/download/v${{ matrix.espresso }}/x86_64-linux-gnu-espresso - chmod +x x86_64-linux-gnu-espresso - sudo mv x86_64-linux-gnu-espresso /usr/local/bin/espresso - espresso || true - + uses: ./.github/workflows/install-espresso + with: + version: ${{ matrix.espresso }} - name: Setup Scala uses: actions/setup-java@v3 with: @@ -74,12 +70,7 @@ jobs: - name: Install Tabby OSS Cad Suite uses: ./.github/workflows/setup-oss-cad-suite - name: Install Espresso - run: | - cd /tmp - wget https://github.com/chipsalliance/espresso/releases/download/v2.4/x86_64-linux-gnu-espresso - chmod +x x86_64-linux-gnu-espresso - sudo mv x86_64-linux-gnu-espresso /usr/local/bin/espresso - espresso || true + uses: ./.github/workflows/install-espresso - name: Setup Scala uses: actions/setup-java@v3 with: -- cgit v1.2.3 From 116210ff806ccdda91b4c3343f78bad66783d0e6 Mon Sep 17 00:00:00 2001 From: mergify[bot] Date: Sat, 24 Dec 2022 17:45:37 +0000 Subject: FlatIOSpec: make sure the Analog test is using FLatIO (#2909) (#2910) (cherry picked from commit b91a2050aeb143aa80762dfb1b40f1e5035de4b5) Co-authored-by: Megan Wachs --- src/test/scala/chiselTests/experimental/FlatIOSpec.scala | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/test/scala/chiselTests/experimental/FlatIOSpec.scala b/src/test/scala/chiselTests/experimental/FlatIOSpec.scala index ebb7cbdb..fb3f64c7 100644 --- a/src/test/scala/chiselTests/experimental/FlatIOSpec.scala +++ b/src/test/scala/chiselTests/experimental/FlatIOSpec.scala @@ -55,9 +55,11 @@ class FlatIOSpec extends ChiselFlatSpec { val bar = Analog(8.W) } class MyModule extends RawModule { - val in = IO(Flipped(new MyBundle)) - val out = IO(new MyBundle) - out <> in + val io = FlatIO(new Bundle { + val in = Flipped(new MyBundle) + val out = new MyBundle + }) + io.out <> io.in } val chirrtl = emitChirrtl(new MyModule) chirrtl should include("out.foo <= in.foo") -- cgit v1.2.3