B-Lang-org / bsc

Bluespec Compiler (BSC)
Other
955 stars 146 forks source link

Feature request: FIRRTL output #468

Open john-terrell opened 2 years ago

john-terrell commented 2 years ago

FIRRTL output would allow BSV to take advantage of the ecosystem popping up around Chipyard/RocketChip while still using BSV.

FIRRTL: https://www.chisel-lang.org/firrtl/

Thoughts?

rsnikhil commented 2 years ago

We have had FIRRTL on our radar as a potential back-end for bsc since about 2013 (we've interacted with the Berkeley RISC-V and Chisel folks since that time), for the very reason you mention (leverage the FIRRTL ecosystem).

We think it would be great to do this, but haven't had the resources ourselves to do it.

Also, FIRRTL in the early days was changing a lot, and so we thought we'd wait until things became more stable.

Now may be a good time to revisit the topic, if someone has the time an energy to pursue it.

Note: Bluespec, Inc. is a regular user of Chipyard and the Rocket generator (and has been, for some years now), but just using the generated RTL for Rocket to plug into Bluespec systems, nothing FIRRTL-specific.

quark17 commented 2 years ago

Adding a new backend is fairly straightforward and self-contained. For context:

The compiler is a series of stages and, between each stage, the design exists in a data structure. Each stage takes in the data structure and returns a data structure. Often it's the same data structure, but at several points in the series, there are stages that convert from one representation to another. The main representations are:

  1. a source representation very close to BH/Classic syntax (pre-elaboration and at first not-typechecked but then it's typechecked);
  2. an elaborated module (code is computed leaving just the state and rules and interface -- there are no loops or abstract types any more, just unrolled functions on bit and bit vectors)
  3. an elaborated module plus a schedule that has been computed; and
  4. a generated module (the rule-based module and schedule is converted to a netlist-ish module).

After any stage in the series, we could insert a function that takes the current data structure and then writes out a file for that module (or package). We are already doing this in four different places: the Verilog backend, the Bluesim backend, and two experimental dumps that output the design as unscheduled LambdaCalculus and SAL (a language for symbolic analysis).

The Verilog backend operates on the generated module (no 4). At that point, the design inside BSC is just modules with ports and wire assignments (and any foreign function calls for simulation), so printing this as Verilog is mostly straightforward. Although there are few quirks of Verilog syntax that have to be worked around.

The Bluesim backend operates from an earlier point, on the elaborated module with schedule (no 3). This allows the Bluesim model to execute the bodies of rules in a static sequence, at clock edges; which can be faster than keeping dynamic lists of which signals have changed and then updating the signals that depend on those etc etc. (Similar to how Verilator gets its speedup, by determining a static non-cyclic order of signals.)

There are also two experimental dumps, on the elaborated module before scheduling (no 2). These can be activated with the hidden flags -ddumpLambdaCalculus and -ddumpSAL. These were added for a researcher who was experimenting with ways of analyzing BSV designs. Like Bluesim and Verilog, the output is not usable on its own; there is also a pre-written library that is needed alongside it. For Verilog, that library is just the definitions for any submodules that are instantiated in the generated module. For Bluesim, though, it's not just the submodules but also an additional library of code that is used by the generated code. The same is true for the LC and SAL dumps: they also make use of library functions (and modules) that need to be defined elsewhere.

Anyway, getting back to FIRRTL!

If I understand correctly, BSC can already plug into the FIRRTL ecosystem by applying a Verilog-to-FIRRTL tool to BSC's generated Verilog. Is that true? The proposal here, then, is to get some benefit by outputting FIRRTL code directly. I admit that I don't know FIRRTL enough yet to understand the scope of this benefit. Obviously, removing a layer of indirection would be good, but if you have some thoughts, I would be interested to hear. I could see it depending on where the FIRRTL backend starts.

If BSC were to simply output FIRRTL at the point where it currently outputs Verilog (no 4), then I'm not sure how much benefit would be seen. (But I'm happy to be corrected!) I would guess that you'd want to take advantage of some of the high-level constructs that FIRRTL provides. (Though, again, I don't yet know enough about FIRRTL to know what they are. But my understanding is that the FIRRTL ecosystem talks about lowering designs down to LoFIRRTL, which is like a structured netlist. That's what point no 4 is in BSC, so we'd only be able to output LoFIRRTL at that point, I'd think.)

What you'd like, perhaps, is to branch from a point in BSC where the design is sufficiently elaborated (to identify all the submodules, rules, and interface) but not so elaborated that high-level types and loops have been reduced to flat wires. Unfortunately, there's not currently any point like this.

As I said in the description of no 2 above, BSC's elaboration process removes high-level types and loops. There was an idea to split the elaboration into two parts, where the first step would elaborate just enough to determine the hardware (leaving as much high-level types and loops/generates as possible) and the second step would then elaborate the rest. Then the point between the two stages would be available for branching a backend. The Bluesim backend, for example, could benefit from operating on higher-level types perhaps. Some experimentation was done, to attempt this, but it wasn't successful.

Unfortunately, I think that this kind of enhancement to BSC would be necessary for a FIRRTL output to be useful. But if there are ideas for how to still use higher-level FIRRTL from the existing branch points, I'm open to hearing about that. Or if you think there's still benefit to dumping low-level FIRRTL.

If someone wants to try adding a FIRRTL output at an existing point in BSC, I'd be happy to mentor through that process.

quark17 commented 2 years ago

There's a talk, "Chisel/FIRRTL Ecosystem Updates", at the ChipsAlliance Spring Event, streaming online tomorrow: https://chipsalliance.org/workshops-meetings/

I may have to wait until the YouTube recording is available, since that's too early in my timezone. The ChipsAlliance Autumn Event, six months ago, also had a Chisel/FIRRTL talk, with a quick intro to the ecosystem. The slides and video are posted for that, and can be found further down on the page of the above URL, but here's a direct link to video of the talk: https://youtu.be/auXZdPwYs10?t=2958

quark17 commented 2 years ago

I wanted to emphasis this comment that might have been buried:

If someone wants to try adding a FIRRTL output at an existing point in BSC, I'd be happy to mentor through that process.

This could be a great project for a university student (or Google Summer of Code). The main work here is in researching where the best branch point is and how best to represent things.

Also, to answer a few of my own questions: FIRRTL attempts to improve reusability by allowing a single source to be synthesized to different targets (ASIC, FPGA, Verilator, etc). BSC doesn't have a great story for this, but attempts to get around it somewhat by having different implementations of primitive Verilog modules for different simulators -- which is a bit of a maintenance headache. It'd be interesting to see if outputting FIRRTL could relieve BSC of having to manage this and rely on FIRRTL synthesis tools to do it. I also understand that there are formal tools for FIRRTL/Chisel; it would be interesting to know whether formal analysis of BSC-generated FIRRTL (likely low-level FIRRTL) would be any better than formal analysis of the generated Verilog.