Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pass Chisel information to firtool to generate debug information for the Tywaves project #4015

Open
2 of 4 tasks
rameloni opened this issue Apr 19, 2024 · 15 comments
Open
2 of 4 tasks

Comments

@rameloni
Copy link
Contributor

rameloni commented Apr 19, 2024

I have started to work on a better version for my type-based waveform viewer for Tydi and Chisel-related projects (Tywaves).

My chisel fork: https://github.com/rameloni/chisel/tree/tywaves-annotations

Currently, I created a demo to show potential features of types in waveforms and prove its feasibility. Therefore, it only works with a restricted number of cases so far. The demo is divided into 2 main parts:

Although the approach I used for the demo works for some cases, there are some drawbacks related to that both practical and technical. Because of that the need for an integration within the chisel elaboration infrastructure.

The current approach and drawbacks: chisel side

In my demo, I create an external library for chisel that:

  • parses Chisel IR, Firrtl IR, and the HGLDD (debug info emitted by firtool to link verilog and firrtl)
  • retrieves and joins signals together by identifying IDs (shared between IRs) based on signal names and source locators
  • emits a symbol table suited for the viewer from the combination of Chisel circuit, Firrtl circuit, and HGLDD

This leads to the following issues:

  1. First of all, it accesses and uses the Chisel IR which is private to chisel3. This may compromise compatibility with future chisel versions.
  2. IDs are based on source locators and variable names. This causes for example issues when I have multiple instances of the same module (its internal signals have the same source locators, currently not working in the demo).
  3. It relies on HGLDD which can also change in the future since it is not stable and realized for synopsys.
  4. In addition HGLDD mainly contains Firrtl-to-Verilog information (except for source locators in chisel). This requires a new file format.

During a CIRCT meeting a few weeks ago, I had the opportunity to present my project and show the demo. Fabian Schuiki and I agreed that these issues would be solved if I managed to pass Chisel information directly to firtool, also simplifying the code itself.
This can be achieved by propagating "Chisel IR information" during the elaboration phase to "Firrtl IR" (from here this GitHub issue).

I explain the drawbacks in a bit more detail here: https://github.com/rameloni/tywaves-chisel-demo?tab=readme-ov-file#drawbacks

New approach: integration during Chisel elaboration and Firtool

To solve the issues of the current demo, I need a systematic method to map Chisel values to Firrtl. In this way, I could provide firtool with the emission of a (new) debug file format. In addition:

  • it would simplify the code structure and tool flow
  • it guarantees a better integration in the Chisel/CIRCT infrastructure, this...
  • since it will be part of the source code of Chisel and firtool, it would be also easier to support new features and eventual changes in the conversion from Chisel-to-Firrtl circuit
  • it would solve the issue of (guessing) the IDs, because the "mapping" will be done during the elaboration process for each element, ensuring an exact match between chisel and firrtl elements

Implementation of the new approach in Chisel

Chisel allows passing arbitrary metadata to FIRRTL associated with more targets (elements in a FIRRTL circuit) through the annotation mechanism. The toTarget() function can be used to reference a scala object with a FIRRTL target. Therefore, associating each target with its concrete scala/chisel information.

My goal with this issue is to write an implementation to:

  • annotate each firrtl target (modules, instances, nodes, signals...) with chisel types and (possibly) other metadata such as scala parameters (i.e. class MyModule[T<:Data](gen: T, n: T) extends RawModule). This last is more challenging though.
  • enable the annotation only for simulation and (maybe) only if tywaves is needed. It's useless to have this annotation during ChiselStage.emitSystemVerilog) for example.
  • check if every target is annotated (for eventual bug detection)
  • write a list of supported chisel constructs to keep track of the current progress
@rameloni
Copy link
Contributor Author

rameloni commented Apr 19, 2024

Tracking supported chisel constructs emitted in FIRRTL annotations

These tables summarize which chisel constructs are currently supported and related commit.

  • ✅ done
  • ⌛ in progress
  • 🔧 fixing
  • 🔜 requires to start
  • ❓ there is a question about the annotation (for example, if the way to annotate is sufficient or not)

Module types

Module type TypeName String Annotation supported? Tested emission? Commit
Normal module (Module/RawModule) Name of the module class rameloni@65a47f3
Blackbox Name of the blackbox class rameloni@65a47f3
Intrinsic Name of the intrinsic class rameloni@65a47f3
Classes Name of the Class class rameloni@65a47f3
Parametrized modules (MyModule[T]) Module[T] 🔧
Module with parameter (MyModule(n: Int)) Module(n) rameloni@d4d6331
Submodule instances (any type) Name of the instance module class rameloni@65a47f3 and rameloni@0353ef1

Chisel Data types

Ground type TypeName String Annotation supported? Tested emission? Commit
Clock Clock rameloni@65a47f3
Synchronous reset Bool rameloni@65a47f3
Asynchronous reset AsyncReset rameloni@65a47f3
Abstract reset Reset rameloni@65a47f3
Bool Bool rameloni@65a47f3
UInt UInt rameloni@65a47f3
SInt SInt rameloni@65a47f3
Analog Analog rameloni@65a47f3
Aggregate type TypeName String Annotation supported? Tested emission? Commit
Bundle (anonymous) AnonymousBundle rameloni@65a47f3
Bundle (user defined) Name of the defined class rameloni@65a47f3
Vec of type T T[Dim1][Dim2][..][DimN] rameloni@65a47f3
MixedVec MixedVec rameloni@65a47f3
Nested bundles Name of the top bundle rameloni@65a47f3
User defined parametrized types (MyBundle[T]) MyType[T] ⌛ 🔧
User defined types with parameters (MyBundle(n: Int)) MyType(n) rameloni@d4d6331 and rameloni@0353ef1
DecoupledIO Should be same as bundle 🔜 🔜

Hardware bindings

Binding TypeName String Annotation supported? Tested emission? Commit
Port of type T IO[T] rameloni@65a47f3
Port of type T in submodules IO[T] rameloni@65a47f3
Wire of type T Wire[T] rameloni@18153de
Wire of type T in submodules Wire[T] rameloni@18153de
Reg of type T Reg[T] rameloni@18153de
Reg of type T in submodules Reg[T] rameloni@18153de

Memories

Memory type TypeName String Annotation supported? Tested emission? Commit
ROM (with Vec[T]) T[size] rameloni@65a47f3 and rameloni@ff1de98
SyncReadMem SyncReadMem[T[size]] ✅ (❓ if the memory is of aggregate type, the fields of aggregates are annotated only when the memory is effectively used. Namely, when the MPORT is effectively instantiated) rameloni@ff1de98
Mem Mem[T[size]] ✅ (❓ if the memory is of aggregate type, the fields of aggregates are annotated only when the memory is effectively used. Namely, when the MPORT is effectively instantiated) rameloni@ff1de98
SRAMs SramTarget[T[size]] + SRAMInterface utility bundle rameloni@ff1de98

Others

Type TypeName String Annotation supported? Tested emission? Commit
ChiselEnum 🔜 🔜
Decoders 🔜 🔜
Properties 🔜 🔜
Layers 🔜 🔜
Functional abstraction (scala meta programming) ? (Counter, Mux...) Not sure if it needs support

@rameloni
Copy link
Contributor Author

rameloni commented Apr 19, 2024

Update of 19-04-2024

I have already done some work on that: rameloni@65a47f3

So far I:

  1. Created a TywavesAnnotation (firrtl) case class to represent the annotation
  2. Created a companion object to generate the respective ChiselAnnotations for Chisel circuit: it parses a chisel circuit, extracts the necessary information from each component, and annotates each FIRRTL target
  3. Created AddTywavesAnnotations phase to add the TywavesAnnotation to the elaborated Chisel circuit
  4. Updated ChiselStage to integrate AddTywavesAnnotation phase (run before Convert phase only if withDebug is true)

Point 2, however, raises some doubts for me. It explores a Chisel circuit as it is done in Converter.convert, so there is a redundancy of code. I know, that, in general, annotations (such as dontTouch) are generated inside the builder context by the execution of the scala meta-program.
However, if I were to let the user annotate every single variable/module this would become a long, repetitive, error-prone process.
Consequently, I was wondering if I could create something alternative like binding a whole module and recursively annotating every hardware component in it. This I'm pretty sure is possible for IO ports but not for inner wires, registers, and modules.

@rameloni
Copy link
Contributor Author

rameloni commented Apr 21, 2024

Update of 21-04-2024

I added annotation support to:

  • Modules
  • Ports, registers, and wires of any data type extending Data (for vectors of the same type only the first element of each dimension is annotated to reduce the size of emitted firrtl)
  • Memories of any data type extending Data

However, for memories the annotation of aggregates (Vecs, Bundles and user defined) will work only if the memory is effectively used. This means that, in the following example, annotations for the fields a and b of MyBundle are generated only when withConnection is true.

class TopCircuitSyncMem(withConnection: Boolean /* If true connect memPort */ ) extends Module {
  class MyBundle { val a = UInt(8.W); val b = SInt(8.W) }
  val gen = new MyBundle
  val mem = SyncReadMem(4, gen)
  if (withConnection) {
    val idx = IO(Input(UInt(2.W)))
    val in = IO(Input(gen))
    val out = IO(Output(gen))
    mem.write(idx, in)
    out := mem.read(idx)
  }
}

This would make sense to me since the mem is not instantiated if unused. However, I am unsure about that, since the annotation has MPORT.a and MPORT.b as targets rather than the expected mem.a and mem.b as targets.

I reported here the outputs: https://github.com/rameloni/chisel/blob/ff1de98fce44950d137dacc156da85dba8d3bddd/src/test/scala/circtTests/tywavesTests/memTests/README.md#syncreadmem

@rameloni
Copy link
Contributor Author

Update of 22-04-2024

I would like to create the type annotation for parametric and parametrized modules in the following way:

class CircuitWithParam(n: Int, c: String)
   extends Module
class CircuitWithParam(val n: Int, val c: String)
   extends Module

class CircuitParametric[T] extends Module
{
  "class":"chisel3.tywaves.TywavesAnnotation",
  "target":"~CircuitWithParam|CircuitWithParam",
  "typeName":"CircuitWithParam(2, "Hello world!")"
}

Or using maps:

{
  "class":"chisel3.tywaves.TywavesAnnotation",
  "target":"~CircuitWithParam|CircuitWithParam",
  "typeName":"CircuitWithParam(n, c),
  "params":{
      "n":"2",
      "c":"Hello world!"
  }
}

While for parametric something similar:

{
  "class":"chisel3.tywaves.TywavesAnnotation",
  "target":"~CircuitParametric|CircuitParametric",
  "typeName":"CircuitParametric[Int]
}

Support for modules with parameters

I managed to get good results for getting values, names and types of field parameters. I am now able to retrieve the fields of any given scala class (including modules, bundles etc...) and filter the ones of the constructor only. In addition, I can also get recursive fields when a field is of a complex type.

I created a method getConstructorParams(target: Any): Seq(ClassParam) to do that, where ClassParam is a case class that I use to encode the parameters of a given class.

In the following example, I'm able to access any val (public, protected and private):

class Base(val a: Int, c: Float)
class A(private val a: Int, val x: String, val base: Base) { val c = 10 }
class B(protected val aClass: A) { val c = 10 }

val b = new B(new A(1, "ciao", new Base(3, 1.1f)))

println(getConstructorParams(b)) // This return a: case class ClassParam(name: String, typeName: String, value: Option[String])

This example would emit:

ClassParam("aClass", "A", Some("A(a: 1, x: ciao, base: Base(a: 3, c))")))

NOTE: it is worth to notice that seems that scala reflection cannot be used to access actual values of parameters that are not val or var. This is something, that I think it's not really a problem: if user likes to have also the value of a parameter of a module they should declare it as a val otherwise they can see only the type and the name.

So far I've tested it with generic scala classes. I still need to create proper tests for parametric chisel constructs, but they would work similarly so I don't think I will have problems.

Support for paramteric modules

I think I can exploit scala reflection to get information also for Parametric classes.

@jackkoenig
Copy link
Contributor

@rameloni You're doing some awesome work here. You might be at a good point to start looking into how this information should be consumed by firtool. We don't want to support annotations long term (they were the way we extended the Scala FIRRTL Compiler, but firtool doesn't have the same flexibility since the annotations have to be explicitly handled by the firtool codebase), so we should discuss how this information may be best communicated from Chisel to firtool, perhaps via the FIRRTL spec. I am not saying you shouldn't use annotations at the moment, but we should think about what representation the maintainers of firtool would prefer.

Related to that, I'm curious how this information should be represented within firtool across lowering. That's something I don't know much about so perhaps we should try to schedule time in the CIRCT meeting to discuss, or perhaps @seldridge or @fabianschuiki may have some ideas to share here.

@rameloni
Copy link
Contributor Author

rameloni commented Apr 23, 2024

Thank you very much @jackkoenig.
Yes, I think I now have enough support for a great part of the chisel constructs to start looking into the next step. Of course, there are other things to finish with annotations, but I guess I can eventually fix them meanwhile I'll be working on firtool.

I'm using annotations only in the last step of my implementation, all the other steps are independent from the annotation system.
I decided to use the annotation system since it can associate arbitrary metadata to any firrtl target (solving the ID issue of my demo). In other words, I found it a good and easy way to systematically get a 1-to-1 mapping from chisel to firrtl.

I didn't look yet carefully into firtool since I was trying to implement the "parameter annotation for scala classes", I think I got a nice result about that. I'm also able to access names, types and values of a specific field (val and var) of any class, although I restricted it to the constructor only and I also need to add proper tests for Modules and Bundles with parameters. I'll make an updated post later today (I think it's a good way to post updates about the features I'm implementing).

@fabianschuiki
Copy link
Contributor

This is really nice! 🥳 I agree with @jackkoenig that using annotations is good to get things rolling, but we'll have to find a more permanent solution later. Firtool internally uses its Debug dialect to track information through the pipeline. It currently uses the FIRRTL ports and types to conjure up these trackers.

Ideally, with your annotations @rameloni, we'd be able to generate these trackers directly from the annotations. In the long run, we may want to extend the FIRRTL spec to add statements that can annotate debug information as we need them. We can prototype a lot of this with intrinsics, while we try to figure out how things should work.

One cool first thing to try would be to make the Chisel compiler plugin that opportunistically annotates val names onto expressions actually create a debug variable intrinsic (which doesn't exist yet) for every val. That would make all vals show up in the waveform viewer, regardless of what happens in the Verilog. Then there's the whole hierarchy and call stack that we could try to annotate. Maybe mirroring the debug dialect ops in FIRRTL intrinsics is sufficient to add Chisel-level type and hierarchy info to the output.

@rameloni
Copy link
Contributor Author

rameloni commented May 2, 2024

@fabianschuiki I managed to associate my annotations with the Firrtl dialect and process them MaterializeDebugInfo through the addAnnotation function in LowerAnnotations pass. Now, I should be able to include them into the debug dialect and access them from an emitter similarly to EmitHgldd. To do so, I've been thinking of adding an optional field in the debug dialect operations to contain that information.

At the moment, I thought to try to get it working through annotations because it wouldn't require to update/add new things on chisel side the code and I wanted to understand a bit more how firtool works.
Regarding the intrinsics, I'll postpone their usage if I get it fully working with the annotations, otherwise I'll stop implementing it through annotations and I'll move to intrinsics.

And thank you for the help and recommendations!

@fabianschuiki
Copy link
Contributor

That sounds very exciting! What kind of additional information do you want to attach to the debug operations? You should be able to do so without changing the debug dialect directly, by just adding them as attributes when you create the operation itself. That might get you pretty far.

@rameloni
Copy link
Contributor Author

rameloni commented May 2, 2024

Yes, with "adding optional field" I meant an attribute through the table gen.
I thought to attach what I have in the annotations so far: the chisel type and the list parameters of that type constructor (which also define the "type").

However, I may process the annotations directly into the emitter without passing through the MaterializeDebugInfo and without adding any attribute to the debug dialect. This is a last minute idea though 😅 maybe an attribute in the debug dialect is not needed.

@fabianschuiki
Copy link
Contributor

fabianschuiki commented May 2, 2024

Yeah you can also add attributes to ops that are not part of the debug dialect *.td file. That's very useful for experimenting and getting things up and running, before you decide exactly what to do.

If the Chisel type is a struct or array, you probably want to create many debug dialect ops for it. Basically, disassemble the FIRRTL value and reassemble it based on your type using dbg.array, dbg.struct, and dbg.variable ops. One of the key things the debug dialect wants to do is track how things like struct fields or class members are modified and transformed through the compilation pipeline. This is done by taking all struct/array types apart into separate %N values in the IR, and then re-assembling the structs and arrays using debug dialect op. That allows the compiler to do whatever it wants with the values in order to optimize the compilation, while the debug dialect can still tell you how to assemble the original Chisel type.

Do you have a few concrete examples of how that type information looks like?

@rameloni
Copy link
Contributor Author

rameloni commented May 2, 2024

Yes, I've seen that, I've already played a bit with that. I'll try to get an emitter tomorrow with a file format compatible with the viewer (the one I generated through the demo), so I think I'll fix some technical issues of the demo and then I can redefine the file format with a better and more robust version (hopefully from Monday).

@rameloni
Copy link
Contributor Author

rameloni commented May 2, 2024

If the Chisel type is a struct or array, you probably want to create many debug dialect ops for it. Basically, disassemble the FIRRTL value and reassemble it based on your type using dbg.array, dbg.struct, and dbg.variable ops. One of the key things the debug dialect wants to do is track how things like struct fields or class members are modified and transformed through the compilation pipeline. This is done by taking all struct/array types apart into separate %N values in the IR, and then re-assembling the structs and arrays using debug dialect op. That allows the compiler to do whatever it wants with the values in order to optimize the compilation, while the debug dialect can still tell you how to assemble the original Chisel type.

Oh yes, I see why debug dialect is important for this aspect, it may justify the choice of adding an attribute instead of propagating the annotations attached to firrtl to the emitter.

Do you have a few concrete examples of how that type information looks like?

I have some examples of how this type information is represented in firrtl annotations. I think an example with bundles and vecs may be enough to cover almost all cases (I tried to compact the output of firrtl):

// A user defined bundle
class MyBundle[B <: Data](val x: B, val w: Int) extends Bundle {
    val innerX = UInt(w.W)
}
    
// A nested bundle
class MyBundleNested(val size: Int) extends Bundle {
    val inner1 = SInt(7.W)
    val inner2 = new MyBundle(Bool(), size)
    val inner3 = Vec(2, new Bundle {val y = Bool()})// Vector of anonymous bundles
}

class TopCircuit[T <: Data] extends RawModule {
    val aIn = IO(Input(new Bundle {}))
    val bIn = IO(Input(new MyBundle(UInt(8.W), 2)))
    val vIn = IO(Input(Vec(4, UInt(8.W))))

    val nested = Wire(new MyBundleNested(4))
    val nestedOut = IO(Output(new MyBundleNested(4)))

    // Connections
    nested.inner1 := vIn(0).asSInt
    nested.inner2 := bIn

    nestedOut <> nested
 
}
FIRRTL version 4.0.0
circuit TopCircuit :%[[
  {
    "class":"chisel3.tywaves.TywavesAnnotation", "target":"~TopCircuit|TopCircuit", 
    "typeName":"TopCircuit"
  },
  {
    "class":"chisel3.tywaves.TywavesAnnotation", "target":"~TopCircuit|TopCircuit>aIn", 
    "typeName":"IO[AnonymousBundle]"
  },
  {
    "class":"chisel3.tywaves.TywavesAnnotation", "target":"~TopCircuit|TopCircuit>bIn.innerX", 
    "typeName":"IO[UInt<2>]"
  },
  {
    "class":"chisel3.tywaves.TywavesAnnotation", "target":"~TopCircuit|TopCircuit>bIn.x", 
    "typeName":"IO[UInt<8>]"
  },
  {
    "class":"chisel3.tywaves.TywavesAnnotation", "target":"~TopCircuit|TopCircuit>bIn", 
    "typeName":"IO[MyBundle]",
    "params":[
      { "name":"x", "typeName":"B", "value":"IO[UInt<8>]" },
      { "name":"w", "typeName":"Int", "value":"2" }
    ]
  },
  {
    "class":"chisel3.tywaves.TywavesAnnotation", "target":"~TopCircuit|TopCircuit>vIn[0]",
    "typeName":"IO[UInt<8>]"
  },
  {
    "class":"chisel3.tywaves.TywavesAnnotation", "target":"~TopCircuit|TopCircuit>vIn",
    "typeName":"IO[UInt<8>[4]]",
    "params":[
      { "name":"gen", "typeName":"=> T"},
      { "name":"length", "typeName":"Int" }
    ]
  },
  {
    "class":"chisel3.tywaves.TywavesAnnotation", "target":"~TopCircuit|TopCircuit>nestedOut.inner3[0].y",
    "typeName":"IO[Bool]"
  },
  {
    "class":"chisel3.tywaves.TywavesAnnotation", "target":"~TopCircuit|TopCircuit>nestedOut.inner3[0]",
    "typeName":"IO[AnonymousBundle]"
  },
  {
    "class":"chisel3.tywaves.TywavesAnnotation",  "target":"~TopCircuit|TopCircuit>nestedOut.inner3",
    "typeName":"IO[AnonymousBundle[2]]",
    "params":[
      { "name":"gen", "typeName":"=> T" },
      { "name":"length", "typeName":"Int" }
    ]
  },
  {
    "class":"chisel3.tywaves.TywavesAnnotation", "target":"~TopCircuit|TopCircuit>nestedOut.inner2.innerX",
    "typeName":"IO[UInt<4>]"
  },
  {
    "class":"chisel3.tywaves.TywavesAnnotation", "target":"~TopCircuit|TopCircuit>nestedOut.inner2.x",
    "typeName":"IO[Bool]"
  },
  {
    "class":"chisel3.tywaves.TywavesAnnotation", "target":"~TopCircuit|TopCircuit>nestedOut.inner2",
    "typeName":"IO[MyBundle]",
    "params":[
      { "name":"x", "typeName":"B", "value":"IO[Bool]" },
      { "name":"w", "typeName":"Int", "value":"4" }
    ]
  },
  {
    "class":"chisel3.tywaves.TywavesAnnotation", "target":"~TopCircuit|TopCircuit>nestedOut.inner1",
    "typeName":"IO[SInt<7>]"
  },
  {
    "class":"chisel3.tywaves.TywavesAnnotation", "target":"~TopCircuit|TopCircuit>nestedOut",
    "typeName":"IO[MyBundleNested]",
    "params":[
      { "name":"size", "typeName":"Int", "value":"4" }
    ]
  },
  {
    "class":"chisel3.tywaves.TywavesAnnotation", "target":"~TopCircuit|TopCircuit>nested.inner3[0].y",
    "typeName":"Wire[Bool]"
  },
  {
    "class":"chisel3.tywaves.TywavesAnnotation", "target":"~TopCircuit|TopCircuit>nested.inner3[0]",
    "typeName":"Wire[AnonymousBundle]"
  },
  {
    "class":"chisel3.tywaves.TywavesAnnotation", "target":"~TopCircuit|TopCircuit>nested.inner3",
    "typeName":"Wire[AnonymousBundle[2]]",
    "params":[
      { "name":"gen", "typeName":"=> T"},
      { "name":"length", "typeName":"Int"}
    ]
  },
  {
    "class":"chisel3.tywaves.TywavesAnnotation", "target":"~TopCircuit|TopCircuit>nested.inner2.innerX",
    "typeName":"Wire[UInt<4>]"
  },
  {
    "class":"chisel3.tywaves.TywavesAnnotation", "target":"~TopCircuit|TopCircuit>nested.inner2.x",
    "typeName":"Wire[Bool]"
  },
  {
    "class":"chisel3.tywaves.TywavesAnnotation", "target":"~TopCircuit|TopCircuit>nested.inner2",
    "typeName":"Wire[MyBundle]",
    "params":[
      { "name":"x", "typeName":"B", "value":"Wire[Bool]" },
      { "name":"w", "typeName":"Int", "value":"4" }
    ]
  },
  {
    "class":"chisel3.tywaves.TywavesAnnotation", "target":"~TopCircuit|TopCircuit>nested.inner1",
    "typeName":"Wire[SInt<7>]"
  },
  {
    "class":"chisel3.tywaves.TywavesAnnotation", "target":"~TopCircuit|TopCircuit>nested",
    "typeName":"Wire[MyBundleNested]",
    "params":[
      { "name":"size", "typeName":"Int", "value":"4" }
    ]
  }
]]
  public module TopCircuit :
    input aIn : { }
    input bIn : { x : UInt<8>, innerX : UInt<2>}
    input vIn : UInt<8>[4]
    output nestedOut : { inner1 : SInt<7>, inner2 : { x : UInt<1>, innerX : UInt<4>}}

    wire nested : { inner1 : SInt<7>, inner2 : { x : UInt<1>, innerX : UInt<4>}}
    node _nested_inner1_T = asSInt(vIn[0])
    connect nested.inner1, _nested_inner1_T
    connect nested.inner2, bIn
    connect nestedOut, nested

I have other examples here:

@rameloni
Copy link
Contributor Author

rameloni commented May 3, 2024

I moved the conversation about the part related to firtool here: llvm/circt#6983

I thought it was better since I'm working on circt for this part.

@rameloni
Copy link
Contributor Author

@jackkoenig is there any diagram about chiselsim pipeline? I may need for my thesis, but I only found the one in the chiselbook which is outdated since it uses the SFC and not firtool. I could always create one by myself, but I was wondering if there's an official one that I can use. Thanks ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants