Comments (7)
Thank you again for reporting this. I will make the change in the Library Guide.
Also, I discussed this with @rsnikhil and he agrees that the Library Guide examples should be fully working examples, that can be compiled and run. He suggests that these examples should exist as files in this repo, and the Library Guide should just point to the example files. He mentions that there is already a collection of examples which we use as the starting point: the examples accompanying the book BSV By Example. Nikhil suggests that every section of the Library Guide should point to an example there and, if no suitable example exists yet, an example file should be added. The BSV By Example book is available for download from a different repo at the moment (here), so Nikhil will take on the task of putting the document source and examples into this repo. Then we can look at updating the Library Guide to point to examples there.
from bsc.
The type ArithOpGP2
is defined in the example:
interface ArithOpGP2#(type t);
...
endinterface
And the type CFP
is defined above that:
typedef Int#(18) CFP;
They aren't from a library. They are user-defined types that only exist within this example.
These types add some realism to the example, by showing how the UniqueWrappers
library can be used with your own types. However, they are not necessary for illustrating how to use UniqueWrappers
, and I can see how they make the example less clear, by distracting from the part that's important.
Does that answer your question?
The UniqueWrappers
library is not commonly used, so you probably don't need to worry about it. But here is a simpler example of what it does. (Well, it started simple, and then I added extra features, but hopefully it is still clear).
import UniqueWrappers::*;
// Change this to False to see the result of not using UniqueWrappers
Bool share = True;
(* synthesize *)
module mkTestUniqueWrappers ();
// -----
// Declare and instantiate an interface that takes 2 arguments, multiplies them
// and returns the result. It is a Wrapper2 because there are 2 arguments.
function Bit#(8) multFn (Bit#(8) x, Bit#(8) y);
return (x * y);
endfunction
Wrapper2#(Bit#(8),Bit#(8), Bit#(8)) shared_mult <- mkUniqueWrapper2(multFn);
// Below we define two rules that will share the function.
// Because they share it, they cannot both execute at the same time,
// so we introduce a condition:
Reg#(Bool) rg_cond <- mkRegU;
// -----
// The first user of the function
Reg#(Bit#(8)) rgA1 <- mkRegU;
Reg#(Bit#(8)) rgA2 <- mkRegU;
Reg#(Bit#(8)) rgA3 <- mkRegU;
rule rlA (rg_cond);
if (! share) begin
// If we wrote this, the logic would not be shared
rgA3 <= rgA1 * rgA2;
end
else begin
// By using an instantiated wrapper module, we force the logic to be shared
// in the generated Verilog from BSC:
// Note that "shared_mult" is a "Wrapper2" interface, so we call
// the method "func". It is an ActionValue method, so we need to get
// the value first, before assigning it to the register.
let mr <- shared_mult.func (rgA1, rgA2);
rgA3 <= mr;
end
endrule
// -----
// The second user of the function
Reg#(Bit#(8)) rgB1 <- mkRegU;
Reg#(Bit#(8)) rgB2 <- mkRegU;
Reg#(Bit#(8)) rgB3 <- mkRegU;
rule rlB (! rg_cond);
if (! share) begin
rgB3 <= rgB1 * rgB2;
end
else begin
let mr <- shared_mult.func (rgB1, rgB2);
rgB3 <= mr;
end
endrule
endmodule
If you compile with with -verilog
and search for *
in the generated Verilog file, you should see only one occurrence:
assign IF_shared_mult_arg_whas_THEN_shared_mult_arg_w_ETC___d11 =
shared_mult_arg$wget[15:8] * shared_mult_arg$wget[7:0] ;
However, if you change the variable shared
to False and recompile, you should see two copies of *
in the Verilog:
assign rgA1_MUL_rgA2___d4 = rgA1 * rgA2 ;
assign rgB1_MUL_rgB2___d9 = rgB1 * rgB2 ;
from bsc.
the type is not defined in example, the code I provided is from myself and not from the doc!
that what the point. I know what is wrapper I pointed to the thing - example from doc is not working
from bsc.
Sorry, I think I understand now.
The example from the doc has a few issues that need fixing:
- The type
ComplexP
should beComplex
The example is from 2005, when the theComplex
library was still being developed, and was not yet part of the BSC release. At that time, the type was calledComplexP
. To work now, the name just needs to be changed toComplex
. - Several libraries need importing
It's possible that examples do not include theimport
statements, for brevity. But it is probably a good idea to include it, so that the example is complete and so that readers know whether they have included all the necessary libraries. - The interface of the module should be
Empty
There is no need to defineArithOpGP2
, because it is unused. Just remove it:
module mkComplexMult1Fifo() ;
or this, if it's more consistent with the style used by the guide:
module mkComplexMult1Fifo (Empty) ;
Yes, these should be fixed in the document. Thank you for reporting this. Your version is good, except that the definition of ArithOpGP2
should be removed.
from bsc.
I guess I would also changed the name to something other than mkComplexMult1Fifo
, since it is no longer a FIFO module.
If we did keep the interface, your definition for ArithOpGP2
is okay, but I would remove the Maybe
and the check for notEmpty
.
The example has two input FIFOs, but they could be one FIFO of Tuple2
.
And I think the GP
in the name probably indicated GetPut
, so possibly it looked something like this:
interface ArithOpGP2#(type t);
interface Put#(Tuple2#(t,t)) put;
interface Get#(t) get;
endinterface
But I can't find any example of ArithOpGP2
existing, only of ArithOp2
, which was this in an early 2005 example that led to the creation of UniqueWrappers
:
interface ArithOp#(type a_type) ;
method Action start( a_type in1, a_type in2 ) ;
method a_type result ;
endinterface
And in that example, no input or output FIFOs were being used.
I don't think it's important to follow the original example(s). We can just consider what it's helpful in an example now. Leaving out the interface and making it a standalone example might be best, and that way readers can compile it and explore the output.
from bsc.
for users coming from verilog world it's useful to see inputs and outputs in produced verilog code. for establishing the connection between func world and real one. when I am not able to test out examples from "reference blah guide" I'd think that language sucks or not maintained well, and in any case not user friendly at all.
what I did in provided example - it generates actual working hardware and not empirical unicorns.
however, if you think empty interface is better for understanding, ok...fine :)
from bsc.
btw, the latest example I did is having 2 fifos only
import FIFO :: * ;
import FIFOF :: * ;
import StmtFSM :: * ;
import UniqueWrappers :: * ;
import Complex :: *;
typedef Int#(18) CFP;
typedef struct {
Complex#(CFP) a;
Complex#(CFP) b;
} CFP2 deriving (Eq, Bits);
interface ArithOpGP2#(type t);
method Action enqueue(Complex#(t) a, Complex#(t) b);
method ActionValue#(Maybe#(Complex#(t))) getResult();
endinterface
(* synthesize *)
module mkComplexMult1Fifo( ArithOpGP2#(CFP) ) ;
FIFO#(CFP2) infifo <- mkFIFO;
let arg = infifo.first ;
FIFOF#(Complex#(CFP)) outfifo <- mkFIFOF;
Reg#(CFP) rr <- mkReg(0);
Reg#(CFP) ii <- mkReg(0);
Reg#(CFP) ri <- mkReg(0);
Reg#(CFP) ir <- mkReg(0);
// Declare and instantiate an interface that takes 2 arguments, multiplies them
// and returns the result. It is a Wrapper2 because there are 2 arguments.
Wrapper2#(CFP,CFP, CFP) smult <- mkUniqueWrapper2( \* ) ;
// Define a sequence of actions
// Since smult is a UnqiueWrapper the method called is smult.func
Stmt multSeq =
seq
action
let mr <- smult.func( arg.a.rel, arg.b.rel ) ;
rr <= mr ;
endaction
action
let mr <- smult.func( arg.a.img, arg.b.img ) ;
ii <= mr ;
endaction
action
// Do the first add in this step
let mr <- smult.func( arg.a.img, arg.b.rel ) ;
ir <= mr ;
rr <= rr - ii ;
endaction
action
let mr <- smult.func( arg.a.rel, arg.b.img );
ri <= mr ;
// We are done with the inputs so deq the in fifos
infifo.deq ;
endaction
action
let ii2 = ri + ir ;
let res = Complex{ rel: rr , img: ii2 } ;
outfifo.enq( res ) ;
endaction
endseq;
// Now convert the sequence into a FSM ;
// Bluespec can assign the state variables, and pick up implict
// conditions of the actions
FSM multfsm <- mkFSM(multSeq);
rule startFSM;
multfsm.start;
endrule
method Action enqueue(Complex#(CFP) a, Complex#(CFP) b);
CFP2 ab;
ab.a=a;
ab.b=b;
infifo.enq(ab);
endmethod
method ActionValue#(Maybe#(Complex#(CFP))) getResult();
if (outfifo.notEmpty) begin
let res = outfifo.first;
outfifo.deq;
return tagged Valid res;
end else
return tagged Invalid;
endmethod
endmodule
from bsc.
Related Issues (20)
- Verilog import fails in macro substitution HOT 2
- Unexpected syntax error HOT 1
- expandPorts.tcl has hardcoded paths which do not exist. HOT 1
- Unexpected behavior in Stmt sequence when using par HOT 2
- Bluesim divide-by-zero behavior is inconsistent on arm64 HOT 2
- Type synonyms with phantom parameters can lead to strange behaviors (E.g., compiler hang) HOT 4
- -remove-unused-modules flag doesn't work with mkProbe module provided in std library HOT 2
- Failures with compilation on raspberry-pi 5 HOT 4
- GCC 14 emits extra warnings HOT 1
- Github's macos-11 runner is going away HOT 1
- [Bluesim] Simulation executable fails with `undefined symbol: _Z21vcd_write_scope_startP9tSimStatePKc` HOT 9
- `sqrtFP` is incorrect HOT 6
- compile to verilog, convert function to function, but not to modules. HOT 1
- Preserving structure at synthesis boundaries HOT 2
- Better control of wrapper generation HOT 6
- Incremental compilation model and UX improvements
- how does bsc disambiguate between V2K keywords and library functions? HOT 2
- Debugging with Bluetcl - displaying values
- implicit pack/unpack + custom Bits instance can result in extraneous logic. HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from bsc.