// SPDX-License-Identifier: Apache-2.0 package chiselTests import chisel3._ import chisel3.CompileOptions._ import chisel3.stage.ChiselStage class CompileOptionsSpec extends ChiselFlatSpec with Utils { abstract class StrictModule extends Module()(chisel3.ExplicitCompileOptions.Strict) abstract class NotStrictModule extends Module()(chisel3.ExplicitCompileOptions.NotStrict) class SmallBundle extends Bundle { val f1 = UInt(4.W) val f2 = UInt(5.W) } class BigBundle extends SmallBundle { val f3 = UInt(6.W) } "A Module with missing bundle fields when compiled with implicit Strict.CompileOption " should "throw an exception" in { a[ChiselException] should be thrownBy extractCause[ChiselException] { import chisel3.ExplicitCompileOptions.Strict class ConnectFieldMismatchModule extends Module { val io = IO(new Bundle { val in = Input(new SmallBundle) val out = Output(new BigBundle) }) io.out := io.in } ChiselStage.elaborate { new ConnectFieldMismatchModule() } } } "A Module with missing bundle fields when compiled with implicit NotStrict.CompileOption " should "not throw an exception" in { import chisel3.ExplicitCompileOptions.NotStrict class ConnectFieldMismatchModule extends Module { val io = IO(new Bundle { val in = Input(new SmallBundle) val out = Output(new BigBundle) }) io.out := io.in } ChiselStage.elaborate { new ConnectFieldMismatchModule() } } "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] { import chisel3.ExplicitCompileOptions.Strict class CreateRegFromBoundTypeModule extends Module { val io = IO(new Bundle { val in = Input(new SmallBundle) val out = Output(new BigBundle) }) val badReg = Reg(7.U(4.W)) } ChiselStage.elaborate { new CreateRegFromBoundTypeModule() } } } "A Module in which a Reg is created with a bound type when compiled with implicit NotStrict.CompileOption " should "not throw an exception" in { import chisel3.ExplicitCompileOptions.NotStrict class CreateRegFromBoundTypeModule extends Module { val io = IO(new Bundle { val in = Input(new SmallBundle) val out = Output(new BigBundle) }) val badReg = Reg(7.U(4.W)) } ChiselStage.elaborate { new CreateRegFromBoundTypeModule() } } "A Module with wrapped IO when compiled with implicit Strict.CompileOption " should "not throw an exception" in { import chisel3.ExplicitCompileOptions.Strict class RequireIOWrapModule extends Module { val io = IO(new Bundle { val in = Input(UInt(32.W)) val out = Output(Bool()) }) io.out := io.in(1) } ChiselStage.elaborate { new RequireIOWrapModule() } } "A Module with unwrapped IO when compiled with implicit Strict.CompileOption " should "throw an exception" in { a[BindingException] should be thrownBy extractCause[BindingException] { import chisel3.ExplicitCompileOptions.Strict class RequireIOWrapModule extends Module { val io = new Bundle { val in = Input(UInt(32.W)) val out = Output(Bool()) } io.out := io.in(1) } ChiselStage.elaborate { new RequireIOWrapModule() } } } "A Module connecting output as source to input as sink when compiled with implicit Strict.CompileOption " should "throw an exception" in { a[ChiselException] should be thrownBy extractCause[ChiselException] { import chisel3.ExplicitCompileOptions.Strict class SimpleModule extends Module { val io = IO(new Bundle { val in = Input(UInt(3.W)) val out = Output(UInt(4.W)) }) } class SwappedConnectionModule extends SimpleModule { val child = Module(new SimpleModule) io.in := child.io.out } ChiselStage.elaborate { new SwappedConnectionModule() } } } "A Module connecting output as source to input as sink when compiled with implicit NotStrict.CompileOption " should "not throw an exception" in { import chisel3.ExplicitCompileOptions.NotStrict class SimpleModule extends Module { val io = IO(new Bundle { val in = Input(UInt(3.W)) val out = Output(UInt(4.W)) }) } class SwappedConnectionModule extends SimpleModule { val child = Module(new SimpleModule) io.in := child.io.out } ChiselStage.elaborate { new SwappedConnectionModule() } } "A Module with directionless connections when compiled with implicit Strict.CompileOption " should "throw an exception" in { a[ChiselException] should be thrownBy extractCause[ChiselException] { // Verify we can suppress the inclusion of default compileOptions import Chisel.{defaultCompileOptions => _} import chisel3.ExplicitCompileOptions.Strict class SimpleModule extends Module { val io = IO(new Bundle { val in = Input(UInt(3.W)) val out = Output(UInt(4.W)) }) val noDir = Wire(UInt(3.W)) } class DirectionLessConnectionModule extends SimpleModule { val a = 0.U(3.W) val b = Wire(UInt(3.W)) val child = Module(new SimpleModule) b := child.noDir } ChiselStage.elaborate { new DirectionLessConnectionModule() } } } "Strict.copy()" should "be equivalent in all CompileOptions traits" in { import chisel3.ExplicitCompileOptions.Strict val copiedCompileOptions = Strict.copy() assert(copiedCompileOptions.connectFieldsMustMatch == Strict.connectFieldsMustMatch) assert(copiedCompileOptions.declaredTypeMustBeUnbound == Strict.declaredTypeMustBeUnbound) assert(copiedCompileOptions.dontTryConnectionsSwapped == Strict.dontTryConnectionsSwapped) assert(copiedCompileOptions.dontAssumeDirectionality == Strict.dontAssumeDirectionality) assert(copiedCompileOptions.checkSynthesizable == Strict.checkSynthesizable) assert(copiedCompileOptions.explicitInvalidate == Strict.explicitInvalidate) assert(copiedCompileOptions.inferModuleReset == Strict.inferModuleReset) assert(copiedCompileOptions.migrateInferModuleReset == Strict.migrateInferModuleReset) assert(copiedCompileOptions.emitStrictConnects == Strict.emitStrictConnects) } "NotStrict.copy()" should "be equivalent in all CompileOptions traits" in { import chisel3.ExplicitCompileOptions.NotStrict val copiedCompileOptions = NotStrict.copy() assert(copiedCompileOptions.connectFieldsMustMatch == NotStrict.connectFieldsMustMatch) assert(copiedCompileOptions.declaredTypeMustBeUnbound == NotStrict.declaredTypeMustBeUnbound) assert(copiedCompileOptions.dontTryConnectionsSwapped == NotStrict.dontTryConnectionsSwapped) assert(copiedCompileOptions.dontAssumeDirectionality == NotStrict.dontAssumeDirectionality) assert(copiedCompileOptions.checkSynthesizable == NotStrict.checkSynthesizable) assert(copiedCompileOptions.explicitInvalidate == NotStrict.explicitInvalidate) assert(copiedCompileOptions.inferModuleReset == NotStrict.inferModuleReset) assert(copiedCompileOptions.migrateInferModuleReset == NotStrict.migrateInferModuleReset) assert(copiedCompileOptions.emitStrictConnects == NotStrict.emitStrictConnects) } }