Keyboard Shortcuts
Likes
Search
Best Practices for Simulation in Bluespec
You can find the snippets referenced below in the code .
?
In general, with respect to simulation and VCD interpretation. I’d appreciate any advice on the following:
1. What’s the best way to simulate Bluespec designs effectively? Are there tricks to make Bluesim or Verilog output more usable?
2. VCD Signal Names: My VCDs have cryptic names like:
```
$var reg 3 ; IF_tagEngine_resetTagCounter_2_BIT_3_3_THEN_ta_ETC___d30 $end ``` These seem to come from a case statement in my requestTag method:
```
requestTag :: ActionValue UIntLog2N(numTags) requestTag = do ? ? case resetTagCounter of ? ? ? ? Just 0 -> do resetTagCounter := Nothing; return 0 ? ? ? ? Just tag -> do resetTagCounter := Just (tag - 1); return tag ? ? ? ? Nothing -> do freeQueue.deq; return freeQueue.first ``` Names like that make VCDs EXTREMELY hard to use and basically useless.
?
How can I map these back to my source code? Is there a way to get cleaner signal names?
3. Sum/Product Types in VCDs: My design uses Maybe (e.g., Reg (Maybe (UInt 3))) and vectors of registers. In the VCD, these appear as raw bit vectors. How do one decode their symbolic values (e.g., Just 2 vs. Nothing) during simulation?
4. Higher-Level Simulation: TCL feels clunky for testbenches. Has anyone integrated Bluespec with Python (e.g., via PyVerilator or cocotb) for a more modern workflow?
I’m relying heavily on $display for debugging, which helps, but I’d like to leverage waveforms more effectively. Any tips or tools you recommend would be great! Theres no way $display will/scale as my design get larger.
If there's currently nothing better than my flow, Bluespec urgently needs improved simulation tooling. |
On Wed, Apr 2, 2025 at 06:40 AM, Yehowshua Immanuel wrote:
I think the In general state elements and rules keep their names in a not-too-mangled shape. For rules,
Well, if the names matched your source 1 : 1, then IIRC the names do preserve source locations if possible (although YMMV b/c CSE and other optimizations), and I vaguely recall that there is some way to get at them using BlueTcl (although I haven't used that myself, so not sure). In my experience, knowing what the state is and what happens to it (= which rules fire) is a lot of what you need to know to effectively debug a design.
A common trick is to use interfaces instead of structs — I think that preserves the fields at least? Also, some waveform viewers allow you to script the formatting that appears in the waveform. I've done this, but rarely b/c it's annoying to do manually. I guess the latter could be automated, I think BlueTcl knows what the structure of types is?
I'm sorry to say that generally in the EDA industry everything is driven via Tcl. But Bluespec is an open-source project, and you have experience writing this kind of tooling — why not take a stab at improving that aspect? |
开云体育I already added `-keep-fires`?. The issue I’m having is that the generated VCD literally doesn’t have doesn’t even have the word `request` in it even though `TagEngine` has the `requestTag` method…Is this typical? I would imagine in an ideal world methods should at least have respective can/will fire signals show up in the VCD? To reproduce, you can do: ``` git clone? cd?riscv-bluespec-classic TOPMODULE=mkSim make b_compile b_link b_sim_vcd ``` I’ve attached the VCD for convenience. It seems very strange that a whole method would not show up... Yehowshua |
There's a GUI environment called BDW, available in the repo , which automates the connection to the GTKwave VCD viewer and provides the scripts for displaying enums and tags as their source code names, and for separating struct fields and vector elements into separate lines.? That code could probably be extracted into a command-line tool, if one would prefer not to use a GUI.? The BDW GUI also supports viewing the source code module hierarchy (including intermediate modules that have been inlined) and users can click on interfaces, state elements, and rules, to automatically add the related signals to the attached GTKWave viewer. As Mieszko said, I only use VCDs for those things -- method ports, state elements, and rule firings -- which have clear naming in the generated code.? I don't debug combinational logic that way, though you can use Probes as Mieszko said.? I tend to use display statements etc. The reason why the word 'request' doesn't show up is because you haven't specified that module for separate synthesis -- BSC inlines submodules.? If the logic for 'request' gets merges with logic from the calling location in the parent module, then there won't necessarily be any signal in the generated Verilog that corresponds to 'request'.? If there's a signal in the generated code that appears to have the same definition as 'request', then it's possible that there's a correctable bug in BSC that we can try to fix -- see if you can create a small example and open an issue.? BSC does generally try to keep source names where it can. But during elaboration, sometimes BSC has to create new signal names, for subexpressions or newly created expressions, and those start with names that are just unique numbers, like "__d1", "__d2", __d3", etc.? That's entirely unhelpful, so BSC attempts to give more meaningful names to these, based on the expression that they are assigned to.? This is defined in "src/comp/SignalNaming.hs", I believe, and I think I've written an explanation of it before -- but for example, if you had: __d1 = x?+ y then BSC would name it "x_PLUS_y__d1".? And this: __d2 = x[2:0] would be named "x_BITS_2_0__d2". During elaboration, case expressions becomes nested if-then-else and everything is optimized down to bits, so examing of tags is just equality on extracted bits, so your expression probably was something like this: __d3 = if (foo[3:3] == 1) then ... which gets named "IF_foo_BITS_3_3_EQ_1_THEN_..." but to avoid generating really long names, they are truncated at some point and just end with "_ETC__d3".? I agree that these longer names are not so helpful, but still better than just "__d3".? Suggestions on how to format these descriptive names is welcome, if you have better ideas. My suggestion, though, would be to insert a synthesis boundary on the "mkTagEngine" module etc. ?(It's worth nothing that Mieszko's suggestion of using "interface" is only going to be helpful on a separately-synthesized module.? You can also try out PR #729, which implements a feature in BSC to split method input ports into separate ports for each field or sub-element.) If you don't want to insert synthesis boundaries, you might try the BDW GUI's module browser.? As I said, it allows for viewing the inlined intermediate module hiearchy, and I believe that you can click on those modules to send any associated signals (that have remained in the Verilog) to the GTKWave viewer. Note that BSC elaborates all the way to bits for Bluesim just as it does for Verilog.? Bluesim is able to linearize the rule execution, but isn't currently doing anything more high-level for the logic execution within each rule.? In theory, it may be possible to implement an evaluator that doesn't expand as far, so that simulation can be kept at a higher level (preserving types and perhaps some loops etc) -- I once experimented with this by trying to tweak the existing evaluator, but ran into some snags, it's probably a significant project.? Also note that the Verilog backend does some optimization of the signals, inlining ones that are simple or only used once, etc; whereas Bluesim doesn't do much optimization.? So you might see more signal names in the Bluesim VCD -- if you're debugging from VCD, I would tend to use the Verilog, which might be less cluttered. ?(Also, you might even see if Verilator on the Verilog simulates faster than the Bluesim anyway, for a given design.) As for Tcl and Python, embedding the current Bluetcl in Python would be straightforward and would be great to see, if someone wants to give it a go.? I described a little about this in a previous email thread.? But basically, the functions are implemented into Haskell and that's exported to C and compiled in with a Tcl kernel.? I haven't embedded Haskell functions in Python to know if there's a more direct route, but certainly one could export to C and then import them into Python.? The only bit of work, really, is that the current Haskell functions are a little specific to Tcl in how they expect to receive and return data, and so one might want to decouple the underlying behavior from the specifics of the interface a little more, so that it can be shared by a Tcl wrapper and a Python wrapper. J |
Can you define specific instances to synthesize?? For example:
and then synthesize that, and call "mkTagEngine5" where you need it? If you need nested levels of polymorphism, then another option is to use a typeclass:
and then call "mkTagEngineSynth" anywhere you want a synth boundary and the context will specify which instance to use.? You'll need to populate the typeclass with the instances you need:
There's even a script to automate this process, "InstSynth.tcl" (for "instance specific synthesis"), in bsc/util/bluetcl-scripts/.? Of course, it would be nice if the script wasn't needed and that BSC could support it natively, for example by putting a synthesize pragma on the submodule instantiation.? These workarounds (and potentially others) are discussed on GitHub issue #543. J |