package GlibcRandom; import StmtFSM::*; import Vector::*; import GetPut::*; import ClientServer::*; // (*mutually_exclusive="lc.lc,initialize.actionof_l15c40"*) (*mutually_exclusive="lc.lc,initialize.actionof_l15c40_1"*) module mkRandom(Server#(int,int)); Reg#(Randtable) randtable<-mkRegU; LinearCongruential lc<-mkLinearCongruential(randtable); Get#(int) inner <-mkRandomR(randtable); Reg#(Bool)ready<-mkReg(False); FSM initialize<-mkFSMWithPred(seq lc.finished; repeat(fromInteger(numToDiscard))(action int result<-inner.get; endaction); ready<=True; endseq,!ready ); //NOTE: put should only be called once ever. It does not work to re-seed a RNG. Maybe a future task. interface Put request; method Action put(int seed) if (!ready); lc.seed(seed); initialize.start; endmethod endinterface interface Get response; method ActionValue#(int) get if(ready) =inner.get; endinterface endmodule typedef 31 DEG_3; Integer sEP_3=3; Bit#(5) finalIndex=fromInteger(valueof(DEG_3)-1); typedef Bit#(5) Index; function Tuple2#(int,Randtable) fibonacci(Randtable v); int val=v[0]+v[sEP_3]; v[sEP_3]=val; return tuple2(val,(rotate(v))); endfunction module mkRandomR#(Reg#(Randtable) randtable)(Get#(int)); method ActionValue#(int) get; Tuple2#(int,Randtable) rv=fibonacci(randtable); randtable<=tpl_2(rv); Bit#(32) bval=pack(tpl_1(rv)); Bit#(31) bvc=bval[31:1]; Bit#(32) zbv={0,bvc}; int result=unpack(zbv); return result; endmethod endmodule typedef Vector#(DEG_3,int) Randtable; Integer numToDiscard=310; //this takes 300000 elaboration steps. function Randtable discardInitial(Randtable r); for(Integer i=0;i