I have an use case where I want an external circuit to initialize some memory content. Currently I am exposing the native memory control signals (i.e. address, data, we, en, etc) manually all the way to the top module. Although a bit tedious, the way RTL is generated makes this relatively easy.
Until CIRCT fully supports something like ESI or can easily generate an AXI master interface on one of the ports ( which could then be used to fetch data from somewhere else and initialize the memories without external circuitry) I am relying on an external memory initializer to fetch the data from main memory.
I was wondering if anyone has been considering adding a pass that offers this kind of functionality: exposing internal signals to the top level module. I can see even a debug value on this where we can simply instantiate the top level module and some of the internal signals are already exposed, ready to be hooked up to an ILA.
You might look at the recent FIRRTL work implementing the
boring (?) API. (Boring like tunneling.) I think this is exactly what you’re looking for. It’d be really useful to have that but not FIRRTL specific.
We (SiFive) are slowly working towards this type of thing. There are a number of internal features (which we’re intending to make public) around memory extraction, though they may not have public Chisel APIs. There are other, public Scala FIRRTL Compiler (SFC) transforms that provide primitives for doing things like what you’re trying to do. Enumerating these:
- SiFive Memory Extraction – Take a memory and move it to the test harness so that an end user can add signals to it.
- SiFive Memory Port Addition – Drill some ports in from the top to specific memories.
- SFC Wiring Transform/Chisel’s
BoringUtils – An implementation of “soft connects” that lets a user describe sources and sinks in the design that will be wired together by the compiler.
- SFC Top Module Transform – A specialized wiring transform that will drill some signals all the way to the top for connection to FPGA logic debug units.
As may be obvious, a lot of this was demand driven. (1) and (2) are both two different ways of doing the same thing that could be potentially solved by (3) if it was generic enough. (3) is pretty generic, but has some edge cases that didn’t work for everybody. (4) is one such edge case.
Ideally, I’d like to approach this from two directions: (1) in the near term continue to drive and support the existing FIRRTL custom transform stack and (2) in the mid term work towards adding the necessary primitives (operations, attributes) necessary for these types of manipulations (e.g., resolution of soft connects, hierarchy manipulations, etc.). I think the only bad solution would be to wind up with many one-off, highly specialized transforms for different purposes.
One way of approaching this is to think about a cross-module reference (XMR) primitive that can either be lowered to actual connections or SystemVerilog hierarchical references. (I wrote up something like this in: Cross Module Reference (XMR) Primitive · Issue #933 · llvm/circt · GitHub
And I agree with John that I’d like to see this as something that is generic and lives in
hw dialect. Any expedient porting of FIRRTL annotations/transforms can then be switched to support the more generic work in
hw or other downstream dialects.