package CompletionBuffer; import RegFile::*; import GetPut::*; import Counter::*; import List::*; // The CompletionBuffer interface: interface CompletionBuffer #(type n, type a); method Get#(CBToken#(n)) reserve(); method Put#(Tuple2#(CBToken#(n), a)) complete(); method Get#(a) drain(); endinterface: CompletionBuffer typedef Bit#(TLog#(n)) CBToken #(type n); function Bool isPowerOf2(Integer n); return (n == exp(2, log2(n))); endfunction: isPowerOf2 module mkCompletionBuffer(CompletionBuffer#(n, a)) provisos (Bits#(a, sa), Log#(n, ln), Log#(n, TLog#(n)), Add#(1, ln, ln1)); let hi = fromInteger(valueOf(n)); // A function to increment the pointer, with wraparound: function Action incr(Reg#(Bit#(ln)) r); return (isPowerOf2(valueOf(n)) ? action r <= r + 1; endaction : action r <= (r == hi-1 ? 0 : r + 1); endaction); endfunction: incr // The data vector: RegFile#(Bit#(ln), a) buff(); mkRegFileWCF#(0, hi-1) the_buff(buff); // The flags vector: // The RWires for both its set operations: List#(RWire#(void)) sets = replicate(hi, ?); List#(RWire#(void)) clears = replicate(hi, ?); // the vector itself: List#(Reg#(Bool)) flags = replicate(hi, ?); // Instantiate it all: for (Integer j = 0; j 0); actionvalue incr(o); n.down; return((buff.sub)(o)); endactionvalue endmethod: get endinterface: drain endmodule: mkCompletionBuffer endpackage: CompletionBuffer