Giter Site home page Giter Site logo

doc example for mkUniqueWrapper2 about bsc HOT 7 OPEN

postoroniy avatar postoroniy commented on August 25, 2024
doc example for mkUniqueWrapper2

from bsc.

Comments (7)

quark17 avatar quark17 commented on August 25, 2024

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.

postoroniy avatar postoroniy commented on August 25, 2024

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.

quark17 avatar quark17 commented on August 25, 2024

Sorry, I think I understand now.

The example from the doc has a few issues that need fixing:

  1. The type ComplexP should be Complex
    The example is from 2005, when the the Complex library was still being developed, and was not yet part of the BSC release. At that time, the type was called ComplexP. To work now, the name just needs to be changed to Complex.
  2. Several libraries need importing
    It's possible that examples do not include the import 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.
  3. The interface of the module should be Empty
    There is no need to define ArithOpGP2, 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.

quark17 avatar quark17 commented on August 25, 2024

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.

postoroniy avatar postoroniy commented on August 25, 2024

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.

postoroniy avatar postoroniy commented on August 25, 2024

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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.