¿ªÔÆÌåÓý

ctrl + shift + ? for shortcuts
© 2025 Groups.io

Re: Programmatically create a vector of registers in Bluespec Haskell initialized from 0..5

 

I think I eventually made progress on the previous issue... So in BH RN I have the following where the number of bits in `UInt` is parameterizable:


data Tag a
= Next (UInt a)
| Empty
deriving (Bits, Eq, FShow)

initTagNext :: Integer -> Module(Reg (Tag a))
initTagNext i = do
t :: Reg (Tag a)
t <- mkReg (Next (fromInteger i))
return t

initTagEmpty :: Integer -> Module(Reg (Tag a))
initTagEmpty i = do
t :: Reg (Tag a)
t <- mkReg Empty
return t


Re: Programmatically create a vector of registers in Bluespec Haskell initialized from 0..5

 

Thanks for that code! I'm wondering how I can make it parametrizable... So far - no luck!

import Vector::*; // Required for Vector

module mkTop #(parameter Integer bitWidth) (Empty); // No default value

// Parameterized module with configurable bit width 'n'
module mkRegJ #(Integer i, parameter Integer n) (Reg #(Bit #(n)));
let r <- mkReg (fromInteger (i));
return r;
endmodule

// Helper function to instantiate mkRegJ with a fixed bit width
function ActionValue #(Reg #(Bit #(bitWidth))) mkRegJFixed(Integer i);
return mkRegJ(i, bitWidth);
endfunction

// Use mapM with the helper function
Vector #(6, Reg #(Bit #(bitWidth))) v_rgs <- mapM (mkRegJFixed, genVector);

rule rl_once;
for (Integer j = 0; j < 6; j = j + 1)
$display ("v_rgs [%2d] = %2d", j, v_rgs [j]);
$finish (0);
endrule

endmodule
$bsc -u -verilog mkTop.bsv
checking package dependencies
compiling mkTop.bsv
Error: "mkTop.bsv", line 17, column 28: (T0008)
? Unbound type variable `bitWidth'
?


Re: Programmatically create a vector of registers in Bluespec Haskell initialized from 0..5

 
Edited

Here's how I'd write it in BSV; I'd guess it's not too different in BH (would use the same mapM and genVector).
?
Example run:
?

./exe_HW_bsim

v_rgs [ 0] =? 0

v_rgs [ 1] =? 1

v_rgs [ 2] =? 2

v_rgs [ 3] =? 3

v_rgs [ 4] =? 4

v_rgs [ 5] =? 5

?
Nikhil
?


Programmatically create a vector of registers in Bluespec Haskell initialized from 0..5

 

I'm trying to figure out how to programmatically create a vector of registers in Bluespec Haskell initialized from 0..5. I think I should use mapM with mkReg next - but I'm not quite sure... Any help would be appreciated...
?
?
```bs
package TagEngine() where
import Vector
import Util
#define UIntLog2N(n) (UInt (TLog n))
data Tag a
? ? = Next (Maybe (UInt a))
interface (TagEngine :: # -> *) numTags =
? ? requestTag :: ActionValue UIntLog2N(numTags)
? ? retireTag ?:: UIntLog2N(numTags) -> Action
mkTagEngine :: Module (TagEngine numTags)
mkTagEngine =
? ? do
? ? ? ? let v :: Vector numTags Reg(UIntLog2N(numTags)) = genVector
? ? ? ? counter <- mkReg(0 :: UIntLog2N(numTags))
? ? ? ? return $
? ? ? ? ? interface TagEngine
? ? ? ? ? ? requestTag :: ActionValue UIntLog2N(numTags)
? ? ? ? ? ? requestTag = do
? ? ? ? ? ? ? ? counter := counter + 1
? ? ? ? ? ? ? ? return counter
? ? ? ? ? ? retireTag :: UIntLog2N(numTags) -> Action
? ? ? ? ? ? retireTag tag = do
? ? ? ? ? ? ? ? counter := 0
? ? where
? ? ? ? a = "Hello"
a :: Integer
a = 3
```


Re: Using the Completion Buffer in Bluespec Haskell

 

NVM - I think I figured it out


Re: Testbenches

 

I also like the idea. Always found such lists really useful in other languages/frameworks.
?
Johannes


Re: Using the Completion Buffer in Bluespec Haskell

 

Would appreciate any pointers


Using the Completion Buffer in Bluespec Haskell

 

I found some documentation on the completion buffer here:
?
But I haven't quite figured out a robust way to use it in Bluespec Haskell


Re: Testbenches

 

I like that idea a lot. There are a few popular AXI/AHB repos that I think people would like to know about when they first start using Bluespec.

Michael

On Fri, Mar 14, 2025 at 5:11?PM Julie Schwartz via <quark=[email protected]> wrote:
That's awesome, thank you.? I would love for the BSC repo to have a list of links to all the useful code that's out there -- perhaps a new section of the README under "Community" can be a list of libraries, projects, tools, etc.? We could include the TU Darmstadt repos?

Julie

On Tue, Mar 11, 2025 at 7:40?AM johannes-wirth via <johannes-wirth=[email protected]> wrote:
I have written some helper modules for testbenches, depending on what you're doing they may also be helpful for you.
?
1) A "scoreboard" where you can put reference data as well as "dut" data. The module will then compare and can provide some stats at the end.
2) Randomizer modules for generating (input) data, similar to the Randomizable libary which Julie mentioned above. They have two advantages: You can use it with a "user-provided" seed, which allows to replicate specific test runs which failed earlier. And they work with enums and tagged unions (the Randomizable library can produce invalid values there, e.g. for enum with 3 values with bit represenation 00,01,10 it also generates 11; my implementation prevents this, however the distribution is not uniform in those cases).
?
You can find them here in our small library (or to be more precise my fork of it, as it is not yet merged):
?
I also have some documentation here:
?
Johannes


Re: Testbenches

 

That's awesome, thank you.? I would love for the BSC repo to have a list of links to all the useful code that's out there -- perhaps a new section of the README under "Community" can be a list of libraries, projects, tools, etc.? We could include the TU Darmstadt repos?

Julie

On Tue, Mar 11, 2025 at 7:40?AM johannes-wirth via <johannes-wirth=[email protected]> wrote:
I have written some helper modules for testbenches, depending on what you're doing they may also be helpful for you.
?
1) A "scoreboard" where you can put reference data as well as "dut" data. The module will then compare and can provide some stats at the end.
2) Randomizer modules for generating (input) data, similar to the Randomizable libary which Julie mentioned above. They have two advantages: You can use it with a "user-provided" seed, which allows to replicate specific test runs which failed earlier. And they work with enums and tagged unions (the Randomizable library can produce invalid values there, e.g. for enum with 3 values with bit represenation 00,01,10 it also generates 11; my implementation prevents this, however the distribution is not uniform in those cases).
?
You can find them here in our small library (or to be more precise my fork of it, as it is not yet merged):
?
I also have some documentation here:
?
Johannes


Re: crossing reset domains

 

My trepidation over leveraging BDPI turned out to be totally warranted
?
Unwarranted!? My trepidation was totally unwarranted!
?
Sigh.? Proofreading fail.
?
-William
?


crossing reset domains

 

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


Re: Testbenches

 

I have written some helper modules for testbenches, depending on what you're doing they may also be helpful for you.
?
1) A "scoreboard" where you can put reference data as well as "dut" data. The module will then compare and can provide some stats at the end.
2) Randomizer modules for generating (input) data, similar to the Randomizable libary which Julie mentioned above. They have two advantages: You can use it with a "user-provided" seed, which allows to replicate specific test runs which failed earlier. And they work with enums and tagged unions (the Randomizable library can produce invalid values there, e.g. for enum with 3 values with bit represenation 00,01,10 it also generates 11; my implementation prevents this, however the distribution is not uniform in those cases).
?
You can find them here in our small library (or to be more precise my fork of it, as it is not yet merged):
?
I also have some documentation here:
?
Johannes


Re: StmtFSM examples in BH syntax

 

Also, do you by chance use the ECP5 FPGA with BH? I linked to some examples in my previous reply although they were basic. I'm going to see how BH fares when it comes to IO PHYs however. I have some simple PCIe over ECP5 SERDES experiments queued up.


Re: StmtFSM examples in BH syntax

 

Glad to see BH syntax adoption in industry! I think BSV syntax is truly awful..
?
Trying to document BH here:
?
Also, modeling RiscV with a Formal model before implementing it in ULX3S with BH here:
?
I had wanted to add language server support to BSC for BH. I started by looking at CPackage, but never really committed to seeing it through. Perhaps if there are other BH users, I may give it another go.


Re: StmtFSM examples in BH syntax

 

Ha, thanks Charlie! He and I actually work for the same company (causing me to adopt the BH syntax), and I've certainly seen this library in our repo. I really like what it does, but have some existing test benches which need a slightly less strict scheduler (wait until this thing eventually becomes true). Having said that, I may be able to add that using an alternative constructor which doesn't count cycles but executes steps instead.

And I see there are some other goodies which came along with this donation (MList, some of our rule syntax) which is useful.


Re: StmtFSM examples in BH syntax

 

Hi Arjen,

I spoke with folks that had been using StmtFSM in BH.? They had written a wrapper library that provided abstracted functions for seq, par, for-loops, delays etc.? They no longer have this library, but said it was straightforward to make, by reading the StmtFSM library.? The reason they no longer have this, is because they switched away from StmtFSM to their own simpler SequenceRules library.? They were only using statically-timed constructs (no conditionals, breaks, etc) and StmtFSM was not scaling well for them.? So they wrote a library that just constructs up a list of actions, and then instantiates a single counter register and indexes through the list.? They've graciously agreed to contribute the library (although they note that it's only 150 lines of code) and it's currently in a PR to the "bsc-contrib" library, if you're interested:


Julie


Re: Testbenches

 

There are various ways to write testbenches, and it probably depends on the kind of design or interface.? The BSC testsuite might be a source of examples -- sorry, I'm not sure which directories are good examples, offhand.? I have certainly written many testbenches like the Verilog you describe: a rule that provides input and then a rule that receives outputs and checks them, perhaps with a FIFO between them if the input rule needs to pass the expected output values etc.

I don't know that there's a good ecosystem of testbench features, yet, if that's what you're asking.? There is a Randomizable library, which has some simple constrained randomization -- it was written before the Generics feature was available (for querying the fields of a type) so probably a more sophisticated randomizer could be written now.? There is also "$random" and the LFSR library.

You can also import Verilog submodules to produce values (or to check values, or to implement assertions).? Or import C functions.? And in the worst case, you can write the entire testbench in Verilog or C/C++ and connect it to the BH/BSV design.

J


On Thu, Mar 6, 2025 at 10:11?AM Emily Schmidt via <aiju=[email protected]> wrote:
Is there any documentation / examples on how to write testbenches in BSV? I would like to have tests that run (maybe constrained) random inputs through my modules and then compares it to a reference model. In Verilog I would have a bunch of tasks that run in an initial block that fill up arrays with inputs and expected outputs, and then always blocks that feed the inputs into the module and retrieve outputs and compare them and then emit @PASS or @FAIL at the end. I could probably hack something together using StmtFSM but it seems like it would maybe be a little clumsy, and maybe there's a better way I'm not thinking of.
?
- Emily


Testbenches

 

Is there any documentation / examples on how to write testbenches in BSV? I would like to have tests that run (maybe constrained) random inputs through my modules and then compares it to a reference model. In Verilog I would have a bunch of tasks that run in an initial block that fill up arrays with inputs and expected outputs, and then always blocks that feed the inputs into the module and retrieve outputs and compare them and then emit @PASS or @FAIL at the end. I could probably hack something together using StmtFSM but it seems like it would maybe be a little clumsy, and maybe there's a better way I'm not thinking of.
?
- Emily


Re: StmtFSM examples in BH syntax

 

Ah thank you! I realize I missed the do to chain statements together. I'll experiment with this a bit and see what some helper functions can do.