Skip to content

Latest commit

 

History

History
240 lines (181 loc) · 5.78 KB

FIFOG.md

File metadata and controls

240 lines (181 loc) · 5.78 KB

FIFOG

This package contains constructors for a group of FIFOs with a FIFOG interface. FIFOG is like FIFOF, but instead of adding information about the fullness of the FIFO, it adds information about the guards of the FIFO.

In a correct FIFOF implementation, notFull and notEmpty must be scheduled before both enq and deq for correct one-rule-at-a-time semantics. In this case, the following two rules conflict and are unable to be scheduled in the same cycle.

rule enqIntoFIFOF;
    if (fifo.notFull) fifo.enq(x);
endrule

rule deqFromFIFOF;
    if (fifo.notEmpty) fifo.deq();
endrule

Semantically, the interface method canEnq does not have to come before deq, and canDeq do not have to come before enq, so by using FIFOG you can write the two rules below which will not conflict.

rule enqIntoFIFOG;
    if (fifo.canEnq) fifo.enq(x);
endrule

rule deqFromFIFOG;
    if (fifo.canDeq) fifo.deq();
endrule

Like FIFOF, but instead of adding information about the full-ness of the FIFO, it adds information about the guard of the FIFO.

interface FIFOG#(type t);
    method Action enq(t x);
    method Action deq;
    method t first;
    method Action clear;
    method Bool notFull;
    method Bool notEmpty;
    method Bool canEnq;
    method Bool canDeq;
endinterface

instance ToGet#(FIFOG#(t), t);
    function Get#(t) toGet(FIFOG#(t) m);
        return (interface Get;
                    method ActionValue#(t) get();
                        m.deq;
                        return m.first();
                    endmethod
                endinterface);
    endfunction
endinstance

instance ToPut#(FIFOG#(t), t);
    function Put#(t) toPut(FIFOG#(t) m);
        return (interface Put;
                    method Action put(t x);
                        m.enq(x);
                    endmethod
                endinterface);
    endfunction
endinstance

2-element conflict-free FIFOG

module mkFIFOG(FIFOG#(t)) provisos (Bits#(t,tSz));
    (* hide *)
    let _m <- mkFIFOGfromFIFOF(mkFIFOF);
    return _m;
endmodule

Sized conflict-free FIFOG

module mkSizedFIFOG#(Integer n)(FIFOG#(t)) provisos (Bits#(t,tSz));
    (* hide *)
    let _m <- mkFIFOGfromFIFOF(mkSizedFIFOF(n));
    return _m;
endmodule

1-element conflicting FIFOG

module mkFIFOG1(FIFOG#(t)) provisos (Bits#(t,tSz));
    (* hide *)
    let _m <- mkFIFOGfromFIFOF(mkFIFOF1);
    return _m;
endmodule

Pipeline FIFOG

module mkLFIFOG(FIFOG#(t)) provisos (Bits#(t,tSz));
    (* hide *)
    let _m <- mkFIFOGfromFIFOF(mkLFIFOF);
    return _m;
endmodule

Bypass FIFOG

Note: mkSizedBypassFIFOF isn't correct, so we don't expose a mkSizedBypassFIFOG (its notEmpty and notFull methods are CF with enq and deq, but semantically that is not possible with one-rule-at-a-time semantics.)

module mkBypassFIFOG(FIFOG#(t)) provisos (Bits#(t,tSz));
    (* hide *)
    let _m <- mkFIFOGfromFIFOF(mkBypassFIFOF);
    return _m;
endmodule

Pipeline FIFOG

This FIFO has a scheduling constraint that requires deq to come before enq.

module mkPipelineFIFOG(FIFOG#(t)) provisos (Bits#(t,tSz));
    (* hide *)
    let _m <- mkFIFOGfromFIFOF(mkPipelineFIFOF);
    return _m;
endmodule

Module to make FIFOG from a FIFOF module.

This module construct a FIFOG from a FIFOF by using wires to delay the the notEmpty and notFull signals so they can be used as canDeq and canEnq.

module [m] mkFIFOGfromFIFOF#(m#(FIFOF#(t)) mkM)(FIFOG#(t)) provisos (Bits#(t,tSz), IsModule#(m, a__));
    (* hide *)
    FIFOF#(t) _m <- mkM;

    Wire#(Bool) canEnq_wire <- mkBypassWire;
    Wire#(Bool) canDeq_wire <- mkBypassWire;
    // virtual regs are only used to force SB ordering between methods
    Reg#(Bool) virtualEnqReg <- mkRevertingVirtualReg(True);
    Reg#(Bool) virtualDeqReg <- mkRevertingVirtualReg(True);

    (* fire_when_enabled *)
    rule setCanEnqWire;
        canEnq_wire <= _m.notFull;
    endrule
    // If this assertion fails, it may be due to outside scheduling
    // constraints, especially for bypass FIFOs.
    (* fire_when_enabled *)
    rule setCanDeqWire;
        canDeq_wire <= _m.notEmpty;
    endrule

    // These rules can help with debugging when using this module on a new
    // FIFOF module, but they are commented out in normal use because
    // impCondOf() is not fully supported by the bluespec compiler yet and
    // causes compilation warnings.
    // rule doAssert1;
    //     if (canEnq_wire != impCondOf(_m.enq)) begin
    //         $fdisplay(stderr, "[ERROR] mkFIFOGfromFIFOF: canEnq_wire != impCondOf(_m.enq)");
    //     end
    // endrule
    // rule doAssert2;
    //     if (canDeq_wire != impCondOf(_m.deq)) begin
    //         $fdisplay(stderr, "[ERROR] mkFIFOGfromFIFOF: canDeq_wire != impCondOf(_m.deq)");
    //     end
    // endrule

    method Action enq(t x);
        _m.enq(x);
        virtualEnqReg <= False;
    endmethod
    method Action deq;
        _m.deq;
        virtualDeqReg <= False;
    endmethod
    method t first = _m.first;
    method Action clear = _m.clear;
    method Bool notFull = _m.notFull;
    method Bool notEmpty = _m.notEmpty;
    method Bool canEnq if (virtualEnqReg) = canEnq_wire;
    method Bool canDeq if (virtualDeqReg) = canDeq_wire;
endmodule