Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: chipsalliance/chisel
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: main
Choose a base ref
...
head repository: rameloni/chisel
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: tywaves-develop
Choose a head ref

Commits on Apr 18, 2024

  1. Annotate ports with Chisel type information in firrtl

    - Create `TywavesAnnotation` (firrtl) case class to represent the annotation
    - Add companion object to generate `TywavesChiselAnnotation`s for Chisel circuit: it parses a chisel circuit, extracts the necessary information from each component, and annotates each FIRRTL target
    - Support annotation for IO ports
    - Add support for modules and data types (grounds, aggregates, and user-defined (only extended bundles))
    - Support nested modules and data types
    - Create `AddTywavesAnnotations` phase to add the TywavesAnnotation to the elaborated Chisel circuit
    - Update `ChiselStage` to integrate `AddTywavesAnnotation` phase (run before `Convert` phase only if `withDebug` is true)
    - Added following tests:
            - Module tests:
    		- Empty module
    		- Module with submodule(s)
    		- Modules with parameters and paremetrized modules (need to extract scala meta-programming information though)
    		- BlackBoxes
    		- Intrinsics
    		- Classes
            - Ports test:
    		- Explict Clock, SyncReset (Bool), AsyncReset and Reset
    		- Implicit clock and reset
    		- Ground types: Bool, UInt, SInt, Analog
    		- Bundles: empty, anonymous, user-defined, nested
    		- Vecs: 1-D, 2-D
    		- MixedVec
    		- Vecs of bundles
    		- Bundles of vecs
    rameloni committed Apr 18, 2024
    Copy the full SHA
    65a47f3 View commit details

Commits on Apr 19, 2024

  1. Annotate registers and wires with Chisel type information in firrtl

    - Added "createAnno" from DefWire, DefRef, DefRegInit case
    - Reorganize test structure making reusable modules for different bindings (IO, Reg, Wire)
    - Added following tests:
            - Ports tests:
    		- Ports inside a submodule
            - Wire/reg tests:
                    - Explict Clock, SyncReset (Bool), AsyncReset and Reset
    		- Implicit clock and reset
    		- Ground types: Bool, UInt, SInt
    		- Analog (only wires)
    		- Bundles: empty, anonymous, user-defined, nested
    		- Vecs: 1-D, 2-D
    		- MixedVec
    		- Vecs of bundles
    		- Bundles of vecs
    		- Wires/regs inside a submodule
    rameloni committed Apr 19, 2024
    Copy the full SHA
    18153de View commit details

Commits on Apr 21, 2024

  1. Refactor of TywavesAnnotationSpec test structure

    - Move module and data types tests in different subdirectories
    - Add readmes with output samples of the annotations
    rameloni committed Apr 21, 2024
    Copy the full SHA
    e6de3b6 View commit details
  2. Annotate Chisel Memories

    - Added "createAnno" from DefMemory, DefSeqMemory, FirrtlMemory and DefMemPort case
    - Implement "createAnnoMem" to create a TyeavesAnnotation for memory (a memory does not extend the Data type)
    - Return empty annotations from Connect, DefInvalid
    - Add warning message for "Unhandled circuit commands"
    - Added the following tests:
    	- ROM of ground type
    	- SyncReadMem (when UNUSED) of ground type, aggregate types (bundle)
    	- Mem (when UNUSED) of ground type, aggregate types (bundle)
    	- SRAM of ground type (with different combs of ports), aggregate types
    	- SyncReadMem (when USED) of ground type, aggregate types (this instantiate MPORT)
            - Mem (when USED) of ground type, aggregate types (this instantiate MPORT)
    rameloni committed Apr 21, 2024
    Copy the full SHA
    ff1de98 View commit details

Commits on Apr 22, 2024

  1. [Fix tywaves] type name a annotation for innertype in memories (case …

    …of Vecs)
    
    - Added the following tests:
    	- Masked memories (SyncReadMem, Mem, SRAM)
    rameloni committed Apr 22, 2024
    Copy the full SHA
    017ecef View commit details

Commits on Apr 24, 2024

  1. Annotate types with the parameters (name, type, value) in the scala c…

    …onstructor (it works for any scala class)
    
    [Fix tywaves] Fix annotation issue for first parameter of the constructor
    
    Sometimes the first parameters was skipped. The `getConstructorParams` was dropping the first element of the list assuming that it contained the class itself and not a parameter.
    This assumption worked only for some cases ("$outer" is not always present in first position). Now the method is improved by doing a filter map (collect).
    
    Update report output samples in tests readmes
    
    Annotate types with parameters in the scala constructor (it works for any scala class)
    
    - Create a case class (`ClassParam`) to represent the parameters of a class in the firrtl annotation
    - Update `TywavesAnnotation` with `params: Option[Seq[ClassParam]]`. Some classes may not have any parameter
    - Implement `getConstructorParams()` to get params of a constructor of any scala class. It uses scala reflection.
    - Added the following tests:
    	- Test getConstructorParams() for:
    		- classes
    		- case classes
    		- private, protected and public fields in the constructor: name, type and value accessible
    		- fields in the body of a class (expected behaviour not accessible)
    		- parameters in the constructor (no val): only name and type accessible
    - Updated the following tests:
    	- Vec tests of DataTypesSpec: chisel Vecs have a length parameter in the constructor
    	- Mem tests: memories contain constructs with parameters in their constructors
    	- Module tests: update the module with parameters test
    rameloni committed Apr 24, 2024
    Copy the full SHA
    d4d6331 View commit details

Commits on Apr 25, 2024

  1. Fix behaviour of getConstructorParams when the value of a parameter i…

    …s type of chisel3.Data
    
    Now it returns only the value without the complete name (packageName.type.name) of the parameter.
    
    - Fix hasParams: sometimes some parameters of a class were not detected.
    - Added the following tests:
            - Circuit with parameters (scala basic types, scala classes, and chisel types)
            - Bundles with parameters (scala basic types, scala classes, and chisel types)
    - Updated tests (scala fmt and bug fix):
            - TypeAnnotationMemSpec
            - TypeAnnotationModuleSpec
            - TypeAnnotationDataTypesSpec
    - Fix scalafmt errors
    rameloni committed Apr 25, 2024
    Copy the full SHA
    0353ef1 View commit details
  2. Copy the full SHA
    42678b5 View commit details

Commits on May 8, 2024

  1. Copy the full SHA
    4b734cb View commit details
  2. Fix test circuits

    rameloni committed May 8, 2024
    Copy the full SHA
    b11fb47 View commit details

Commits on Jun 2, 2024

  1. Fix TypeAnnotationMemSpec test. Run scala fmt

    rameloni committed Jun 2, 2024
    Copy the full SHA
    91108bf View commit details

Commits on Jun 27, 2024

  1. Merge branch 'chipsalliance:main' into tywaves-annotations

    rameloni authored Jun 27, 2024

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    a684fde View commit details

Commits on Jul 9, 2024

  1. Merge branch 'chipsalliance:main' into tywaves-annotations

    rameloni authored Jul 9, 2024

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    44b03b3 View commit details
  2. Rename tywaves package in tywavesinternal

    Solve any conflict with the package in tywaves-chisel-api.
    
    Fix rameloni/tywaves-chisel#27
    rameloni committed Jul 9, 2024
    Copy the full SHA
    2d57816 View commit details
  3. Annotate temporary nodes in when statements

    rameloni committed Jul 9, 2024
    Copy the full SHA
    41e0211 View commit details

Commits on Jul 11, 2024

  1. Copy the full SHA
    064e2f1 View commit details
  2. Document TywavesAnnotation.scala

    Fixes  #4
    rameloni committed Jul 11, 2024
    Copy the full SHA
    c289be6 View commit details
  3. Copy the full SHA
    69e9c76 View commit details
  4. [TywavesAnno] fix mem tests

    rameloni committed Jul 11, 2024
    Copy the full SHA
    3ed630f View commit details
  5. Copy the full SHA
    a8f30e8 View commit details
  6. Add circuit test with ChiselEnums

    rameloni committed Jul 11, 2024
    Copy the full SHA
    a713fda View commit details
411 changes: 411 additions & 0 deletions core/src/main/scala/chisel3/tywavesinternal/TywavesAnnotation.scala

Large diffs are not rendered by default.

35 changes: 35 additions & 0 deletions src/main/scala/chisel3/stage/phases/AddTywavesAnnotations.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package chisel3.stage.phases

import chisel3.stage.ChiselCircuitAnnotation
import chisel3.tywavesinternal.TywavesChiselAnnotation
import firrtl.AnnotationSeq
import firrtl.options.{Dependency, Phase}

// TODO: this phase should be added to the ChiselStage such that it is executed before
// Convert phase and run only if Tywaves is enabled. Otherwise, it should be skipped
// since it adds unnecessary annotations for other purposes.

/** This phase adds annotations to the Chisel circuit that will be propagated to FIRRTL and
* used by firtool to generate proper debug file format for Tywaves.
*
* - It parses the whole Chisel circuit
* - Extracts the necessary information from each component
* - Annotates each FIRRTL target
*/
class AddTywavesAnnotations extends Phase {

override def prerequisites = Seq(Dependency[Elaborate])
override def optionalPrerequisites = Seq.empty
override def optionalPrerequisiteOf = Seq(Dependency[MaybeInjectingPhase])
override def invalidates(a: Phase) = false

def transform(annotations: AnnotationSeq): AnnotationSeq = annotations.flatMap {
case a: ChiselCircuitAnnotation =>
// Generate the Tywaves annotations from the Chisel circuit
val anno = TywavesChiselAnnotation.generate(a.circuit)
val circuit = a.circuit.copy(annotations = a.circuit.annotations ++ anno)
// Some(a) ++
Some(ChiselCircuitAnnotation(circuit))
case a => Some(a)
}
}
22 changes: 14 additions & 8 deletions src/main/scala/circt/stage/ChiselStage.scala
Original file line number Diff line number Diff line change
@@ -15,7 +15,7 @@ import firrtl.EmittedBtor2CircuitAnnotation
*
* @note The companion object, [[ChiselStage$]], has a cleaner API for compiling and returning a string.
*/
class ChiselStage extends Stage {
class ChiselStage(withDebug: Boolean = false) extends Stage {

override def prerequisites = Seq.empty
override def optionalPrerequisites = Seq.empty
@@ -29,18 +29,24 @@ class ChiselStage extends Stage {

override def run(annotations: AnnotationSeq): AnnotationSeq = {

val pm = new PhaseManager(
targets = Seq(
Dependency[chisel3.stage.phases.AddImplicitOutputFile],
Dependency[chisel3.stage.phases.AddImplicitOutputAnnotationFile],
Dependency[chisel3.stage.phases.MaybeAspectPhase],
Dependency[chisel3.stage.phases.AddSerializationAnnotations],
val targets = Seq(
Dependency[chisel3.stage.phases.AddImplicitOutputFile],
Dependency[chisel3.stage.phases.AddImplicitOutputAnnotationFile],
Dependency[chisel3.stage.phases.MaybeAspectPhase],
Dependency[chisel3.stage.phases.AddSerializationAnnotations]
) ++
// TODO: make this working only if Tywaves is enabled
(if (withDebug) Seq(Dependency[chisel3.stage.phases.AddTywavesAnnotations]) else Seq.empty) ++
Seq(
Dependency[chisel3.stage.phases.Convert],
Dependency[chisel3.stage.phases.AddDedupGroupAnnotations],
Dependency[chisel3.stage.phases.MaybeInjectingPhase],
Dependency[circt.stage.phases.AddImplicitOutputFile],
Dependency[circt.stage.phases.CIRCT]
),
)

val pm = new PhaseManager(
targets = targets,
currentState = Seq(
Dependency[firrtl.stage.phases.AddDefaults],
Dependency[firrtl.stage.phases.Checks]
495 changes: 495 additions & 0 deletions src/test/scala/circtTests/tywavesTests/TywavesAnnotationCircuits.scala

Large diffs are not rendered by default.

455 changes: 455 additions & 0 deletions src/test/scala/circtTests/tywavesTests/dataTypesTests/README.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
package circtTests.tywavesTests.dataTypesTests

import chisel3._
import chisel3.stage.ChiselGeneratorAnnotation
import chisel3.tywavesinternal.ClassParam
import circt.stage.ChiselStage
import org.scalatest.funspec.AnyFunSpec
import org.scalatest.matchers.should.Matchers
import org.scalatest.exceptions.TestFailedException

class TypeAnnotationDataTypesSpec extends AnyFunSpec with Matchers with chiselTests.Utils {
import circtTests.tywavesTests.TywavesAnnotationCircuits.DataTypesCircuits._
import circtTests.tywavesTests.TywavesAnnotationCircuits.{BindingChoice, PortBinding, RegBinding, WireBinding}
import circtTests.tywavesTests.TestUtils._

def typeTests(args: Array[String], targetDir: os.Path, b: BindingChoice): Unit = {
def addClockReset(nameTop: String, nameInst: Option[String] = None) = if (b == RegBinding)
Seq(
(createExpected(s"~$nameTop\\|${nameInst.getOrElse(nameTop)}>clock", "Clock", "IO"), 1),
(createExpected(s"~$nameTop\\|${nameInst.getOrElse(nameTop)}>reset", "Reset", "IO"), 1)
)
else Seq.empty
it("should annotate ground types") {
(new ChiselStage(true)).execute(args, Seq(ChiselGeneratorAnnotation(() => new TopCircuitGroundTypes(b))))
val string = os.read(targetDir / "TopCircuitGroundTypes.fir")
val analog =
if (b != RegBinding)
Seq((createExpected("~TopCircuitGroundTypes\\|TopCircuitGroundTypes>analog", "Analog<1>", b.toString), 1))
else Seq.empty
val expectedMatches = Seq(
(createExpected("~TopCircuitGroundTypes\\|TopCircuitGroundTypes>uint", "UInt<8>", b.toString), 1),
(createExpected("~TopCircuitGroundTypes\\|TopCircuitGroundTypes>sint", "SInt<8>", b.toString), 1),
(createExpected("~TopCircuitGroundTypes\\|TopCircuitGroundTypes>bool", "Bool", b.toString), 1),
// TODO: there's no distinction between Bits and UInt since internally Bits.apply() returns UInt
(createExpected("~TopCircuitGroundTypes\\|TopCircuitGroundTypes>bits", "UInt<8>", b.toString), 1)
) ++ addClockReset("TopCircuitGroundTypes") ++ analog
checkAnno(expectedMatches, string)
}

it("should annotate bundles") {
new ChiselStage(true).execute(args, Seq(ChiselGeneratorAnnotation(() => new TopCircuitBundles(b))))
val string = os.read(targetDir / "TopCircuitBundles.fir")

val expectedMatches = Seq(
(createExpected("~TopCircuitBundles\\|TopCircuitBundles>a", "AnonymousBundle", b.toString), 1),
(createExpected("~TopCircuitBundles\\|TopCircuitBundles>b", "MyEmptyBundle", b.toString), 1),
(createExpected("~TopCircuitBundles\\|TopCircuitBundles>c", "MyBundle", b.toString), 1),
(createExpected("~TopCircuitBundles\\|TopCircuitBundles>c.a", "UInt<8>", b.toString), 1),
(createExpected("~TopCircuitBundles\\|TopCircuitBundles>c.b", "SInt<8>", b.toString), 1),
(createExpected("~TopCircuitBundles\\|TopCircuitBundles>c.c", "Bool", b.toString), 1)
) ++ addClockReset("TopCircuitBundles")
checkAnno(expectedMatches, string)
}

it("should annotate nested bundles") {
new ChiselStage(true)
.execute(args, Seq(ChiselGeneratorAnnotation(() => new TopCircuitBundlesNested(b))))
val string = os.read(targetDir / "TopCircuitBundlesNested.fir")
val expectedMatches = Seq(
(createExpected("~TopCircuitBundlesNested\\|TopCircuitBundlesNested>a", "MyNestedBundle", b.toString), 1),
(createExpected("~TopCircuitBundlesNested\\|TopCircuitBundlesNested>a.a", "Bool", b.toString), 1),
(createExpected("~TopCircuitBundlesNested\\|TopCircuitBundlesNested>a.b", "MyBundle", b.toString), 1),
(createExpected("~TopCircuitBundlesNested\\|TopCircuitBundlesNested>a.b.a", "UInt<8>", b.toString), 1),
(createExpected("~TopCircuitBundlesNested\\|TopCircuitBundlesNested>a.b.b", "SInt<8>", b.toString), 1),
(createExpected("~TopCircuitBundlesNested\\|TopCircuitBundlesNested>a.b.c", "Bool", b.toString), 1),
(createExpected("~TopCircuitBundlesNested\\|TopCircuitBundlesNested>a.c", "MyBundle", b.toString), 1),
(createExpected("~TopCircuitBundlesNested\\|TopCircuitBundlesNested>a.c.a", "UInt<8>", b.toString), 1),
(createExpected("~TopCircuitBundlesNested\\|TopCircuitBundlesNested>a.c.b", "SInt<8>", b.toString), 1),
(createExpected("~TopCircuitBundlesNested\\|TopCircuitBundlesNested>a.c.c", "Bool", b.toString), 1)
) ++ addClockReset("TopCircuitBundlesNested")
checkAnno(expectedMatches, string)
}

it("should annotate vecs") {
new ChiselStage(true).execute(args, Seq(ChiselGeneratorAnnotation(() => new TopCircuitVecs(b))))
val string = os.read(targetDir / "TopCircuitVecs.fir")
// format: off
val expectedMatches = Seq(
(createExpected("~TopCircuitVecs\\|TopCircuitVecs>a", "SInt<23>\\[5\\]", b.toString,
params = Some(Seq(ClassParam("gen", "=> T", None), ClassParam("length", "Int", Some("5"))))), 1),
(createExpected("~TopCircuitVecs\\|TopCircuitVecs>a\\[0\\]", "SInt<23>", b.toString), 1),
(createExpected("~TopCircuitVecs\\|TopCircuitVecs>b", "SInt<23>\\[3\\]\\[5\\]", b.toString,
params = Some(Seq(ClassParam("gen", "=> T", None), ClassParam("length", "Int", Some("5"))))), 1),
(createExpected("~TopCircuitVecs\\|TopCircuitVecs>b\\[0\\]", "SInt<23>\\[3\\]", b.toString,
params = Some(Seq(ClassParam("gen", "=> T", None), ClassParam("length", "Int", Some("3"))))), 1),
(createExpected("~TopCircuitVecs\\|TopCircuitVecs>b\\[0\\]\\[0\\]", "SInt<23>", b.toString), 1),
(createExpected("~TopCircuitVecs\\|TopCircuitVecs>c", "AnonymousBundle\\[5\\]", b.toString,
params = Some(Seq(ClassParam("gen", "=> T", None), ClassParam("length", "Int", Some("5"))))), 1),
(createExpected("~TopCircuitVecs\\|TopCircuitVecs>c\\[0\\]", "AnonymousBundle", b.toString), 1),
(createExpected("~TopCircuitVecs\\|TopCircuitVecs>c\\[0\\].x", "UInt<8>", b.toString), 1),

(createExpected("~TopCircuitVecs\\|TopCircuitVecs>d", "MixedVec", b.toString,
// TODO: check for MixedVec what the value of the parameter should be
params = Some(Seq(ClassParam("eltsIn", "Seq\\[T\\]", Some("Seq\\[T\\]\\(unsafeArray(.*?)\\)"))))), 1),
(createExpected("~TopCircuitVecs\\|TopCircuitVecs>d.0", "UInt<3>", b.toString), 1),
(createExpected("~TopCircuitVecs\\|TopCircuitVecs>d.1", "SInt<10>", b.toString), 1)
) ++ addClockReset("TopCircuitVecs")
// format: on
checkAnno(expectedMatches, string)
}

it("should annotate bundle with vec") {
new ChiselStage(true).execute(args, Seq(ChiselGeneratorAnnotation(() => new TopCircuitBundleWithVec(b))))
val string = os.read(targetDir / "TopCircuitBundleWithVec.fir")
// format: off
val expectedMatches = Seq(
(createExpected("~TopCircuitBundleWithVec\\|TopCircuitBundleWithVec>a", "AnonymousBundle", b.toString), 1),
(createExpected("~TopCircuitBundleWithVec\\|TopCircuitBundleWithVec>a.vec", "UInt<8>\\[5\\]", b.toString,
params = Some(Seq(ClassParam("gen", "=> T", None), ClassParam("length", "Int", Some("5"))))), 1),
(createExpected("~TopCircuitBundleWithVec\\|TopCircuitBundleWithVec>a.vec\\[0\\]", "UInt<8>", b.toString), 1)
) ++ addClockReset("TopCircuitBundleWithVec")
// format: on
checkAnno(expectedMatches, string)
}

it("should annotate submodule types") {
new ChiselStage(true)
.execute(args, Seq(ChiselGeneratorAnnotation(() => new TopCircuitTypeInSubmodule(b))))
val string = os.read(targetDir / "TopCircuitTypeInSubmodule.fir")
val analog =
if (b != RegBinding)
Seq((createExpected("~TopCircuitTypeInSubmodule\\|TopCircuitGroundTypes>analog", "Analog<1>", b.toString), 1))
else Seq.empty
val expectedMatches = Seq(
(createExpected("~TopCircuitTypeInSubmodule\\|TopCircuitGroundTypes>uint", "UInt<8>", b.toString), 1),
(createExpected("~TopCircuitTypeInSubmodule\\|TopCircuitGroundTypes>sint", "SInt<8>", b.toString), 1),
(createExpected("~TopCircuitTypeInSubmodule\\|TopCircuitGroundTypes>bool", "Bool", b.toString), 1),
(createExpected("~TopCircuitTypeInSubmodule\\|TopCircuitGroundTypes>bits", "UInt<8>", b.toString), 1),
(
(
"""~TopCircuitTypeInSubmodule\|TopCircuitGroundTypes""",
""""target":"~TopCircuitTypeInSubmodule\|TopCircuitGroundTypes",\s+"typeName":"TopCircuitGroundTypes""""
),
1
)
) ++ addClockReset("TopCircuitTypeInSubmodule", Some("TopCircuitGroundTypes")) ++ analog
checkAnno(expectedMatches, string)
}
}

describe("Port Annotations") {
val targetDir = os.pwd / "test_run_dir" / "TywavesAnnotationSpec" / "Port Annotations"
val args: Array[String] = Array("--target", "chirrtl", "--target-dir", targetDir.toString)

it("should fail") {
class TopCircuitFail extends Module
(new ChiselStage(true)).execute(args, Seq(ChiselGeneratorAnnotation(() => new TopCircuitFail)))
val string = os.read(targetDir / "TopCircuitFail.fir")
val expectedMatches = Seq(
(createExpected("~TopCircuitFail\\|TopCircuitFail>clock", "Clock", "IO"), 1)
// (createExpected("~TopCircuitFail\\|TopCircuitFail>reset", "Bool", "IO"), 1)
)
assertThrows[TestFailedException] { checkAnno(expectedMatches, string) }
}

it("should annotate clock and reset") {
(new ChiselStage(true)).execute(args, Seq(ChiselGeneratorAnnotation(() => new TopCircuitClockReset)))
val string = os.read(targetDir / "TopCircuitClockReset.fir")
val expectedMatches = Seq(
(createExpected("~TopCircuitClockReset\\|TopCircuitClockReset>clock", "Clock", "IO"), 1),
(createExpected("~TopCircuitClockReset\\|TopCircuitClockReset>syncReset", "Bool", "IO"), 1),
(createExpected("~TopCircuitClockReset\\|TopCircuitClockReset>reset", "Reset", "IO"), 1),
(createExpected("~TopCircuitClockReset\\|TopCircuitClockReset>asyncReset", "AsyncReset", "IO"), 1)
)
checkAnno(expectedMatches, string)
}

it("should annotate implicit clock and reset") {
(new ChiselStage(true)).execute(args, Seq(ChiselGeneratorAnnotation(() => new TopCircuitImplicitClockReset)))
val string = os.read(targetDir / "TopCircuitImplicitClockReset.fir")
val expectedMatches = Seq(
(createExpected("~TopCircuitImplicitClockReset\\|TopCircuitImplicitClockReset>clock", "Clock", "IO"), 1),
(createExpected("~TopCircuitImplicitClockReset\\|TopCircuitImplicitClockReset>reset", "Bool", "IO"), 1)
)
checkAnno(expectedMatches, string)

}

typeTests(args, targetDir, PortBinding)
}

describe("Wire Annotations") {
val targetDir = os.pwd / "test_run_dir" / "TywavesAnnotationSpec" / "Wire Annotations"
val args: Array[String] = Array("--target", "chirrtl", "--target-dir", targetDir.toString)
typeTests(args, targetDir, WireBinding)
}

describe("Reg Annotations") {
val targetDir = os.pwd / "test_run_dir" / "TywavesAnnotationSpec" / "Reg Annotations"
val args: Array[String] = Array("--target", "chirrtl", "--target-dir", targetDir.toString)
typeTests(args, targetDir, RegBinding)
}

describe("Tmp Values Annotations") {
val targetDir = os.pwd / "test_run_dir" / "TywavesAnnotationSpec" / "Tmp Values Annotations"
val args: Array[String] = Array("--target", "chirrtl", "--target-dir", targetDir.toString)
// format: off
it("should annotate tmp value in when") {
(new ChiselStage(true)).execute(args, Seq(ChiselGeneratorAnnotation(() => new TopCircuitWhenElse)))
val string = os.read(targetDir / "TopCircuitWhenElse.fir")
val expectedMatches = Seq(
(createExpected("~TopCircuitWhenElse\\|TopCircuitWhenElse>inSeq", "UInt<8>\\[8\\]", "IO",
params = Some(Seq(ClassParam("gen", "=> T", None), ClassParam("length", "Int", Some("8"))))), 1),
(createExpected("~TopCircuitWhenElse\\|TopCircuitWhenElse>inSeq\\[0\\]", "UInt<8>", "IO"), 1),
(createExpected("~TopCircuitWhenElse\\|TopCircuitWhenElse>out", "UInt<8>", "IO"), 1),
(createExpected("~TopCircuitWhenElse\\|TopCircuitWhenElse>sel", "UInt<3>", "IO"), 1),
// Tmp
(createExpected("~TopCircuitWhenElse\\|TopCircuitWhenElse>evenSel", "UInt<8>", "OpResult"), 1),
(createExpected("~TopCircuitWhenElse\\|TopCircuitWhenElse>_evenSel_T", "UInt<9>", "OpResult"), 1),
(createExpected("~TopCircuitWhenElse\\|TopCircuitWhenElse>oddSel", "UInt<8>", "OpResult"), 1),
(createExpected("~TopCircuitWhenElse\\|TopCircuitWhenElse>_oddSel_T", "UInt<9>", "OpResult"), 1),
(createExpected("~TopCircuitWhenElse\\|TopCircuitWhenElse>selIsOne", "UInt<8>", "OpResult"), 1),
(createExpected("~TopCircuitWhenElse\\|TopCircuitWhenElse>_selIsOne_T", "UInt<9>", "OpResult"), 1),
(createExpected("~TopCircuitWhenElse\\|TopCircuitWhenElse>tmp", "UInt<3>", "OpResult"), 1),
(createExpected("~TopCircuitWhenElse\\|TopCircuitWhenElse>_tmp_T", "UInt<4>", "OpResult"), 1),
(createExpected("~TopCircuitWhenElse\\|TopCircuitWhenElse>_T", "UInt<2>", "OpResult"), 1),
(createExpected("~TopCircuitWhenElse\\|TopCircuitWhenElse>_T_1", "Bool", "OpResult"), 1),
(createExpected("~TopCircuitWhenElse\\|TopCircuitWhenElse>_T_2", "Bool", "OpResult"), 1),

)
checkAnno(expectedMatches, string)
// format: on
}
}

describe("Chisel enum Annotations") {
val targetDir = os.pwd / "test_run_dir" / "TywavesAnnotationSpec" / "Enum Values Annotations"
val args: Array[String] = Array("--target", "chirrtl", "--target-dir", targetDir.toString)
// format: off
it("should annotate chiselEnum") {
// ChiselEnums are already annotated, so simply emit a .fir file for firtool tests
new ChiselStage(true).execute(args, Seq(ChiselGeneratorAnnotation(() => new TopCircuitChiselEnum)))
// format: on
}
}
}
387 changes: 387 additions & 0 deletions src/test/scala/circtTests/tywavesTests/memTests/README.md

Large diffs are not rendered by default.

Large diffs are not rendered by default.

467 changes: 467 additions & 0 deletions src/test/scala/circtTests/tywavesTests/moduleTests/README.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package circtTests.tywavesTests.moduleTests

import chisel3.stage.ChiselGeneratorAnnotation
import chisel3._
import circt.stage.ChiselStage
import org.scalatest.AppendedClues.convertToClueful
import org.scalatest.funspec.AnyFunSpec
import org.scalatest.matchers.should.Matchers

class TypeAnnotationModulesSpec extends AnyFunSpec with Matchers with chiselTests.Utils {

import circtTests.tywavesTests.TywavesAnnotationCircuits.ModuleCircuits._
import circtTests.tywavesTests.TestUtils._

describe("Module Annotations") {
val targetDir = os.pwd / "test_run_dir" / "TywavesAnnotationSpec" / "Module Annotations"
val args: Array[String] = Array("--target", "chirrtl", "--target-dir", targetDir.toString)

it("should annotate a circuit") {
(new ChiselStage(true)).execute(args, Seq(ChiselGeneratorAnnotation(() => new TopCircuit)))
os.read(targetDir / "TopCircuit.fir") should include("TywavesAnnotation").and(
include("\"target\":\"~TopCircuit|TopCircuit\"").and(
include("\"typeName\":\"TopCircuit\"")
)
)
}

it("should annotate a module in a circuit") {
(new ChiselStage(true)).execute(args, Seq(ChiselGeneratorAnnotation(() => new TopCircuitSubModule)))
os.read(targetDir / "TopCircuitSubModule.fir") should include("TywavesAnnotation").and(
include("\"target\":\"~TopCircuitSubModule|MyModule\"").and(include("\"typeName\":\"MyModule\""))
)
}

it("should annotate a module in a circuit multiple times") {
(new ChiselStage(true)).execute(args, Seq(ChiselGeneratorAnnotation(() => new TopCircuitMultiModule)))
// The file should include it
val string = os.read(targetDir / "TopCircuitMultiModule.fir")
countSubstringOccurrences(string, "\"class\":\"chisel3.tywavesinternal.TywavesAnnotation\"") should be(5)
countSubstringOccurrences(string, "\"typeName\":\"MyModule\"") should be(4)
}

it("should annotate black boxes") {

(new ChiselStage(true)).execute(args, Seq(ChiselGeneratorAnnotation(() => new TopCircuitBlackBox)))
val string = os.read(targetDir / "TopCircuitBlackBox.fir")
countSubstringOccurrences(string, "\"class\":\"chisel3.tywavesinternal.TywavesAnnotation\"") should be(5)
countSubstringOccurrences(string, "\"typeName\":\"MyBlackBox") should be(4)
}

it("should annotate intrinsic modules") {
import chisel3.experimental.IntrinsicModule

(new ChiselStage(true)).execute(args, Seq(ChiselGeneratorAnnotation(() => new TopCircuitIntrinsic)))
val string = os.read(targetDir / "TopCircuitIntrinsic.fir")
countSubstringOccurrences(string, "\"class\":\"chisel3.tywavesinternal.TywavesAnnotation\"") should be(13)
countSubstringOccurrences(string, "\"typeName\":\"ExampleIntrinsicModule") should be(4)
}

it("should annotate classes modules") {
(new ChiselStage(true)).execute(args, Seq(ChiselGeneratorAnnotation(() => new TopCircuitClasses)))
val string = os.read(targetDir / "TopCircuitClasses.fir")
countSubstringOccurrences(string, "\"typeName\":\"CSRModule\"") should be(4)
countSubstringOccurrences(
string,
"\"target\":\"~TopCircuitClasses\\|CSRDescription\",\\s*\"typeName\":\"CSRDescription"
) should be(1)
countSubstringOccurrences(string, "\"class\":\"chisel3.tywavesinternal.TywavesAnnotation\"") should be(6)
}

it("should annotate parametric module") {
class MyModule[T <: Data](gen: T) extends RawModule

class TopCircuitParametric extends RawModule {
val myModule1: MyModule[UInt] = Module(new MyModule(UInt(8.W)))
val myModule2: MyModule[SInt] = Module(new MyModule(SInt(8.W)))
val myModule3: MyModule[Bool] = Module(new MyModule(Bool()))
}

(new ChiselStage(true)).execute(args, Seq(ChiselGeneratorAnnotation(() => new TopCircuitParametric)))
val string = os.read(targetDir / "TopCircuitParametric.fir")

// TODO: Fix this test for parametric module
// val expectedMatches = Seq(
// ("\"typeName\":\"MyModule\\[UInt<8>\\]\"", 1),
// ("\"typeName\":\"MyModule\\[SInt<8>\\]\"", 1),
// ("\"typeName\":\"MyModule\\[Bool\\]\"", 1)
// )
// checkAnno(expectedMatches, string)
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,277 @@
package circtTests.tywavesTests.scalaReflectionTests

import chisel3.tywavesinternal.{ClassParam, TywavesChiselAnnotation}
import circtTests.tywavesTests.TestUtils.countSubstringOccurrences
import org.scalatest.AppendedClues.convertToClueful
import org.scalatest.funspec.AnyFunSpec
import org.scalatest.matchers.should.Matchers

import java.math.BigInteger

class ParametersAnnotationSpec extends AnyFunSpec with Matchers with chiselTests.Utils {

describe("Parameters of a scala class") {

it("should return empty list without params") {
class A
val a = new A
TywavesChiselAnnotation.getConstructorParams(a) should be(Seq())
}

it("should access the val of a class constructor") {
val x = 10
class A(val a: Int)
val a = new A(2)
val expectA = Seq(ClassParam("a", "Int", Some(2.toString)))
TywavesChiselAnnotation.getConstructorParams(a) should be(expectA)

class B(val a: Boolean, val b: Float)
val b = new B(true, 1.1f)
val expectB =
Seq(
ClassParam("a", "Boolean", Some("true")),
ClassParam("b", "Float", Some(1.1.toString))
)
TywavesChiselAnnotation.getConstructorParams(b) should be(expectB)

class C(val a: Int, val b: String)
val c = new C(1, "hello")
val expectC = Seq(ClassParam("a", "Int", Some(1.toString)), ClassParam("b", "String", Some("hello")))
TywavesChiselAnnotation.getConstructorParams(c) should be(expectC)
}

it("should access normal parameters of a class constructor") {
class A(a: Int)
val a = new A(1)
val expectA = Seq(ClassParam("a", "Int", None))
TywavesChiselAnnotation.getConstructorParams(a) should be(expectA)

class B(a: Boolean, b: Float)
val b = new B(true, 1.1f)
val expectB = Seq(ClassParam("a", "Boolean", None), ClassParam("b", "Float", None))
TywavesChiselAnnotation.getConstructorParams(b) should be(expectB)

class C(a: Int, b: String)
val c = new C(1, "hello")
val expectC = Seq(ClassParam("a", "Int", None), ClassParam("b", "String", None))
TywavesChiselAnnotation.getConstructorParams(c) should be(expectC)

}

it("should NOT access the internal val of a class") {
class A(a: Int) {
val c = 10
}
val a = new A(1)
val expectA = Seq(ClassParam("a", "Int", None))
TywavesChiselAnnotation.getConstructorParams(a) should be(expectA)
}

it("should access private val of a class constructor") {
class A(private val a: Int) {
val c = 10
}
val a = new A(1)
val expectA = Seq(ClassParam("a", "Int", Some(1.toString)))
TywavesChiselAnnotation.getConstructorParams(a) should be(expectA)

class B(protected val b: Int) {
val c = 10
}
val b = new B(1)
val expectB = Seq(ClassParam("b", "Int", Some(1.toString)))
TywavesChiselAnnotation.getConstructorParams(b) should be(expectB)
}

it("should NOT access val of a super class") {
class A(private val a: Int) {
val c = 10
}
val a = new A(1)
val expectA = Seq(ClassParam("a", "Int", Some(1.toString)))
TywavesChiselAnnotation.getConstructorParams(a) should be(expectA)

class B(protected val b: Int) extends A(b) {
override val c = 10
}
val b = new B(1)
val expectB = Seq(ClassParam("b", "Int", Some(1.toString)))
TywavesChiselAnnotation.getConstructorParams(b) should be(expectB)

class C extends A(1) {
val d = 10
}
val c = new C
TywavesChiselAnnotation.getConstructorParams(c) should be(Seq())
}

it("should parameter of complex types of a class") {
class A(private val a: Int, val x: Char) {
val c = 10
}
val a = new A(1, 'c')

class B(protected val aClass: A) {
val c = 10
}
val b = new B(a)
val expectB = Seq(ClassParam("aClass", "A", Some("A(a: 1, x: c)")))
TywavesChiselAnnotation.getConstructorParams(b) should be(expectB)
}

it("should parameter of nested complex types") {
class Base(val a: Int, c: Float)
class A(private val a: Int, val x: String, val base: Base) {
val c = 10
}
val a = new A(1, "ciao", new Base(3, 1.1f))

class B(protected val aClass: A) {
val c = 10
}
val b = new B(a)
val expectB = Seq(ClassParam("aClass", "A", Some("A(a: 1, x: ciao, base: Base(a: 3, c))")))
TywavesChiselAnnotation.getConstructorParams(b) should be(expectB)
}

it("should work with case classes") {
case class Base(val a: Int, c: Float)
case class A(private val a: Int, val x: String, val base: Base) { val c = 10 }
val a = A(1, "ciao", Base(3, 1.1f))

case class B(protected val aClass: A) {
val c = 10
}
val b = B(a)
val expectB = Seq(ClassParam("aClass", "A", Some("A(a: 1, x: ciao, base: Base(a: 3, c: 1.1))")))
TywavesChiselAnnotation.getConstructorParams(b) should be(expectB)
}
}

describe("Parameters with Chisel constructs") {
import circt.stage.ChiselStage
import chisel3.stage.ChiselGeneratorAnnotation
import circtTests.tywavesTests.TywavesAnnotationCircuits.ParamCircuits._
import circtTests.tywavesTests.TestUtils.{checkAnno, createExpected}

val targetDir = os.pwd / "test_run_dir" / "TywavesAnnotationSpec" / "Chisel Constructs with Parameters Annotations"
val args: Array[String] = Array("--target", "chirrtl", "--target-dir", targetDir.toString)

it("should annotate a circuit with parameters") {
(new ChiselStage(true)).execute(args, Seq(ChiselGeneratorAnnotation(() => new TopCircuitWithParams(8, 16))))
// The file should include it
val string = os.read(targetDir / "TopCircuitWithParams.fir")
val expectedMatches = Seq(
(createExpected("~TopCircuitWithParams\\|TopCircuitWithParams>uint", "UInt<8>", "IO"), 1),
(createExpected("~TopCircuitWithParams\\|TopCircuitWithParams>sint", "SInt<16>", "IO"), 1),
(createExpected("~TopCircuitWithParams\\|TopCircuitWithParams>bool", "Bool", "IO"), 1),
(createExpected("~TopCircuitWithParams\\|TopCircuitWithParams>bits", "UInt<24>", "IO"), 1),
(
createExpected(
"~TopCircuitWithParams\\|TopCircuitWithParams",
"TopCircuitWithParams",
params = Some(Seq(ClassParam("width1", "Int", Some("8")), ClassParam("width2", "Int", Some("16"))))
),
1
)
)
checkAnno(expectedMatches, string, includeConstructor = true)
}

it("should annotate variants of Parametrized module in a circuit") {
(new ChiselStage(true)).execute(args, Seq(ChiselGeneratorAnnotation(() => new TopCircuitWithParamModules)))
// The file should include it
val string = os.read(targetDir / "TopCircuitWithParamModules.fir")
countSubstringOccurrences(string, "\"class\":\"chisel3.tywavesinternal.TywavesAnnotation\"") should be(4)
countSubstringOccurrences(string, "\"typeName\":\"MyModule") should be(3)

val expected1 = "\"typeName\":\"MyModule\"," + "\\s*\"params\":\\[\\s*\\{\\s*" +
"\"name\":\"width\",\\s*\"typeName\":\"Int\",\\s*\"value\":\"8\"" +
"\\s*\\}\\s*\\]\\s*\\}"
(countSubstringOccurrences(string, expected1) should be(1)).withClue("Expected: " + expected1)
val expected2 = "\"typeName\":\"MyModule\"," + "\\s*\"params\":\\[\\s*\\{\\s*" +
"\"name\":\"width\",\\s*\"typeName\":\"Int\",\\s*\"value\":\"16\"" +
"\\s*\\}\\s*\\]\\s*\\}"
(countSubstringOccurrences(string, expected2) should be(1)).withClue("Expected: " + expected2)
val expected3 = "\"typeName\":\"MyModule\"," + "\\s*\"params\":\\[\\s*\\{\\s*" +
"\"name\":\"width\",\\s*\"typeName\":\"Int\",\\s*\"value\":\"32\"" +
"\\s*\\}\\s*\\]\\s*\\}"
(countSubstringOccurrences(string, expected3) should be(1)).withClue("Expected: " + expected3)
}

it("should annotate Parametrized bundles") {
new ChiselStage(true).execute(args, Seq(ChiselGeneratorAnnotation(() => new TopCircuitWithParamBundle)))
// The file should include it
val string = os.read(targetDir / "TopCircuitWithParamBundle.fir")
// format: off
val expectedMatches = Seq(
(createExpected("~TopCircuitWithParamBundle\\|TopCircuitWithParamBundle>baseBundle", "BaseBundle", "IO",
params = Some(Seq(ClassParam("n", "Int", Some(1.toString))))), 1),
(createExpected("~TopCircuitWithParamBundle\\|TopCircuitWithParamBundle>baseBundle.b", "UInt<1>", "IO"), 1),
(createExpected("~TopCircuitWithParamBundle\\|TopCircuitWithParamBundle>otherBundle", "OtherBundle", "IO",
params = Some(Seq(
ClassParam("a", "UInt", Some("IO\\[UInt<1>\\]")),
ClassParam("b", "BaseBundle", Some("BaseBundle\\(n: 1\\)"))))), 1),
(createExpected("~TopCircuitWithParamBundle\\|TopCircuitWithParamBundle>otherBundle.a", "UInt<1>", "IO"), 1),
(createExpected("~TopCircuitWithParamBundle\\|TopCircuitWithParamBundle>otherBundle.b", "BaseBundle", "IO",
params = Some(Seq(ClassParam("n", "Int", Some(1.toString))))), 1),
(createExpected("~TopCircuitWithParamBundle\\|TopCircuitWithParamBundle>otherBundle.b.b", "UInt<1>", "IO"), 1),

(createExpected("~TopCircuitWithParamBundle\\|TopCircuitWithParamBundle>topBundle", "TopBundle", "IO",
params = Some(Seq(
ClassParam("a", "Bool", Some("IO\\[Bool\\]")),
ClassParam("b", "String", Some("hello")),
ClassParam("c", "Char", Some("c")),
ClassParam("d", "Boolean", Some("true")),
ClassParam("o", "OtherBundle", Some("OtherBundle\\(a: IO\\[UInt<1>\\], b: BaseBundle\\(n: 1\\)\\)")) ))), 1),
(createExpected("~TopCircuitWithParamBundle\\|TopCircuitWithParamBundle>topBundle.inner_a", "Bool", "IO"), 1),
(createExpected("~TopCircuitWithParamBundle\\|TopCircuitWithParamBundle>topBundle.o", "OtherBundle", "IO",
params = Some(Seq(ClassParam("a", "UInt", Some("IO\\[UInt<1>\\]")),
ClassParam("b", "BaseBundle", Some("BaseBundle\\(n: 1\\)"))))), 1),
(createExpected("~TopCircuitWithParamBundle\\|TopCircuitWithParamBundle>topBundle.o.a", "UInt<1>", "IO"), 1),
(createExpected("~TopCircuitWithParamBundle\\|TopCircuitWithParamBundle>topBundle.o.b", "BaseBundle", "IO",
params = Some(Seq(ClassParam("n", "Int", Some(1.toString))))), 1),
(createExpected("~TopCircuitWithParamBundle\\|TopCircuitWithParamBundle>topBundle.o.b.b", "UInt<1>", "IO"), 1),

(createExpected("~TopCircuitWithParamBundle\\|TopCircuitWithParamBundle>caseClassBundle", "CaseClassExample", "IO",
params = Some(Seq(
ClassParam("a", "Int", Some("1")),
ClassParam("o", "OtherBundle", Some("OtherBundle\\(a: IO\\[UInt<2>\\], b: BaseBundle\\(n: 1\\)\\)"))
))), 1),
(createExpected("~TopCircuitWithParamBundle\\|TopCircuitWithParamBundle>caseClassBundle.o", "OtherBundle", "IO",
params = Some(Seq(
ClassParam("a", "UInt", Some("IO\\[UInt<2>\\]")),
ClassParam("b", "BaseBundle", Some("BaseBundle\\(n: 1\\)"))))), 1),
(createExpected("~TopCircuitWithParamBundle\\|TopCircuitWithParamBundle>caseClassBundle.o.a", "UInt<2>", "IO"), 1),
(createExpected("~TopCircuitWithParamBundle\\|TopCircuitWithParamBundle>caseClassBundle.o.b", "BaseBundle", "IO",
params = Some(Seq(ClassParam("n", "Int", Some(1.toString))))), 1),
(createExpected("~TopCircuitWithParamBundle\\|TopCircuitWithParamBundle>caseClassBundle.o.b.b", "UInt<1>", "IO"), 1),
(createExpected("~TopCircuitWithParamBundle\\|TopCircuitWithParamBundle>anonBundle", "AnonymousBundle", "IO"), 1),
)
// format: on
checkAnno(expectedMatches, string)
}

it("should annotate Parametrized modules and bundles with scala classes as params") {
new ChiselStage(true).execute(args, Seq(ChiselGeneratorAnnotation(() => new TopCircuitWithParamScalaClasses)))
// The file should include it
val string = os.read(targetDir / "TopCircuitWithParamScalaClasses.fir")
// format: off
val expectedMatches = Seq(
(createExpected("~TopCircuitWithParamScalaClasses\\|MyModule", "MyModule",
params = Some(Seq(
ClassParam("a", "MyScalaClass", Some("MyScalaClass\\(a: 1, b\\)")),
ClassParam("b", "MyScalaCaseClass", Some("MyScalaCaseClass\\(a: 2, b: world\\)"))
))), 1),
(createExpected("~TopCircuitWithParamScalaClasses\\|TopCircuitWithParamScalaClasses>bundle", "MyBundle", "IO",
params = Some(Seq(
ClassParam("a", "MyScalaClass", Some("MyScalaClass\\(a: 1, b\\)")),
ClassParam("b", "MyScalaCaseClass", Some("MyScalaCaseClass\\(a: 2, b: world\\)"))
))), 1),
)
// format: on
checkAnno(expectedMatches, string)
}
}

}
380 changes: 380 additions & 0 deletions src/test/scala/circtTests/tywavesTests/scalaReflectionTests/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,380 @@
# Annotations for Chisel Constructs with Parameters

For each circuit in [ParamCircuits](../TywavesAnnotationCircuits.scala), the following annotations are generated:

## Circuit with Parameters

> **NOTE**: `val` inside the body of the class are not considered parameters
```scala
class TopCircuitWithParams(val width1: Int, width2: Int) extends RawModule {
val width3 = width1 + width2 // Not a parameter
val uint: UInt = IO(Input(UInt(width1.W)))
val sint: SInt = IO(Input(SInt(width2.W)))
val bool: Bool = IO(Input(Bool()))
val bits: Bits = IO(Input(Bits(width3.W)))
}

```

```fir
circuit TopCircuitWithParams :%[[
{
"class":"chisel3.tywavesinternal.TywavesAnnotation",
"target":"~TopCircuitWithParams|TopCircuitWithParams",
"typeName":"TopCircuitWithParams",
"params":[
{
"name":"width1",
"typeName":"Int",
"value":"8"
},
{
"name":"width2",
"typeName":"Int",
"value":"16"
}
]
},
; Other tywavesinternal annotations
]]
public module TopCircuitWithParams : @[src/test/scala/circtTests/tywavesTests/TywavesAnnotationCircuits.scala 318:11]
input uint : UInt<8> @[src/test/scala/circtTests/tywavesTests/TywavesAnnotationCircuits.scala 320:26]
input sint : SInt<16> @[src/test/scala/circtTests/tywavesTests/TywavesAnnotationCircuits.scala 321:26]
input bool : UInt<1> @[src/test/scala/circtTests/tywavesTests/TywavesAnnotationCircuits.scala 322:26]
input bits : UInt<24> @[src/test/scala/circtTests/tywavesTests/TywavesAnnotationCircuits.scala 323:26]
skip
```

## Module instances with basic scala types parameters

```scala
class TopCircuitWithParamModules extends RawModule {
class MyModule(val width: Int) extends RawModule

val mod1: MyModule = Module(new MyModule(8))
val mod2: MyModule = Module(new MyModule(16))
val mod3: MyModule = Module(new MyModule(32))
}

```

```fir
circuit TopCircuitWithParamModules :%[[
{
"class":"chisel3.tywavesinternal.TywavesAnnotation",
"target":"~TopCircuitWithParamModules|MyModule",
"typeName":"MyModule",
"params":[
{
"name":"width",
"typeName":"Int",
"value":"8"
}
]
},
{
"class":"chisel3.tywavesinternal.TywavesAnnotation",
"target":"~TopCircuitWithParamModules|MyModule_1",
"typeName":"MyModule",
"params":[
{
"name":"width",
"typeName":"Int",
"value":"16"
}
]
},
{
"class":"chisel3.tywavesinternal.TywavesAnnotation",
"target":"~TopCircuitWithParamModules|MyModule_2",
"typeName":"MyModule",
"params":[
{
"name":"width",
"typeName":"Int",
"value":"32"
}
]
},
{
"class":"chisel3.tywavesinternal.TywavesAnnotation",
"target":"~TopCircuitWithParamModules|TopCircuitWithParamModules",
"typeName":"TopCircuitWithParamModules"
}
]]
module MyModule : @[src/test/scala/circtTests/tywavesTests/TywavesAnnotationCircuits.scala 328:13]
skip
module MyModule_1 : @[src/test/scala/circtTests/tywavesTests/TywavesAnnotationCircuits.scala 328:13]
skip
module MyModule_2 : @[src/test/scala/circtTests/tywavesTests/TywavesAnnotationCircuits.scala 328:13]
skip
public module TopCircuitWithParamModules : @[src/test/scala/circtTests/tywavesTests/TywavesAnnotationCircuits.scala 327:11]
inst mod1 of MyModule @[src/test/scala/circtTests/tywavesTests/TywavesAnnotationCircuits.scala 330:34]
inst mod2 of MyModule_1 @[src/test/scala/circtTests/tywavesTests/TywavesAnnotationCircuits.scala 331:34]
inst mod3 of MyModule_2 @[src/test/scala/circtTests/tywavesTests/TywavesAnnotationCircuits.scala 332:34]
```

## Bundles with chisel types parameters

```scala
class TopCircuitWithParamBundle extends RawModule {
class BaseBundle(val n: Int) extends Bundle {
val b: UInt = UInt(n.W)
}

class OtherBundle(val a: UInt, val b: BaseBundle) extends Bundle {} // Example of nested class in parameters

class TopBundle(a: Bool, val b: String, protected val c: Char, private val d: Boolean, val o: OtherBundle)
extends Bundle {
val inner_a = a
}

case class CaseClassExample(a: Int, o: OtherBundle) extends Bundle

val baseBundle = IO(Input(new BaseBundle(1)))
val otherBundle = IO(Input(new OtherBundle(UInt(baseBundle.n.W), baseBundle.cloneType)))
val topBundle = IO(Input(new TopBundle(Bool(), "hello", 'c', true, otherBundle.cloneType)))

val caseClassBundle = IO(Input(CaseClassExample(1, new OtherBundle(UInt(2.W), baseBundle.cloneType))))

}

```

```fir
circuit TopCircuitWithParamBundle :%[[
; other tywavesinternal annotations
{
"class":"chisel3.tywavesinternal.TywavesAnnotation",
"target":"~TopCircuitWithParamBundle|TopCircuitWithParamBundle>baseBundle",
"typeName":"IO[BaseBundle]",
"params":[
{
"name":"n",
"typeName":"Int",
"value":"1"
}
]
},
{
"class":"chisel3.tywavesinternal.TywavesAnnotation",
"target":"~TopCircuitWithParamBundle|TopCircuitWithParamBundle>otherBundle.b",
"typeName":"IO[BaseBundle]",
"params":[
{
"name":"n",
"typeName":"Int",
"value":"1"
}
]
},
{
"class":"chisel3.tywavesinternal.TywavesAnnotation",
"target":"~TopCircuitWithParamBundle|TopCircuitWithParamBundle>otherBundle",
"typeName":"IO[OtherBundle]",
"params":[
{
"name":"a",
"typeName":"UInt",
"value":"IO[UInt<1>]"
},
{
"name":"b",
"typeName":"BaseBundle",
"value":"BaseBundle(n: 1)"
}
]
},
{
"class":"chisel3.tywavesinternal.TywavesAnnotation",
"target":"~TopCircuitWithParamBundle|TopCircuitWithParamBundle>topBundle.o.b.b",
"typeName":"IO[UInt<1>]"
},
{
"class":"chisel3.tywavesinternal.TywavesAnnotation",
"target":"~TopCircuitWithParamBundle|TopCircuitWithParamBundle>topBundle.o.b",
"typeName":"IO[BaseBundle]",
"params":[
{
"name":"n",
"typeName":"Int",
"value":"1"
}
]
},
{
"class":"chisel3.tywavesinternal.TywavesAnnotation",
"target":"~TopCircuitWithParamBundle|TopCircuitWithParamBundle>topBundle.o",
"typeName":"IO[OtherBundle]",
"params":[
{
"name":"a",
"typeName":"UInt",
"value":"IO[UInt<1>]"
},
{
"name":"b",
"typeName":"BaseBundle",
"value":"BaseBundle(n: 1)"
}
]
},
{
"class":"chisel3.tywavesinternal.TywavesAnnotation",
"target":"~TopCircuitWithParamBundle|TopCircuitWithParamBundle>topBundle",
"typeName":"IO[TopBundle]",
"params":[
{
"name":"a",
"typeName":"Bool",
"value":"IO[Bool]"
},
{
"name":"b",
"typeName":"String",
"value":"hello"
},
{
"name":"c",
"typeName":"Char",
"value":"c"
},
{
"name":"d",
"typeName":"Boolean",
"value":"true"
},
{
"name":"o",
"typeName":"OtherBundle",
"value":"OtherBundle(a: IO[UInt<1>], b: BaseBundle(n: 1))"
}
]
},
{
"class":"chisel3.tywavesinternal.TywavesAnnotation",
"target":"~TopCircuitWithParamBundle|TopCircuitWithParamBundle>caseClassBundle.o.b",
"typeName":"IO[BaseBundle]",
"params":[
{
"name":"n",
"typeName":"Int",
"value":"1"
}
]
},
{
"class":"chisel3.tywavesinternal.TywavesAnnotation",
"target":"~TopCircuitWithParamBundle|TopCircuitWithParamBundle>caseClassBundle.o",
"typeName":"IO[OtherBundle]",
"params":[
{
"name":"a",
"typeName":"UInt",
"value":"IO[UInt<2>]"
},
{
"name":"b",
"typeName":"BaseBundle",
"value":"BaseBundle(n: 1)"
}
]
},
{
"class":"chisel3.tywavesinternal.TywavesAnnotation",
"target":"~TopCircuitWithParamBundle|TopCircuitWithParamBundle>caseClassBundle",
"typeName":"IO[CaseClassExample]",
"params":[
{
"name":"a",
"typeName":"Int",
"value":"1"
},
{
"name":"o",
"typeName":"OtherBundle",
"value":"OtherBundle(a: IO[UInt<2>], b: BaseBundle(n: 1))"
}
]
}
]]
public module TopCircuitWithParamBundle : @[src/test/scala/circtTests/tywavesTests/TywavesAnnotationCircuits.scala 336:11]
input baseBundle : { b : UInt<1>} @[src/test/scala/circtTests/tywavesTests/TywavesAnnotationCircuits.scala 348:26]
input otherBundle : { a : UInt<1>, b : { b : UInt<1>}} @[src/test/scala/circtTests/tywavesTests/TywavesAnnotationCircuits.scala 349:27]
input topBundle : { inner_a : UInt<1>, o : { a : UInt<1>, b : { b : UInt<1>}}} @[src/test/scala/circtTests/tywavesTests/TywavesAnnotationCircuits.scala 350:25]
input caseClassBundle : { o : { a : UInt<2>, b : { b : UInt<1>}}} @[src/test/scala/circtTests/tywavesTests/TywavesAnnotationCircuits.scala 352:31]
skip
```

## Bundles and modules with scala classes and case classes types parameters

> **NOTE**: when the parameter is not a `val` is not always annotated
```scala
class TopCircuitWithParamScalaClasses extends RawModule {
class MyScalaClass(val a: Int, b: String)

case class MyScalaCaseClass(a: Int, b: String)

class MyModule(val a: MyScalaClass, b: MyScalaCaseClass) extends RawModule

class MyBundle(val a: MyScalaClass, b: MyScalaCaseClass) extends Bundle

val mod : MyModule = Module(new MyModule(new MyScalaClass(1, "hello"), MyScalaCaseClass(2, "world")))
val bundle: MyBundle = IO(Input(new MyBundle(new MyScalaClass(1, "hello"), MyScalaCaseClass(2, "world"))))

}

```

```fir
circuit TopCircuitWithParamScalaClasses :%[[
; other tywavesinternal annotations
{
"class":"chisel3.tywavesinternal.TywavesAnnotation",
"target":"~TopCircuitWithParamScalaClasses|MyModule",
"typeName":"MyModule",
"params":[
{
"name":"a",
"typeName":"MyScalaClass",
"value":"MyScalaClass(a: 1, b)"
},
{
"name":"b",
"typeName":"MyScalaCaseClass",
"value":"MyScalaCaseClass(a: 2, b: world)"
}
]
},
{
"class":"chisel3.tywavesinternal.TywavesAnnotation",
"target":"~TopCircuitWithParamScalaClasses|TopCircuitWithParamScalaClasses>bundle",
"typeName":"IO[MyBundle]",
"params":[
{
"name":"a",
"typeName":"MyScalaClass",
"value":"MyScalaClass(a: 1, b)"
},
{
"name":"b",
"typeName":"MyScalaCaseClass",
"value":"MyScalaCaseClass(a: 2, b: world)"
}
]
}
]]
module MyModule : @[src/test/scala/circtTests/tywavesTests/TywavesAnnotationCircuits.scala 361:13]
skip
public module TopCircuitWithParamScalaClasses : @[src/test/scala/circtTests/tywavesTests/TywavesAnnotationCircuits.scala 357:11]
input bundle : { } @[src/test/scala/circtTests/tywavesTests/TywavesAnnotationCircuits.scala 365:32]
inst mod of MyModule @[src/test/scala/circtTests/tywavesTests/TywavesAnnotationCircuits.scala 364:36]
```