anchor.diff:  endinterface
   
   interface MPStreamEngine#(numeric type haystackBusWidth, numeric type configBusWidth);
  -   interface PipeIn#(MemData#(configBusWidth)) needle;
  -   interface PipeIn#(MemData#(configBusWidth)) mpNext;
  -   interface PipeIn#(MemData#(haystackBusWidth)) haystack;
  +   interface PipeIn#(MemDataF#(configBusWidth)) needle;
  +   interface PipeIn#(MemDataF#(configBusWidth)) mpNext;
  +   interface PipeIn#(MemDataF#(haystackBusWidth)) haystack;
      interface PipeOut#(Int#(32)) locdone;
  +   method Action clear();
  +   method Action start(Bit#(32) needleLen);
   endinterface
   
   typedef Bit#(8) Char;
  
positive.code:    FIFO#(void) doneFifo <- mkFIFO;
     
     rule countCycles;
        if (debug) $display("******************************************** %d", cycleCnt);
        cycleCnt <= cycleCnt+1;
     endrule
     
     rule haystackResp;
        if (debug) $display("mkMPEngine::haystackResp");
        let rv <- toGet(haystackFifo).get;
        haystackGb.enq(unpack(rv.data));
        if (rv.last)
           conff.deq;
     endrule
     
     rule haystackDrain(stage != Search);
        if (debug) $display("mkMPEngine::haystackDrain");
        haystackGb.deq;
     endrule
     
     rule bramDrain(stage != Search);
        if (debug) $display("mkMPEngine::mpNextDrain");
        let x <- mpNextBram.portA.response.get;
        let y <- needleBram.portA.response.get;
        efifo.deq;
     endrule
    
     
  `define OPTIMIZE_MISMATCH
  `ifdef OPTIMIZE_MISMATCH
     rule matchNeedleReq(stage == Search);
        if (debug) $display("mkMPEngine::matchNeedleReq %d %d", epochReg, iReg);
        needleBram.portA.request.put(BRAMRequest{write:False, address: truncate(iReg-1), datain:?, responseOnWrite:?});
        mpNextBram.portA.request.put(BRAMRequest{write:False, address: truncate(iReg), datain:?, responseOnWrite:?});
        efifo.enq(tuple2(epochReg,iReg));
        iReg <= 1;
     endrule
           
     rule matchNeedleResp(stage == Search);
        let nv <- needleBram.portA.response.get;
        let mp <- mpNextBram.portA.response.get;
        let epoch = tpl_1(efifo.first);
        efifo.deq;
        if (debug) $display("mkMPEngine::matchNeedleResp %d %d", epochReg, epoch);
        if (epoch == epochReg) begin
  	 Bool deq_haystack = False;
  	 let n = haystackLenReg;
  	 let m = needleLenReg;
  	 let hv = haystackGb.first;
  	 let i = tpl_2(efifo.first);
  	 let j = jReg;
  	 if (debug) $display("mkMPEngine::feck %d %d %d %d %x %x", n, m, i, j, hv[0], nv);
  	 if (j > n) begin
  	    // jReg points to the end of the haystack; we are done
  	    stage <= Config_needle;
  	    if (debug) $display("mkMPEngine::end of search %d", j);
  	    locf.enq(-1);
  	 end
  	 else if (i==m+1) begin
  	    // iReg points to the end of the needle; we have a match
  	    if (debug) $display("mkMPEngine::string match %d", j);
  	    locf.enq(unpack(haystackBase+j-i));
  	 end
  	 else if (nv != hv[0]) begin
  	    // mismatch betwen head of haystack and head of needle; rewind iReg
  	    if (debug) $display("mkMPEngine::char mismatch %d %d MP_Next[i]=%d", i, j, mp);
  	    if (mp == 0) begin
  	       iReg <= 1;
  	       jReg <= j+1;
  	       deq_haystack = True;
  	    end
  	    else begin
  	       epochReg <= epochReg + 1;
  	       iReg <= mp;
  	    end
  	 end
  	 else begin
  	    // match between head of needle and head of haystack; increment haystack
  	    if (debug) $display("mkMPEngine::char match(%d) %d %d", (nv == hv[0]), i, j);
  	    deq_haystack = True;
  	    jReg <= j+1;
  	    epochReg <= epochReg + 1;
  	    iReg <= i+1;
  	 end
  	 if (deq_haystack) begin
  	    haystackGb.deq;
  	    lastHD <= cycleCnt;
  	    if (debug) $display("mkMPEngine:: deq haystack(%d)", cycleCnt-lastHD);
  	 end
        end
        else begin
  	 if (debug) $display("mkMPEngine::discard");
  	 noAction;
        end
     endrule
  `else
     rule matchNeedleReq(stage == Search);
        if (debug) $display("mkMPEngine::matchNeedleReq %d %d", epochReg, iReg);
        needleBram.portA.request.put(BRAMRequest{write:False, address: truncate(iReg-1), datain:?, responseOnWrite:?});
        mpNextBram.portA.request.put(BRAMRequest{write:False, address: truncate(iReg), datain:?, responseOnWrite:?});
        efifo.enq(tuple2(epochReg,iReg));
        iReg <= iReg+1;
     endrule
           
     rule matchNeedleResp(stage == Search);
        let nv <- needleBram.portA.response.get;
        let mp <- mpNextBram.portA.response.get;
        let epoch = tpl_1(efifo.first);
        efifo.deq;
        if (debug) $display("mkMPEngine::matchNeedleResp %d %d", epochReg, epoch);
        if (epoch == epochReg) begin
  	 Bool deq_haystack = False;
  	 let n = haystackLenReg;
  	 let m = needleLenReg;
  	 let hv = haystack.first;
  	 let i = tpl_2(efifo.first);
  	 let j = jReg;
  	 if (debug) $display("mkMPEngine::feck %d %d %d %d %x %x", n, m, i, j, hv[0], nv);
  	 if (j > n) begin
  	    // jReg points to the end of the haystack; we are done
  	    stage <= Config_needle;
  	    if (debug) $display("mkMPEngine::end of search %d", j);
  	 end
  	 else if (i==m+1) begin
  	    // iReg points to the end of the needle; we have a match
  	    if (debug) $display("mkMPEngine::string match %d", j);
  	    locf.enq(unpack(haystackBase+j-i));
  	    epochReg <= epochReg + 1;
  	    iReg <= 1;
  	 end
  	 else if (nv != hv[0]) begin
  	    // mismatch betwen head of haystack and head of needle; rewind iReg
  	    if (debug) $display("mkMPEngine::char mismatch %d %d MP_Next[i]=%d", i, j, mp);
  	    epochReg <= epochReg + 1;
  	    if (mp == 0) begin
  	       iReg <= 1;
  	       jReg <= j+1;
  	       deq_haystack = True;
  	    end
  	    else begin
  	       iReg <= mp;
  	    end
  	 end
  	 else begin
  	    // match between head of needle and head of haystack; increment haystack
  	    if (debug) $display("mkMPEngine::char match(%d) %d %d", (nv == hv[0]), i, j);
  	    deq_haystack = True;
  	    jReg <= j+1;
  	 end
  	 if (deq_haystack) begin
  	    haystack.deq;
  	    lastHD <= cycleCnt;
  	    if (debug) $display("mkMPEngine:: deq haystack(%d)", cycleCnt-lastHD);
  	 end
        end
        else begin
  	 if (debug) $display("mkMPEngine::discard");
  	 noAction;
        end
     endrule
  `endif 
    
     interface PipeIn needle = n2b.pipe;
     interface PipeIn mpNext = mp2b.pipe;
     interface PipeIn haystack = toPipeIn(haystackFifo);
     interface PipeOut locdone = toPipeOut(locf);
  
  endmodule
  
negative.code: import Gearbox::*;
  import Connectable::*;
  import ConfigReg::*;
  import StmtFSM::*;
  
  import MemUtils::*;
  import MemTypes::*;
  