Keyboard Shortcuts
Likes
- B-Lang-Discuss
- Messages
Search
Re: Using mkRWireUnsafe for communicating between methods
I don't think I'm getting around using `mkUnsafeRWire`...
?
I tried refactoring where I have the "compute tag" rule compute the tag result and place it in a bypass wire. This means the requestTag method no longer has to be predicated on reading `methodRetireTagCalledValid`. Nevertheless, the compiler refuses to allow me to schedule `requestTag` and `retireTag` together in the same cycle with this approach. I think this is because fundamentally, I'm trying to simultaneously call two methods in the same cycle where there is information flowing between these two methods.
?
So my question now is:
Is it possible in Bluespec to call methodA and methodB simultaneously if the behavior of methodA depends on the argument passed to methodB without using `unsafe`?
?
In a highly concurrent asynchronous bus, it is very likely that the request interface of the bus often requests tags for transactions it wishes to start whilst the response interface simultaneously retires tags for transactions that have just completed. So not being able to simultaneously request and retire a tag will incur a huge performance penalty.
?
In Rust, unsafe means the borrow checker can't prove memory safety. What does unsafe mean in bluespec? What sort of guarantees am I foregoing by using `unsafe`? |
|||||||||||||
Compiler Effusively Complains about `Invalid PP Token`
For example - for the lines of code , 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? |
|||||||||||||
Re: Using mkRWireUnsafe for communicating between methods
Looking at But back to your problem: what to do in this case where you have two methods that interact somehow and you don't want to decouple everything through FIFOs or whatever? One thing you can do is remove most of the side effects from the methods, and replace them with writing one This does have some implications on your interface in the sense that you might need to separate your request and response methods (because they'd be separated by the rule in the schedule order). And of course you have to be careful to not use your module in ways that result in combinational loops, or decouple things by giving up on the notion of reusing a tag the moment it's freed (which you might or might not want to anyway depending on how you permit things to be combinationally linked). |
|||||||||||||
Using mkRWireUnsafe for communicating between methods
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:
|
|||||||||||||
Re: Unable to use interface method argument in `when` guard
Here are three other possibilities: -- canRetireTag sets the tag and returns if ready, used in the same rule rules ? "do_retire": when True ==> ? ? do ?? ? ? b :: Bool ?? ? ? b <- tagEngine.canRetireTag tag ?? ? ? if (b) then ? ? ? ? tagEngine.retireTag ? ? ? ? ... ?? ? ? else ? ? ? ? noAction -- canRetireTag sets the tag and returns if ready, used in separate rules (if needed) ? "check_retire": when True ==> ? ? do ? ? ? b :: Bool ? ? ? b <- tagEngine.canRetireTag tag ? ? ? w_canRetire := b ? "do_retire": when (w_canRetire) ==> ? ? do ? ? ? tagEngine.retireTag ? ? ? ... -- canRetireTag is pure value rules ??"do_retire": when (tagEngine.canRetireTag tag) ==> ? ??do ? ? ??tagEngine.retireTag tag ? ? ??... J On Mon, Mar 24, 2025 at 11:49?AM Yehowshua Immanuel via <programmed4jesus=[email protected]> wrote:
|
|||||||||||||
Re: Unable to use interface method argument in `when` guard
Kudos to bluespec for consistent semantics... I tried to use RWire within the module such that you had to call the following in the same rule to retire a tag:
?
```
tagEngine.setTagToRetire 12 tagEngine.retireTag; ``` ?
But the compiler complained that can fire for the rule depended on will fire in the rule - so yeah didn't work. I can just make sure the tag requestor never attempts to request an invalid tag since I have control over the requestor...
?
Full coded attempt here: |
|||||||||||||
Re: Unable to use interface method argument in `when` guard
Another option is to have two separate methods: one that takes the argument and returns if it's ok, and a method that can then be called to do the action. J On Mon, Mar 24, 2025 at 9:35?AM Yehowshua Immanuel via <programmed4jesus=[email protected]> wrote:
|
|||||||||||||
Re: crossing reset domains
I don't believe there is a way to surgically suppress the warning.? If you have thoughts on how you would want to specify it, that would be a reasonable enhancement request.? I can imagine allowing an attribute on rules or modules, that adds to the suppression list for those scope of that rule or module.? But that may still not be surgical enough, because you probably want to specify what resets or what methods are causing the warning, so that you are informed if some other reset shows up. I don't recall a reset laundering module, although you might try using the mkNullCrossingWire or mkNullCrossingReg modules and giving it the same source and destination clocks, and that might be work to scrub the attached reset -- and then just be careful to only use the output where it's safe.? Reset handling didn't have as thorough a think-through as clocks, so there may be things missing -- if you have ideas, feel free to suggest them. I haven't thought about this kind of design to know if there's a better way to write it, but I can ask around. One thought is that you could store the result of "inner.awake" in a register without a reset (mkRegU).? That (a rule that writes the submodule output to an unreset register) appears to silence all the warnings in your example.? I would guess that using mkNullCrossingWire (or the like) would be doing the same thing (though possibly with less state or delay, if that's a concern). It is currently not possible for users to provide their own Bluesim implementations for imported modules.? That would be a good enhancement to BSC, but would require some thinking.? On the other hand, if you have an idea for a generally useful module for crossing reset domains, we could add it to BSC. J On Fri, Mar 14, 2025 at 11:10?AM William Howe-Lott via <william=[email protected]> wrote:
|
|||||||||||||
Re: Unable to use interface method argument in `when` guard
It is intentional.? The logical order of events for a method is that the RDY is available first, then the arguments are provided (and an EN signal, if it's an action), and then the return value is output (if it has one).? So a method's RDY can't depend on its arguments.? Though BSC could certainly be improved to give a more direct error message, than just the generic one about the variable not being in scope. J On Mon, Mar 24, 2025 at 1:21?AM Yehowshua Immanuel via <programmed4jesus=[email protected]> wrote:
|
|||||||||||||
Unable to use interface method argument in `when` guard
Un-commenting the commented-out lines in the snippet below...
?
?
?
?
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?
|
|||||||||||||
Re: Trouble With FShow for Registered custom type
Interestingly, the BSV parser can insert implicit "_read" method calls in more places than BH.? For example, "tagVec[0]" can be used for the register value.? I don't recall offhand why this works, but it might be because the BSV parser doesn't desugar this into a specific indexing function but uses the typeclass "PrimSelectable" to defer the choice until more type information is available. J |
|||||||||||||
Re: Programmatically create a vector of registers in Bluespec Haskell initialized from 0..5
On Thu, Mar 20, 2025 at 5:03?AM Yehowshua Immanuel via <programmed4jesus=[email protected]> wrote:
The BSV parser desugars into BH code, so if you're familiar with BH or Haskell, it may be helpful to mentally think of the BSV code in those terms.? There are utility programs in "bsc/src/comp/" called "bsv2bsc" and "bsc2bsv" which parse a BSV file and print it as BH and vice versa -- here, "bsc" means BH, and we may want to change the names to "bsv2bh" to be more clear.? Anyway, these may be helpful.? Note, though, that the printing of BSV is not great, so the code from "bh2bsv" may not be the best example to learn from -- for example, I think it uses the 2-line SV instantiation syntax, even though most people probably use the one-line left-arrow style.? It was never polished into a real product, it was more as a tool to produce a first draft conversion that could then be finished by hand, so the output may not be valid BSV. ?(But it'd be good to know where the bugs are and try to fix them.) Anyway, all of that is to say that the BSV declaration you've written is equivalent to this in:
OK, technically, the module type is parameterized, so it looks like this, but that's unnecessary detail for this discussion:
What's important is that everything in "#" is a value argument (not a type argument) to the module function and the last thing in parens is the return interface type. The keyword "parameter" has no meaning besides being a pragma for Verilog synthesis: if you separately synthesize a module with arguments, they become Verilog ports; the "parameter" keyword tells BSC to implement them as Verilog parameters, and to check that any instantiation provides a constant value (not a dynamic value coming from a register, say).? The keyword has no functional meaning and if you are not separately synthesizing that module, it is not used at all. In particular, "parameter" is not defining a type argument.? BSV and BH do not have support for passing explicit type arguments.? The scope of names for types and the scope of names for values are separate; when you declared an argument "n", that is created a value variable called "n" which is different from the type variable "n" created implicitly by the type "Bit#(n)".? It is unfortunate that the BSV parser did not detect this apparent name clash and warn you -- that would be worth logging as an enhancement request. As you discovered, the type parameter of the register size is implicitly passed as an argument by the context where "mkRegJ" is called.? If the context is expecting "Reg#(Bit#(4))" then BSC discovers that "n" is 4.? If the context is ambiguous, you may need to add some explicit types, to specify exactly what type/size the context is expecting. The context can only specify the types of arguments and return values.? If you want to parameterize the size of something internal to the module, then you have two choices: Make that parameter explicit on the return interface type -- for example, instead of FIFO#(t) you could have MyFIFO#(depth,t) which encodes the depth as a type parameter, and allows for static size checking.? It doesn't always make sense to expose the internal sizes this way, and it can be limiting in some cases.? In that case, you might like to pass an explicit size argument to the function/module.? Unfortunately, BSV/BH don't support this -- although it might be a nice enhancement to have.? A workaround is to add a dummy value argument, whose value is irrelevant and is only used to provide a place for the context to specify a size/type.? For example:
Or in BSV:
Anyway, hope that helps clear up the "parameter" keyword and the "#" list.? The use of "#" may be misleading, given its meaning in SystemVerilog. Since BSV is desugared to BH, BSC is limited in what it can support from the SV syntax.? Note that any "#" list can be equally expressed entirely in the plain parens.? For example, the above module is equivalently written like this:
SV allows multiple interfaces to be specified in the parens, and some can be input interfaces and some output interfaces.? BSC insists that only the last one is an output interface and the rest are input interfaces -- basically, it's the order of types in the BH signature using arrows.? In this syntax, BSV requires a name for the final interface, though it's unused.? If avoiding the "#" helps avoid confusion, you can try that.? All of this is a bit unfortunate in BSV's attempt to shoe-horn BH into SV's syntax. J |
|||||||||||||
New (unofficial) social media gathering places
Hi all!
?
Hopefully this is the right place to post this, and I hope you don't mind a *tiny* bit of self advertising:
?
I decided to take the initiative to create a Discord server and a SubReddit for BSC.
?
The links are here:
?
?
One thing I would be interested in setting up is an IRC relay between the existing server and my new Discord server, so hopefully we can expand the community and have everyone interested in the community all be able to talk to each other!
?
Thanks! Aistis Raulinaitis |
|||||||||||||
Re: Trouble With FShow for Registered custom type
The bsc library has a function ?'readVReg :: Vector n (Reg a) -> Vector n a'
which performs _read on each register in a vector of registers and returns a vector of the values.
?
There is also 'writeVReg' to write a Vector of regististers, given a vector of values.
? |
|||||||||||||
Re: Trouble With FShow for Registered custom type
So the error message is telling you what the problem is: your vector has What you need is something of type
and indeed
typechecks. And if you look at how
works equivalently well. The bsc compiler does some magic where it adds ¡ª M |
|||||||||||||
Trouble With FShow for Registered custom type
The `$display (fshow (tagVec !! 0))` found 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 ``` |
|||||||||||||
Re: Programmatically create a vector of registers in Bluespec Haskell initialized from 0..5
I've updated my example so it is parameterized.
Note, it's parameterized both on the vector length and on the bit-width of each register.
The example shows two instances of vector-of-registers, with different vector lengths and registers widths.
? |