diff options
| author | mergify[bot] | 2022-06-13 19:11:33 +0000 |
|---|---|---|
| committer | GitHub | 2022-06-13 19:11:33 +0000 |
| commit | 13641d95951b189d7f5b0d4d99ace45f8b8f6282 (patch) | |
| tree | 863345c541b7edac7b04b717e0690506c120ea14 | |
| parent | 4b8981d627fc307161ff39b78836e37212803756 (diff) | |
Add ImplicitInvalidate, to help migrate the explicitInvalidate compiler option (#2575) (#2579)
* Added ImplicitInvalidate trait with tests
(cherry picked from commit 1356ced1b89ca35ae0cb1d1ab45227ec1776d5e7)
Co-authored-by: Adam Izraelevitz <adam.izraelevitz@sifive.com>
| -rw-r--r-- | core/src/main/scala/chisel3/Data.scala | 2 | ||||
| -rw-r--r-- | core/src/main/scala/chisel3/Module.scala | 2 | ||||
| -rw-r--r-- | core/src/main/scala/chisel3/RawModule.scala | 7 | ||||
| -rw-r--r-- | src/test/scala/chiselTests/MigrateCompileOptionsSpec.scala | 138 |
4 files changed, 121 insertions, 28 deletions
diff --git a/core/src/main/scala/chisel3/Data.scala b/core/src/main/scala/chisel3/Data.scala index f468335e..77ad66ef 100644 --- a/core/src/main/scala/chisel3/Data.scala +++ b/core/src/main/scala/chisel3/Data.scala @@ -866,7 +866,7 @@ trait WireFactory { x.bind(WireBinding(Builder.forcedUserModule, Builder.currentWhen)) pushCommand(DefWire(sourceInfo, x)) - if (!compileOptions.explicitInvalidate) { + if (!compileOptions.explicitInvalidate || Builder.currentModule.get.isInstanceOf[ImplicitInvalidate]) { pushCommand(DefInvalid(sourceInfo, x.ref)) } diff --git a/core/src/main/scala/chisel3/Module.scala b/core/src/main/scala/chisel3/Module.scala index 08286ed5..d03122f9 100644 --- a/core/src/main/scala/chisel3/Module.scala +++ b/core/src/main/scala/chisel3/Module.scala @@ -386,7 +386,7 @@ package internal { clonePorts.setAllParents(Some(cloneParent)) cloneParent._portsRecord = clonePorts // Normally handled during Module construction but ClonePorts really lives in its parent's parent - if (!compileOptions.explicitInvalidate) { + if (!compileOptions.explicitInvalidate || Builder.currentModule.get.isInstanceOf[ImplicitInvalidate]) { // FIXME This almost certainly doesn't work since clonePorts is not a real thing... pushCommand(DefInvalid(sourceInfo, clonePorts.ref)) } diff --git a/core/src/main/scala/chisel3/RawModule.scala b/core/src/main/scala/chisel3/RawModule.scala index 164d3880..bd04fdc4 100644 --- a/core/src/main/scala/chisel3/RawModule.scala +++ b/core/src/main/scala/chisel3/RawModule.scala @@ -147,7 +147,7 @@ abstract class RawModule(implicit moduleCompileOptions: CompileOptions) extends // Generate IO invalidation commands to initialize outputs as unused, // unless the client wants explicit control over their generation. val invalidateCommands = { - if (!compileOptions.explicitInvalidate) { + if (!compileOptions.explicitInvalidate || this.isInstanceOf[ImplicitInvalidate]) { getModulePorts.map { port => DefInvalid(UnlocatableSourceInfo, port.ref) } } else { Seq() @@ -161,7 +161,7 @@ abstract class RawModule(implicit moduleCompileOptions: CompileOptions) extends private[chisel3] def initializeInParent(parentCompileOptions: CompileOptions): Unit = { implicit val sourceInfo = UnlocatableSourceInfo - if (!parentCompileOptions.explicitInvalidate) { + if (!parentCompileOptions.explicitInvalidate || Builder.currentModule.get.isInstanceOf[ImplicitInvalidate]) { for (port <- getModulePorts) { pushCommand(DefInvalid(sourceInfo, port.ref)) } @@ -177,6 +177,9 @@ trait RequireSyncReset extends Module { override private[chisel3] def mkReset: Bool = Bool() } +/** Mix with a [[RawModule]] to automatically connect DontCare to the module's ports, wires, and children instance IOs. */ +trait ImplicitInvalidate { self: RawModule => } + package object internal { import scala.annotation.implicitNotFound diff --git a/src/test/scala/chiselTests/MigrateCompileOptionsSpec.scala b/src/test/scala/chiselTests/MigrateCompileOptionsSpec.scala index 3757c360..091f7f28 100644 --- a/src/test/scala/chiselTests/MigrateCompileOptionsSpec.scala +++ b/src/test/scala/chiselTests/MigrateCompileOptionsSpec.scala @@ -3,41 +3,131 @@ package chiselTests import chisel3.stage.ChiselStage +import chisel3.ImplicitInvalidate +import chisel3.ExplicitCompileOptions import org.scalatestplus.scalacheck.ScalaCheckDrivenPropertyChecks -class MigrateCompileOptionsSpec extends ChiselFlatSpec with ScalaCheckDrivenPropertyChecks with Utils { - import Chisel.{defaultCompileOptions => _, _} - import chisel3.RequireSyncReset +object MigrationExamples { + object InferResets { + import Chisel.{defaultCompileOptions => _, _} + import chisel3.RequireSyncReset + implicit val migrateIR = new chisel3.CompileOptions { + val connectFieldsMustMatch = false + val declaredTypeMustBeUnbound = false + val dontTryConnectionsSwapped = false + val dontAssumeDirectionality = false + val checkSynthesizable = false + val explicitInvalidate = false + val inferModuleReset = false - behavior.of("Migrating infer resets") + override val migrateInferModuleReset = true + } - val migrateIR = new chisel3.CompileOptions { - val connectFieldsMustMatch = false - val declaredTypeMustBeUnbound = false - val dontTryConnectionsSwapped = false - val dontAssumeDirectionality = false - val checkSynthesizable = false - val explicitInvalidate = false - val inferModuleReset = false + class Foo extends Module { + val io = new Bundle {} + } + class FooWithRequireSyncReset extends Module with RequireSyncReset { + val io = new Bundle {} + } + } + object ExplicitInvalidate { + import chisel3.ImplicitInvalidate + val migrateEI = new chisel3.CompileOptions { + val connectFieldsMustMatch = false + val declaredTypeMustBeUnbound = false + val dontTryConnectionsSwapped = false + val dontAssumeDirectionality = false + val checkSynthesizable = false + val explicitInvalidate = true + val inferModuleReset = false + } + object ChiselChildren { + import Chisel.{defaultCompileOptions => _, _} + implicit val options = migrateEI + class Foo extends Module { + val io = new Bundle { + val out = Output(UInt(width = 3)) + } + } + class FooWithImplicitInvalidate extends Module with ImplicitInvalidate { + val io = new Bundle { + val out = Output(UInt(width = 3)) + } + } + class FooWire extends Module { + val io = new Bundle {} + val wire = Wire(Bool()) + } + class FooWireWithImplicitInvalidate extends Module with ImplicitInvalidate { + val io = new Bundle {} + val wire = Wire(Bool()) + } + } + object chisel3Children { + import chisel3._ + class Foo extends Module { + val in = IO(chisel3.Input(UInt(3.W))) + } + } + object ChiselParents { + import Chisel.{defaultCompileOptions => _, _} + implicit val options = migrateEI - override val migrateInferModuleReset = true + class FooParent extends Module { + val io = new Bundle {} + val i = Module(new chisel3Children.Foo) + } + class FooParentWithImplicitInvalidate extends Module with ImplicitInvalidate { + val io = new Bundle {} + val i = Module(new chisel3Children.Foo) + } + } } +} - it should "error if migrating, but not extended RequireSyncReset" in { - implicit val options = migrateIR - class Foo extends Module { - val io = new Bundle {} +class MigrateCompileOptionsSpec extends ChiselFunSpec with Utils { + import Chisel.{defaultCompileOptions => _, _} + import chisel3.RequireSyncReset + + describe("(0): Migrating infer resets") { + import MigrationExamples.InferResets._ + it("(0.a): Error if migrating, but not extended RequireSyncReset") { + intercept[Exception] { ChiselStage.elaborate(new Foo) } } - intercept[Exception] { - ChiselStage.elaborate(new Foo) + it("(0.b): Not error if migrating, and you mix with RequireSyncReset") { + ChiselStage.elaborate(new FooWithRequireSyncReset) } } - it should "not error if migrating, and you mix with RequireSyncReset" in { - implicit val options = migrateIR - class Foo extends Module with RequireSyncReset { - val io = new Bundle {} + + describe("(1): Migrating explicit invalidate") { + import MigrationExamples.ExplicitInvalidate._ + + it("(1.a): error if migrating module input, but not extending ImplicitInvalidate") { + intercept[_root_.firrtl.passes.CheckInitialization.RefNotInitializedException] { + ChiselStage.emitVerilog(new ChiselChildren.Foo) + } + } + it("(1.b): succeed if migrating module input with extending ImplicitInvalidate") { + ChiselStage.emitVerilog(new ChiselChildren.FooWithImplicitInvalidate) + } + + it("(1.c): error if migrating instance output, but not extending ImplicitInvalidate") { + intercept[_root_.firrtl.passes.CheckInitialization.RefNotInitializedException] { + ChiselStage.emitVerilog(new ChiselParents.FooParent) + } + } + it("(1.d): succeed if migrating instance output with extending ImplicitInvalidate") { + ChiselStage.emitVerilog(new ChiselParents.FooParentWithImplicitInvalidate) + } + + it("(1.e): error if migrating wire declaration, but not extending ImplicitInvalidate") { + intercept[_root_.firrtl.passes.CheckInitialization.RefNotInitializedException] { + ChiselStage.emitVerilog(new ChiselChildren.FooWire) + } + } + it("(1.f): succeed if migrating wire declaration with extending ImplicitInvalidate") { + ChiselStage.emitVerilog(new ChiselChildren.FooWireWithImplicitInvalidate) } - ChiselStage.elaborate(new Foo) } } |
