¿ªÔÆÌåÓý

ctrl + shift + ? for shortcuts
© 2025 Groups.io
Predicate Module Behavior on Blueish Context or Not 2
I have a UART module whose behavior I want to change depending on whether or not we're in Bluesim or emitted to actual hardware. If we're in Bluesim, I'd like to call some BDPI functions. If we're in hardware, I want to call my serializer and deserializer methods. Does bluespec have some `detect_bluesim` function or constant that evaluates to true in bluesim and evaluates to false when synthesizing to verilog?
Started by Yehowshua Immanuel @ · Most recent @
Import C Functions in Bluespec Haskell instead of Bluespec Verilog 2
Is it possible to import C functions in Bluespec Haskell? Currently struggling to convert the following to Bluespec Haskell: https://git.joyofhardware.com/ReferenceProjects/riscv-bluespec-classic/src/branch/main/bsv/CBindings.bsv
Started by Yehowshua Immanuel @ · Most recent @
Bluespec in CICD Assertion Failures 2
I'm trying to make it easy for CICD to detect when bluespec simulations / unit tests fail. I was thinking that `$finish 1` was what I wanted to indicate an error, but `echo $?` shows `0`... I'm wondering what the correct way is to get bluesim to return an exit status.
Started by Yehowshua Immanuel @ · Most recent @
Can Fire and Will Fire enabled even though rule doesn't fire in Sim 3
The following rule doesn't trigger in simulation which is the expected behavior. I know it doesn't trigger because un-commenting `$display "clientRequest" (fshow clientRequest)` never prints anything. Oddly enough however, it seems `WILL_FIRE` and `CAN_FIRE` are always high in the generated VCD... Why is this? The reason this rule shouldn't trigger is because `first` method of a FIFO is guarded which becomes an implicit condition for the containing rule. When it comes to this code, I call `selectedClientRequestQueue.first` which becomes an implicit guard condition for the rule. Here's the relevant code snippet below for easy access: ``` rules (sprintf "request server from client %d" clientIdx): when True ==> do let clientRequest :: TaggedBusRequest inFlightTransactions clientRequest = selectedClientRequestQueue.first targetAddr :: Addr = busRequestToAddr |> clientRequest.busRequest targetServerIdx :: (Maybe ServerIdx) = serverMap targetAddr -- $display "clientRequest" (fshow clientRequest) case targetServerIdx of Just serverIdx -> do let targetServerArbiter :: Arbiter.Arbiter_IFC numClients targetServerArbiter = (select requestArbiterByServer serverIdx) arbiterClientSlot :: Arbiter.ArbiterClient_IFC arbiterClientSlot = (select targetServerArbiter.clients clientIdx) arbiterClientSlot.request Nothing -> do action {} ``` Full reference code here: https://git.joyofhardware.com/ReferenceProjects/riscv-bluespec-classic/src/commit/813f543b424eed5a5eea985c5d13e0cb1fb12f30/bs/Bus.bs#L70
Started by Yehowshua Immanuel @ · Most recent @
Overload get and set for a type/typeclass
I am trying to define a type in BSV with overloaded get and set. Is this possible? To clarify, I am not looking to change the _read and _write methods of, for example, a register holding this type. I am also not looking for the Connectable typeclass. Is there a full list of operators/built-ins that can be overloaded?
Started by h@... @
Is it possible to use namespace in bluespec? 2
When using bluespec for large projects, we want to reuse some design as a library. For example, at first, I have a design called A, and it has three source file called foo.bav, bar.bav and baz.bsv, and there may be dependences between, like foo.bsv will import bar.bsv and baz.bsv. Then, I am working on another project B, which will use some functions from project A, I want to include project A as a git submodule in project B, but if project B also has a file called baz.bsv, the conflict will occur. In real projects, most filenames won't be the same, but there are always some files that has the name like utils.bsv, consts.bsv, etc. What I can do now is to copy the code form project A, rename them with a prefix, and change the related import statements in the copyed files to slove the conflict. In this way, its a hard copy of project B, not a git submodule.
Started by mmh_web @ · Most recent @
mapM_ for Vector 2
I'm currently trying to instantiate an Arbiter and call request for each client in `Arbiter_IFC.clients` in a rule. Its seems that `Vector.mapM` is the tool to get the job done?
Started by Yehowshua Immanuel @ · Most recent @
Can't get my provisos to discharge. 7
I'm trying to write a bus-width narrower and I'm having trouble getting the provisos to line up. My write request struct and a stripped down version of my "narrower" are as follows: typedef struct { Bit#(awidth) addr; // must be aligned, ie the low `size` bits must be 0. Bit#(TLog#(TAdd#(TLog#(dbytes),1))) size; Vector#(dbytes, Bit#(8)) data; } WriteReq#(numeric type awidth, numeric type dbytes) deriving (Bits, FShow); interface Narrower#(numeric type awidth, numeric type dbytes_wide, numeric type dbytes_narrow); interface Put#(WriteReq#(awidth, dbytes_wide)) wide; interface Get#(WriteReq#(awidth, dbytes_narrow)) narrow; endinterface module mkNarrower(Narrower#(awidth, dbytes_wide, dbytes_narrow)) provisos (Mul#(dbytes_narrow, max_beats, dbytes_wide), NumAlias#(TExp#(log2_wide), dbytes_wide), NumAlias#(TExp#(log2_narrow), dbytes_narrow), Add#(a__, log2_wide, awidth), Add#(b__, TLog#(TAdd#(TLog#(TExp#(log2_narrow)), 1)), TLog#(TAdd#(TLog#(TExp#(log2_wide)), 1))) ); ... endmodule The provisos involving a__ and b__ were suggested to bsc to get the module to typecheck. I added the other provisos to give names to various quantities. This typechecks. But when I try to instantiate it with concrete parameters: Narrower#(32, 128, 32) n <- mkNarrower; I get the following errors: Error: "Narrowing.bsv", line 73, column 8: (T0031) The provisos for this expression could not be resolved because there are no instances of the form: Mul#(TExp#(a__), b__, TExp#(c__)) The proviso was implied by expressions at the following positions: "Narrowing.bsv", line 74, column 32 Error: "Narrowing.bsv", line 73, column 8: (T0031) The provisos for this expression could not be resolved because there are no instances of the form: Add#(d__, c__, 32) The proviso was implied by expressions at the following positions: "Narrowing.bsv", line 74, column 32 Error: "Narrowing.bsv", line 73, column 8: (T0031) The provisos for this expression could not be resolved because there are no instances of the form: Add#(e__, TLog#(TAdd#(TLog#(TExp#(a__)), 1)), TLog#(TAdd#(TLog#(TExp#(c__)), 1))) The proviso was implied by expressions at the following positions: "Narrowing.bsv", line 74, column 32 Error: "Narrowing.bsv", line 73, column 8: (T0131) The numeric types `TExp#(c__)' and `128' could not be shown to be equal. This equality was required at the following position: "Narrowing.bsv", line 74, column 32 Error: "Narrowing.bsv", line 73, column 8: (T0131) The numeric types `TExp#(a__)' and `32' could not be shown to be equal. This equality was required at the following position: "Narrowing.bsv", line 74, column 32 It looks like the root problem is that bsc doesn't recognize that 32 and 128 are exact powers of two and hence a__ and c__ have to be 5 and 7 (the last two errors). (I used NumAlias#(TExp#(_),_) instead of Log#(_,_) because I only want widths that are an exact powers of two.) But I haven't been able to figure out any other formulation of the provisos that let bsc discover what it needs to know. Any suggestions would be greatly appreciated. -William
Started by William Howe-Lott @ · Most recent @
Coding style: Get/Put vs. Client/Server for pipelines? 3
(I appreciate that this is a subjective question and the general answer is "it depends", but gut wisdom and opinions from experienced Bluespec programmers would be very welcome!) I'm writing a modest graphics core in BSV, with a various moving parts: tile renderers, a sprite engine, a compositor, pixel drivers for various output protocols, and so on. I have a bunch of components that take some data in and produce data out: obvious ones like memory ports, and some domain-specific things like a palette engine (takes in a stream of palette indices, does lookups in palette RAM, outputs R/G/B color signals). Most of these components have both Get and Put interfaces. Some are obviously server-shaped (e.g. memory ports), whereas others represent part of a pipeline in which an upstream module connects to Put, and a downstream module connects to Get. How would you structure the APIs for modules that are expected to be pipelined in a chain? So far in my code, I've hesitated between two approaches: Write pipeline components as Servers. For example the palette engine above would be a completely reasonable Server#(PaletteIndex, RGB). Then write another module that represents the pipeline itself, which presents a bunch of Client subinterfaces and just connects A.response to B.request as needed. The top-level module instantiates a pile of Servers, the pipeline module with its pile of Clients, and wires them together. Write pipeline components as bespoke interfaces that have both Get and Put sub-interfaces, but the interface as a whole isn't a Connectable. The top level module now instantiates these individual pipeline components, and constructs the pipeline's data flow directly by connecting Puts and Gets together. I believe both of these approaches can be made to work, and can produce equivalent RTL when synthesized. Should I prefer one approach over the other? Or is there another better structure that I'm missing? I'm still relatively inexperienced in Bluespec, so I'm particularly interested in hard lessons learned, where it turns out a particular structure leads to headaches later, or conversely a particular structure results in more readable and maintainable code down the road. Thanks, - Dave
Started by David Anderson @ · Most recent @
Inquiry into Bluespec Scheduler Granularity Capabilities: Rule vs. Case-Arm Level 6
I¡¯ve been digging into the scheduling behavior of my TagEngine implementation and could use some insight from the community on how Bluespec resolves conflicts between methods and rules, particularly with respect to granularity. In my TagEngine (FIFO-based tag management), I have: * A requestTag method that issues tags, initially from a countdown (initialTagDistributor) and later from a tagFIFO: ``` requestTag :: ActionValue UIntLog2N(numTags) requestTag = do case initialTagDistributor of Just 0 -> do initialTagDistributor := Nothing (select tagUsageTracker 0) := True return 0 Just tag -> do initialTagDistributor := Just |> tag - 1 (select tagUsageTracker tag) := True return tag Nothing -> do let tag = tagFIFO.first tagFIFO.deq return tag ``` * A retire_tags rule that recycles tags into the tagFIFO: ``` "retire_tags": when True ==> do $display "firing retire_tags" (fshow retireTag) tagFIFO.enq retireTag (select tagUsageTracker retireTag) := False ``` Triggered via a `retireTag` method writing to a wire (`retireTag :: Wire UIntLog2N(numTags)`). My question is about scheduler granularity: In the `Nothing` case of `requestTag`, there¡¯s no write to `tagUsageTracker`, unlike the `Just` cases. `retire_tags`, however, always writes to `tagUsageTracker`. I expected the scheduler to conservatively block `requestTag` and `retire_tags` from firing in the same cycle due to the potential conflict on `tagUsageTracker`, even when `initialTagDistributor` is `Nothing`. However, my Bluesim output suggests they do fire together: ``` count : 7 retiring tag : 4 got tag : 2 firing retire_tags4 count : 8 retiring tag : 4 got tag : 4 ``` This comes from a tester using an ActionSeq: ``` |> do retireTagAction 4 requestTagAction ``` where `retireTagAction` calls `retireTag 4` and `requestTagAction` calls `requestTag`. The dumped schedule for retire_tags shows: ``` Rule: tagEngine_retire_tags Predicate: tagEngine_retireTag.whas && tagEngine_tagFIFO.i_notFull Blocking rules: (none) ``` but doesn¡¯t mention `requestTag` (a method, not a rule). My understanding was that the scheduler operates at the rule/method level, not case-arm level, so it wouldn¡¯t distinguish the Nothing case¡¯s lack of tagUsageTracker writes. Yet, the simulation suggests otherwise. Here are my final questions: * At what granularity does the scheduler resolve conflicts? Does it consider runtime paths (e.g., Nothing vs. Just) or just the union of all possible resource accesses? * Why can requestTag (in Nothing) and retire_tags fire in the same cycle here? Is it because they¡¯re sequenced within one ActionSeq rule, and tagFIFO (a FIFOF) allows enq/deq together?
Started by Yehowshua Immanuel @ · Most recent @
Behavior of `mkPipelineFIFOF` 3
It seems that enqueueing into an empty mkPipelineFIFOF in cycle `n` won't be reflected in its `notEmpty` signal until the beginning of cycle `n+1`? Likewise, if you dequeue a value from a PipelineFIFOF currently holding a single element, the `notEmpty` signal won't change from True to False until the beginning of the next cycle? I suppose the same sort of idea applies to .`notFull`?
Started by Yehowshua Immanuel @ · Most recent @
Best Practices for Simulation in Bluespec 6
You can find the snippets referenced below in the code here. 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.
Started by Yehowshua Immanuel @ · Most recent @
Using mkRWireUnsafe for communicating between methods 9
I'm making a free list in hardware - basically a LIFO that can be used to assign unique tags to bus transactions which are valid for the lifetime of the transaction. My free list module(mkTagEngine) has two methods, requestTag and retireTag. To call both methods simultaneously, requestTag needs to see what tag argument was passed to retireTag(at which point requestTag effectively "falls through" and returns the retired tag"). The only way I've found to communicate arguments between methods is `mkRWireUnsafe`. Why is this? What makes it unsafe? Should I be concerned about using unsafe? Under the hood, does FIFOF use unsafe wires as well? Here is the reference line of code: https://git.joyofhardware.com/ReferenceProjects/riscv-bluespec-classic/src/commit/ed8e0b8337539e4de4fab80883c381bf18da2a1d/bs/TagEngine.bs#L125
Started by Yehowshua Immanuel @ · Most recent @
crossing reset domains 4
Is there an equivalent to mkNullCrossingWire for moving between reset domains? I'm getting BSC warnings (G0043 and G0043) about combining reset domains but I believe I have the logic worked out such that it shouldn't matter. I'd like to silence those warnings--but only exactly here where I've put the effort into thinking it though and not anywhere else where I might accidentally mess up the domains. I found the "-suppress-warnings" compiler flag, but didn't find anything to be more surgical. I'm also open to approaching this differently if this just isn't the Bluespec way. I'm trying to implement an inner module in one reset domain and an outer module in a subsuming domain that has a method to assert/release that inner module's reset and wraps the inner module's interface with one that forwards the method to the inner module when enabled and returns a failed indicator if the inner module is not enabled. The appended code is representative of what I'm trying to do. (The motivator for this is the "dmcontrol.dmactive" bit from the risc-v debug spec if that helps establish context.) I've read through the various reset related posts from the last couple years and the only ideas/suggestions I uncovered were to rewrite the code to have the "enable" be explicitly represented in logic instead of leveraging reset, to slip a dual-domain fifo between the two modules, or to write some custom verilog with appropriate annotations. I'm hesitant to use that first option because that would be a lot of repetitions of "if (is_enabled) ..." instead of just feeding it into the existing reset tree and would make it easy to accidentally miss a bit of state that needs to be reset. I'm hesitant to use the second option because it feels like a sledgehammer/fly type solution given that both modules are in the same clock domain and one reset is a strict subset of the other. Also it would add unnecessary latency to accessing the inner module. And I'm hesitant to use the third option because it seems like I'd also have to write a custom bluesim primitive and end up with a forked bsc or give up on bluesim and just use verilator. (I think--I haven't actually looked at the details so I don't know if it would be that bad or if there is an easy plugin interface I could leverage. My trepidation over leveraging BDPI turned out to be totally warranted--I now have a simple BDPI based jtag proxy that talks OpenOCD's remote bit bang protocol.) -William --- cut here --- package ResetTest; import Clocks::*; interface Inner; // Indicator that we are awake and ready to do something. method Bool awake(); // Do something critical and amazing. method ActionValue#(Bit#(32)) do_something(Bit#(32) arg); endinterface interface Outer; // Turn the inner device on or off. Transition from off to on can // take time. Check for when it is done by invoking is_on(). // Turning the device off resets it. method Action set_on(Bool on); // Returns true iff the inner device is on and ready to do // something. method Bool is_on(); // Do something, but return Invalid if the inner device isn't // ready. method ActionValue#(Maybe#(Bit#(32))) do_something(Bit#(32) arg); endinterface module mkInner(Inner); Reg#(Bit#(3)) wakeup_delay <- mkReg('1); rule wakeup if (wakeup_delay != 0); wakeup_delay <= wakeup_delay - 1; endrule method Bool awake(); return wakeup_delay == 0; endmethod method ActionValue#(Bit#(32)) do_something(Bit#(32) arg); return arg; endmethod endmodule (* synthesize *) module mkOuter(Outer); Reg#(Bool) on <- mkReg(False); Clock cur_clock <- exposeCurrentClock; MakeResetIfc inner_reset <- mkResetSync(1, True, cur_clock); Inner inner <- mkInner(reset_by inner_reset.new_rst); method Action set_on(Bool v); on <= v; endmethod method Bool is_on(); return on && inner.awake(); endmethod method ActionValue#(Maybe#(Bit#(32))) do_something(Bit#(32) arg); if (on && inner.awake()) begin let result <- inner.do_something(arg); return tagged Valid result; end else return Invalid; endmethod endmodule endpackage
Started by William Howe-Lott @ · Most recent @
Bluespec evaluation-time error: unhandled case 3
I was trying to do some fancy stuff by composing an FSM using functions that return Stmt to capture sequences. Looks like I broke something along the way. Any help in understanding the error message and how to fix it is appreciated. This is with Bluespec Compiler, version 2024.07 (build b4f31dbe) Compilation message: "StmtFSM.bs", line 220, column 72: Case: [SNamed sendbytes_l102c63 [[Par_l102c63 ([Action_l103c54] [Action_l104c57] [Seq_l105c49 ([While_l106c57 [SNamed sendbits_l106c76 [[Par_l106c76 ([Action_l107c73] [SExprS _l108c77])]]]] [SExprS _l110c65])])]]] Error: "StmtFSM.bs", line 964, column 13: (S0015) Bluespec evaluation-time error: unhandled case During elaboration of `c0' at "StmtFSM.bs", line 942, column 7. During elaboration of `c1' at "StmtFSM.bs", line 943, column 7. During elaboration of `c_no_action' at "StmtFSM.bs", line 642, column 8. During elaboration of `_rfsm' at "StmtFSM.bs", line 1140, column 8. During elaboration of `fsm' at "I2C.bsv", line 134, column 21. During elaboration of `mkI2CMaster' at "I2C.bsv", line 26, column 8.
Started by vijayvithal jahagirdar @ · Most recent @
RegFile but with more write ports 8
Does anyone know of a library or approach that might fill this need? I'm looking to be able to write multiple times in a cycle. For clarity, I'm trying to do something like this: import RegFile::*; module regfile_write_ports (Empty); RegFile#(UInt#(1), Bool) rf <- mkRegFileFull(); (* fire_when_enabled *) rule wr0; rf.upd(0, True); endrule (* fire_when_enabled *) rule wr1; rf.upd(1, True); endrule or even just this: import RegFile::*; module regfile_write_ports (Empty); RegFile#(UInt#(1), Bool) rf <- mkRegFileFull(); rule wr; rf.upd(0, True); rf.upd(1, True); endrule endmodule
Started by h@... @ · Most recent @
Bluespec Jobs
I've been very much enjoying working in Bluespec in my spare time. I'm wondering if there is a way to work full time on it. Not exactly seeing any shops hiring for Bluespec devs!
Started by Yehowshua Immanuel @
Compiler Effusively Complains about `Invalid PP Token` 4
For example - for the lines of code here, I get: ``` 2 warnings generated. In file included from 34979.c:1: ./bs//Serializer.bs:13:22: warning: missing terminating ' character [-Winvalid-pp-token] START -> 1'b0 ^ ./bs//Serializer.bs:15:22: warning: missing terminating ' character [-Winvalid-pp-token] _ -> 1'b1 ``` I know I can simply disable the pre-processor warns, but why is it so verbose in the first place?
Started by Yehowshua Immanuel @ · Most recent @
Unable to use interface method argument in `when` guard 7
Un-commenting the commented-out lines in the snippet below... https://git.joyofhardware.com/ReferenceProjects/riscv-bluespec-classic/src/commit/e6b002f70e76050eb60a6176f63a9a242306b6d8/bs/TagEngine.bs#L59-L71 retireTag :: UIntLog2N(numTags) -> Action retireTag tag = do let nextStackPtrUint = case stackPtr of Nothing -> 0 Just n -> n + 1 (select inUseVec tag) := False (select freeStackVec nextStackPtrUint) := tag stackPtr := Just nextStackPtrUint -- when -- tag < (reifiedNumTags - 1), -- readReg (select inUseVec tag) causes compilation to fail with: ```bash $TOPMODULE=mkSim make b_compile b_link b_sim mkdir -p build_b_sim Compiling for Bluesim ... bsc -u -sim -simdir build_b_sim -bdir build_b_sim -info-dir build_b_sim -keep-fires -aggressive-conditions -no-warn-action-shadowing -check-assert -cpp -show-schedule +RTS -K128M -RTS -show-range-conflict -p bs/:bsv/:+ -g mkSim bs/Top.bs checking package dependencies <snipped> 5 warnings generated. compiling bs//TagEngine.bs Warning: "bs//TagEngine.bs", line 43, column 8: (P0223) Definition of `counter' is not used. Error: "bs//TagEngine.bs", line 70, column 20: (T0004) Unbound variable `tag' make: *** [Makefile:103: b_compile] Error 1 ``` Is this intentional? Are you not allowed to use interface method arguments in when guards?
Started by Yehowshua Immanuel @ · Most recent @
Trouble With FShow for Registered custom type 4
The `$display (fshow (tagVec !! 0))` found here is failing to compile... I tried creating my own `fshow` instance but haven't had much success... ``` rror: "bs//TagEngine.bs", line 57, column 33: (T0031) The contexts for this expression could not be resolved because there are no instances of the form: Prelude.FShow (Prelude.Reg (TagEngine.Tag numTags)) make: *** [Makefile:103: b_compile] Error 1 ```
Started by Yehowshua Immanuel @ · Most recent @
Current Image
Image Name
Sat 8:39am