use FIFOF, not BypassFIFOF

use FIFOF, not BypassFIFOF

// Copyright (c) 2015 Cornell University.

// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
import Arith::*;
import BRAM::*;
import BRAMCore::*;
import Connectable::*;
import FIFO::*;
import FIFOF::*;
import SpecialFIFOs::*;
import OInt::*;
import StmtFSM::*;
import Vector::*;
import Pipe::*;
import AsymmetricBRAM::*;
import ConnectalBram::*;

import BcamTypes::*;

interface Ram9bx1k;
   interface PipeIn#(Bool) wEnb_iVld;
   interface PipeIn#(Bool) wEnb_indx;
   interface PipeIn#(Bool) wEnb_indc;
   interface PipeIn#(Bit#(9)) mPatt;
   interface PipeIn#(Bit#(9)) wPatt;
   interface PipeIn#(Bit#(5)) wAddr_indx;
   interface PipeIn#(Bit#(5)) wAddr_indc;
   interface PipeIn#(Bit#(5)) wIndx;
   interface PipeIn#(Bit#(32)) wIndc;
   interface PipeIn#(Bool) wIVld;
   interface PipeOut#(Bit#(1024)) mIndc;
endinterface
module mkRam9bx1k(Ram9bx1k);
   FIFOF#(Bool) wEnb_iVld_fifo <- mkFIFOF();
   FIFOF#(Bool) wEnb_indx_fifo <- mkFIFOF();
   FIFOF#(Bool) wEnb_indc_fifo <- mkFIFOF();
   FIFOF#(Bit#(9)) mPatt_fifo <- mkFIFOF();
   FIFOF#(Bit#(9)) wPatt_fifo <- mkFIFOF();
   FIFOF#(Bit#(5)) wAddr_indx_fifo <- mkFIFOF();
   FIFOF#(Bit#(5)) wAddr_indc_fifo <- mkFIFOF();
   FIFOF#(Bit#(5)) wIndx_fifo <- mkFIFOF();
   FIFOF#(Bit#(32)) wIndc_fifo <- mkFIFOF();
   FIFOF#(Bool) wIVld_fifo <- mkFIFOF();
   FIFOF#(Bit#(1024)) mIndc_fifo <- mkFIFOF();

   FIFOF#(Bit#(32)) iVld_fifo <- mkFIFOF;

   let verbose = True;
   Reg#(Bit#(32)) cycle <- mkReg(0);
   rule every1 if (verbose);
      cycle <= cycle + 1;
   endrule

   // WWID = 1, RWID = 32, WDEP = 16384, OREG = 1, INIT = 1
`define VLDRAM AsymmetricBRAM#(Bit#(9), Bit#(32), Bit#(14), Bit#(1))
   `VLDRAM vldram <- mkAsymmetricBRAM(True, False, "VLDram");

   // WWID = 5, RWID = 40, WDEP = 4096, OREG = 0, INIT = 1
`define INDXRAM AsymmetricBRAM#(Bit#(9), Bit#(40), Bit#(12), Bit#(5))
   Vector#(4, `INDXRAM) indxram <- replicateM(mkAsymmetricBRAM(True, False, "indxRam"));

   // DWID = 32, DDEP = 32, MRDW = "DONT_CARE", RREG=ALL, INIT=1
   BRAM_Configure bramCfg = defaultValue;
   bramCfg.memorySize = 32;
   bramCfg.latency=1;
   Vector#(32, BRAM2Port#(Bit#(5), Bit#(32))) dpmlab <- replicateM(ConnectalBram::mkBRAM2Server(bramCfg));
//`define DPMLAB AsymmetricBRAM#(Bit#(5), Bit#(32), Bit#(5), Bit#(32))
//   Vector#(32, `DPMLAB) dpmlab <- replicateM(mkAsymmetricBRAM(False, False, "dpmlab"));

   Vector#(4, Wire#(Bit#(40))) indx <- replicateM(mkDWire(0));

   Vector#(2, PipeOut#(Bit#(9))) wPattPipes <- mkForkVector(toPipeOut(wPatt_fifo));
   Vector#(3, PipeOut#(Bit#(5))) wAddrIndxPipes <- mkForkVector(toPipeOut(wAddr_indx_fifo));

   rule vldram_write;
      let wPatt <- toGet(wPattPipes[0]).get;
      let wAddr_indx <- toGet(wAddrIndxPipes[0]).get;
      let wEnb_iVld <- toGet(wEnb_iVld_fifo).get;
      let wIVld <- toGet(wIVld_fifo).get;
      Bit#(14) wAddr = {wPatt, wAddr_indx};
      vldram.writeServer.put(tuple2(wAddr, pack(wIVld)));
      $display("vldram %d: write to vldram wAddr=%x, data=%x", cycle, wAddr, pack(wIVld));
   endrule

   rule ram_read;
      let mPatt <- toGet(mPatt_fifo).get;
      vldram.readServer.request.put(mPatt);
      for (Integer i=0; i<4; i=i+1) begin
         indxram[i].readServer.request.put(mPatt);
      end
   endrule

   rule indxram_write;
      let wPatt <- toGet(wPattPipes[1]).get;
      let wAddr_indx <- toGet(wAddrIndxPipes[1]).get;
      let wEnb_indx <- toGet(wEnb_indx_fifo).get;
      let wIndx <- toGet(wIndx_fifo).get;
      for (Integer i=0; i<4; i=i+1) begin
         if (wAddr_indx[4:3] == fromInteger(i)) begin
            Bit#(12) wAddr = {wPatt, wAddr_indx[2:0]};
            indxram[i].writeServer.put(tuple2(wAddr, wIndx));
            $display("indxram %d: write i=%x wAddr=%x, data=%x", cycle, i, wAddr, wIndx);
         end
      end
   endrule

   rule dpmlab_write;
      let wAddr_indx <- toGet(wAddrIndxPipes[2]).get;
      let wAddr_indc <- toGet(wAddr_indc_fifo).get;
      let wEnb_indc <- toGet(wEnb_indc_fifo).get;
      let wIndc <- toGet(wIndc_fifo).get;
      for (Integer i=0; i<4; i=i+1) begin
         for (Integer j=0; j<8; j=j+1) begin
            if ((wAddr_indx[4:3] == fromInteger(i)) && wAddr_indx[2:0] == fromInteger(j)) begin
               $display("dpmlab %d: write i=%d, j=%d index=%d", cycle, i, j, i*8+j);
               //dpmlab[i*8+j].writeServer.put(tuple2(wAddr_indc, wIndc));
               dpmlab[i*8+j].portA.request.put(BRAMRequest{write:True, responseOnWrite:False, address: wAddr_indc, datain: wIndc});
            end
         end
      end
   endrule

   rule vldram_output;
      let v <- vldram.readServer.response.get;
      iVld_fifo.enq(v);
   endrule

   for (Integer i=0; i<4; i=i+1) begin
      rule indxram_output;
         let v <- indxram[i].readServer.response.get;
         for (Integer j=0; j<8; j=j+1) begin
            Bit#(5) addr = v[(j+1)*5-1 : j*5];
            //dpmlab[i*8+j].readServer.request.put(addr);
            dpmlab[i*8+j].portB.request.put(BRAMRequest{write: False, responseOnWrite: False, address: addr, datain: ?});
         end
      endrule
   end

   rule dpmlab_read_response;
      let ivld <- toGet(iVld_fifo).get;
      Bit#(1024) mIndc = 0;
      for (Integer i=0; i<4; i=i+1) begin
         for (Integer j=0; j<8; j=j+1) begin
            //let v <- dpmlab[i*8+j].readServer.response.get;
            let v <- dpmlab[i*8+j].portB.response.get;
            Vector#(32, Bit#(1)) ivld_vec = replicate(ivld[8*i+j]);
            Bit#(32) mIndcV = v & pack(ivld_vec);
            mIndc[(i*8+j+1)*32-1 : (i*8+j)*32] = mIndcV;
         end
      end
      mIndc_fifo.enq(mIndc);
   endrule

   interface PipeIn wEnb_iVld = toPipeIn(wEnb_iVld_fifo);
   interface PipeIn wEnb_indx = toPipeIn(wEnb_indx_fifo);
   interface PipeIn wEnb_indc = toPipeIn(wEnb_indc_fifo);
   interface PipeIn mPatt = toPipeIn(mPatt_fifo);
   interface PipeIn wPatt = toPipeIn(wPatt_fifo);
   interface PipeIn wAddr_indx = toPipeIn(wAddr_indx_fifo);
   interface PipeIn wAddr_indc = toPipeIn(wAddr_indc_fifo);
   interface PipeIn wIndx = toPipeIn(wIndx_fifo);
   interface PipeIn wIndc = toPipeIn(wIndc_fifo);
   interface PipeIn wIVld = toPipeIn(wIVld_fifo);
   interface PipeOut mIndc = toPipeOut(mIndc_fifo);
endmodule

interface Ram9b#(numeric type cdep);//camDepth);
   interface PipeIn#(Bool) wEnb_iVld;
   interface PipeIn#(Bool) wEnb_indx;
   interface PipeIn#(Bool) wEnb_indc;
   interface PipeIn#(Bit#(9)) mPatt;
   interface PipeIn#(Bit#(9)) wPatt;
   interface PipeIn#(Bit#(TAdd#(TLog#(cdep), 5))) wAddr_indx;
   interface PipeIn#(Bit#(5)) wAddr_indc;
   interface PipeIn#(Bit#(5)) wIndx;
   interface PipeIn#(Bit#(32)) wIndc;
   interface PipeIn#(Bool) wIVld;
   interface PipeOut#(Bit#(TMul#(cdep, 1024))) mIndc;
endinterface
module mkRam9b(Ram9b#(cdep))
   provisos(Mul#(cdep, 1024, indcWidth)
            ,Add#(TLog#(cdep), 5, wAddrHWidth));

   let verbose = True;
   Reg#(Bit#(32)) cycle <- mkReg(0);
   rule every1 if (verbose);
      cycle <= cycle + 1;
   endrule

   FIFOF#(Bool) wEnb_iVld_fifo <- mkFIFOF();
   FIFOF#(Bool) wEnb_indx_fifo <- mkFIFOF();
   FIFOF#(Bool) wEnb_indc_fifo <- mkFIFOF();
   FIFOF#(Bit#(9)) mPatt_fifo <- mkFIFOF();
   FIFOF#(Bit#(9)) wPatt_fifo <- mkFIFOF();
   FIFOF#(Bit#(wAddrHWidth)) wAddr_indx_fifo <- mkFIFOF();
   FIFOF#(Bit#(5)) wAddr_indc_fifo <- mkFIFOF();
   FIFOF#(Bit#(5)) wIndx_fifo <- mkFIFOF();
   FIFOF#(Bit#(32)) wIndc_fifo <- mkFIFOF();
   FIFOF#(Bool) wIVld_fifo <- mkFIFOF();
   FIFOF#(Bit#(indcWidth)) mIndc_fifo <- mkFIFOF();

   Vector#(cdep, Ram9bx1k) ram <- replicateM(mkRam9bx1k());

   rule ram_wEnb;
      let wEnb_iVld <- toGet(wEnb_iVld_fifo).get;
      let wEnb_indx <- toGet(wEnb_indx_fifo).get;
      let wEnb_indc <- toGet(wEnb_indc_fifo).get;
      let wAddr_indx <- toGet(wAddr_indx_fifo).get;
      Vector#(cdep, Bool) wEnb = replicate(False);
      for (Integer i=0; i < valueOf(cdep); i=i+1) begin
         wEnb[i] = ((wAddr_indx >> 5) == fromInteger(i));
         ram[i].wEnb_iVld.enq(wEnb_iVld && wEnb[i]);
         ram[i].wEnb_indx.enq(wEnb_indx && wEnb[i]);
         ram[i].wEnb_indc.enq(wEnb_indc && wEnb[i]);
         ram[i].wAddr_indx.enq(wAddr_indx[4:0]);
      end
      $display("ram9b %d: write wEnb to all ram blocks", cycle);
   endrule

   rule ram_mPatt;
      let mPatt <- toGet(mPatt_fifo).get;
      for (Integer i=0; i < valueOf(cdep); i=i+1) begin
         ram[i].mPatt.enq(mPatt);
      end
      $display("ram9b %d: mPatt=%x", cycle, mPatt);
   endrule

   rule ram_wPatt;
      let wPatt <- toGet(wPatt_fifo).get;
      for (Integer i=0; i < valueOf(cdep); i=i+1) begin
          ram[i].wPatt.enq(wPatt);
      end
      $display("ram9b %d: wPatt=%x", cycle, wPatt);
   endrule

   rule ram_wAddr;
      let wAddr_indc <- toGet(wAddr_indc_fifo).get;
      let wIndx <- toGet(wIndx_fifo).get;
      let wIVld <- toGet(wIVld_fifo).get;
      let wIndc <- toGet(wIndc_fifo).get;
      for (Integer i=0; i < valueOf(cdep); i=i+1) begin
         ram[i].wAddr_indc.enq(wAddr_indc);
         ram[i].wIndx.enq(wIndx);
         ram[i].wIVld.enq(wIVld);
         ram[i].wIndc.enq(wIndc);
      end
      $display("ram9b %d: wAddr=%x", cycle, wAddr_indc);
   endrule

   rule ram_output;
      Vector#(cdep, Bit#(1024)) mIndc;
      for (Integer i=0; i < valueOf(cdep); i=i+1) begin
         let v <- toGet(ram[i].mIndc).get;
         mIndc[i] = v;
      end
      mIndc_fifo.enq(pack(mIndc));
      $display("ram9b %d: mIndc=%x", cycle, pack(mIndc));
   endrule

   interface PipeIn wEnb_iVld = toPipeIn(wEnb_iVld_fifo);
   interface PipeIn wEnb_indx = toPipeIn(wEnb_indx_fifo);
   interface PipeIn wEnb_indc = toPipeIn(wEnb_indc_fifo);
   interface PipeIn mPatt = toPipeIn(mPatt_fifo);
   interface PipeIn wPatt = toPipeIn(wPatt_fifo);
   interface PipeIn wAddr_indx = toPipeIn(wAddr_indx_fifo);
   interface PipeIn wAddr_indc = toPipeIn(wAddr_indc_fifo);
   interface PipeIn wIndx = toPipeIn(wIndx_fifo);
   interface PipeIn wIndc = toPipeIn(wIndc_fifo);
   interface PipeIn wIVld = toPipeIn(wIVld_fifo);
   interface PipeOut mIndc = toPipeOut(mIndc_fifo);
endmodule

// Copyright (c) 2015 Cornell University.

// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
import Arith::*;
import BRAM::*;
import BRAMCore::*;
import Connectable::*;
import FIFO::*;
import FIFOF::*;
import SpecialFIFOs::*;
import OInt::*;
import StmtFSM::*;
import Vector::*;
import Pipe::*;
import AsymmetricBRAM::*;
import ConnectalBram::*;

import BcamTypes::*;

interface Ram9bx1k;
   interface PipeIn#(Bool) wEnb_iVld;
   interface PipeIn#(Bool) wEnb_indx;
   interface PipeIn#(Bool) wEnb_indc;
   interface PipeIn#(Bit#(9)) mPatt;
   interface PipeIn#(Bit#(9)) wPatt;
   interface PipeIn#(Bit#(5)) wAddr_indx;
   interface PipeIn#(Bit#(5)) wAddr_indc;
   interface PipeIn#(Bit#(5)) wIndx;
   interface PipeIn#(Bit#(32)) wIndc;
   interface PipeIn#(Bool) wIVld;
   interface PipeOut#(Bit#(1024)) mIndc;
endinterface
module mkRam9bx1k(Ram9bx1k);
   FIFOF#(Bool) wEnb_iVld_fifo <- mkBypassFIFOF();
   FIFOF#(Bool) wEnb_indx_fifo <- mkBypassFIFOF();
   FIFOF#(Bool) wEnb_indc_fifo <- mkBypassFIFOF();
   FIFOF#(Bit#(9)) mPatt_fifo <- mkBypassFIFOF();
   FIFOF#(Bit#(9)) wPatt_fifo <- mkBypassFIFOF();
   FIFOF#(Bit#(5)) wAddr_indx_fifo <- mkBypassFIFOF();
   FIFOF#(Bit#(5)) wAddr_indc_fifo <- mkBypassFIFOF();
   FIFOF#(Bit#(5)) wIndx_fifo <- mkBypassFIFOF();
   FIFOF#(Bit#(32)) wIndc_fifo <- mkBypassFIFOF();
   FIFOF#(Bool) wIVld_fifo <- mkBypassFIFOF();
   FIFOF#(Bit#(1024)) mIndc_fifo <- mkBypassFIFOF();

   FIFOF#(Bit#(32)) iVld_fifo <- mkFIFOF;

   let verbose = True;
   Reg#(Bit#(32)) cycle <- mkReg(0);
   rule every1 if (verbose);
      cycle <= cycle + 1;
   endrule

   // WWID = 1, RWID = 32, WDEP = 16384, OREG = 1, INIT = 1
`define VLDRAM AsymmetricBRAM#(Bit#(9), Bit#(32), Bit#(14), Bit#(1))
   `VLDRAM vldram <- mkAsymmetricBRAM(True, False, "VLDram");

   // WWID = 5, RWID = 40, WDEP = 4096, OREG = 0, INIT = 1
`define INDXRAM AsymmetricBRAM#(Bit#(9), Bit#(40), Bit#(12), Bit#(5))
   Vector#(4, `INDXRAM) indxram <- replicateM(mkAsymmetricBRAM(True, False, "indxRam"));

   // DWID = 32, DDEP = 32, MRDW = "DONT_CARE", RREG=ALL, INIT=1
   BRAM_Configure bramCfg = defaultValue;
   bramCfg.memorySize = 32;
   bramCfg.latency=1;
   Vector#(32, BRAM2Port#(Bit#(5), Bit#(32))) dpmlab <- replicateM(ConnectalBram::mkBRAM2Server(bramCfg));
//`define DPMLAB AsymmetricBRAM#(Bit#(5), Bit#(32), Bit#(5), Bit#(32))
//   Vector#(32, `DPMLAB) dpmlab <- replicateM(mkAsymmetricBRAM(False, False, "dpmlab"));

   Vector#(4, Wire#(Bit#(40))) indx <- replicateM(mkDWire(0));

   Vector#(2, PipeOut#(Bit#(9))) wPattPipes <- mkForkVector(toPipeOut(wPatt_fifo));
   Vector#(3, PipeOut#(Bit#(5))) wAddrIndxPipes <- mkForkVector(toPipeOut(wAddr_indx_fifo));

   rule vldram_write;
      let wPatt <- toGet(wPattPipes[0]).get;
      let wAddr_indx <- toGet(wAddrIndxPipes[0]).get;
      let wEnb_iVld <- toGet(wEnb_iVld_fifo).get;
      let wIVld <- toGet(wIVld_fifo).get;
      Bit#(14) wAddr = {wPatt, wAddr_indx};
      vldram.writeServer.put(tuple2(wAddr, pack(wIVld)));
      $display("vldram %d: write to vldram wAddr=%x, data=%x", cycle, wAddr, pack(wIVld));
   endrule

   rule ram_read;
      let mPatt <- toGet(mPatt_fifo).get;
      vldram.readServer.request.put(mPatt);
      for (Integer i=0; i<4; i=i+1) begin
         indxram[i].readServer.request.put(mPatt);
      end
   endrule

   rule indxram_write;
      let wPatt <- toGet(wPattPipes[1]).get;
      let wAddr_indx <- toGet(wAddrIndxPipes[1]).get;
      let wEnb_indx <- toGet(wEnb_indx_fifo).get;
      let wIndx <- toGet(wIndx_fifo).get;
      for (Integer i=0; i<4; i=i+1) begin
         if (wAddr_indx[4:3] == fromInteger(i)) begin
            Bit#(12) wAddr = {wPatt, wAddr_indx[2:0]};
            indxram[i].writeServer.put(tuple2(wAddr, wIndx));
            $display("indxram %d: write i=%x wAddr=%x, data=%x", cycle, i, wAddr, wIndx);
         end
      end
   endrule

   rule dpmlab_write;
      let wAddr_indx <- toGet(wAddrIndxPipes[2]).get;
      let wAddr_indc <- toGet(wAddr_indc_fifo).get;
      let wEnb_indc <- toGet(wEnb_indc_fifo).get;
      let wIndc <- toGet(wIndc_fifo).get;
      for (Integer i=0; i<4; i=i+1) begin
         for (Integer j=0; j<8; j=j+1) begin
            if ((wAddr_indx[4:3] == fromInteger(i)) && wAddr_indx[2:0] == fromInteger(j)) begin
               $display("dpmlab %d: write i=%d, j=%d index=%d", cycle, i, j, i*8+j);
               //dpmlab[i*8+j].writeServer.put(tuple2(wAddr_indc, wIndc));
               dpmlab[i*8+j].portA.request.put(BRAMRequest{write:True, responseOnWrite:False, address: wAddr_indc, datain: wIndc});
            end
         end
      end
   endrule

   rule vldram_output;
      let v <- vldram.readServer.response.get;
      iVld_fifo.enq(v);
   endrule

   for (Integer i=0; i<4; i=i+1) begin
      rule indxram_output;
         let v <- indxram[i].readServer.response.get;
         for (Integer j=0; j<8; j=j+1) begin
            Bit#(5) addr = v[(j+1)*5-1 : j*5];
            //dpmlab[i*8+j].readServer.request.put(addr);
            dpmlab[i*8+j].portB.request.put(BRAMRequest{write: False, responseOnWrite: False, address: addr, datain: ?});
         end
      endrule
   end

   rule dpmlab_read_response;
      let ivld <- toGet(iVld_fifo).get;
      Bit#(1024) mIndc = 0;
      for (Integer i=0; i<4; i=i+1) begin
         for (Integer j=0; j<8; j=j+1) begin
            //let v <- dpmlab[i*8+j].readServer.response.get;
            let v <- dpmlab[i*8+j].portB.response.get;
            Vector#(32, Bit#(1)) ivld_vec = replicate(ivld[8*i+j]);
            Bit#(32) mIndcV = v & pack(ivld_vec);
            mIndc[(i*8+j+1)*32-1 : (i*8+j)*32] = mIndcV;
         end
      end
      mIndc_fifo.enq(mIndc);
   endrule

   interface PipeIn wEnb_iVld = toPipeIn(wEnb_iVld_fifo);
   interface PipeIn wEnb_indx = toPipeIn(wEnb_indx_fifo);
   interface PipeIn wEnb_indc = toPipeIn(wEnb_indc_fifo);
   interface PipeIn mPatt = toPipeIn(mPatt_fifo);
   interface PipeIn wPatt = toPipeIn(wPatt_fifo);
   interface PipeIn wAddr_indx = toPipeIn(wAddr_indx_fifo);
   interface PipeIn wAddr_indc = toPipeIn(wAddr_indc_fifo);
   interface PipeIn wIndx = toPipeIn(wIndx_fifo);
   interface PipeIn wIndc = toPipeIn(wIndc_fifo);
   interface PipeIn wIVld = toPipeIn(wIVld_fifo);
   interface PipeOut mIndc = toPipeOut(mIndc_fifo);
endmodule

interface Ram9b#(numeric type cdep);//camDepth);
   interface PipeIn#(Bool) wEnb_iVld;
   interface PipeIn#(Bool) wEnb_indx;
   interface PipeIn#(Bool) wEnb_indc;
   interface PipeIn#(Bit#(9)) mPatt;
   interface PipeIn#(Bit#(9)) wPatt;
   interface PipeIn#(Bit#(TAdd#(TLog#(cdep), 5))) wAddr_indx;
   interface PipeIn#(Bit#(5)) wAddr_indc;
   interface PipeIn#(Bit#(5)) wIndx;
   interface PipeIn#(Bit#(32)) wIndc;
   interface PipeIn#(Bool) wIVld;
   interface PipeOut#(Bit#(TMul#(cdep, 1024))) mIndc;
endinterface
module mkRam9b(Ram9b#(cdep))
   provisos(Mul#(cdep, 1024, indcWidth)
            ,Add#(TLog#(cdep), 5, wAddrHWidth));

   let verbose = True;
   Reg#(Bit#(32)) cycle <- mkReg(0);
   rule every1 if (verbose);
      cycle <= cycle + 1;
   endrule

   FIFOF#(Bool) wEnb_iVld_fifo <- mkBypassFIFOF();
   FIFOF#(Bool) wEnb_indx_fifo <- mkBypassFIFOF();
   FIFOF#(Bool) wEnb_indc_fifo <- mkBypassFIFOF();
   FIFOF#(Bit#(9)) mPatt_fifo <- mkBypassFIFOF();
   FIFOF#(Bit#(9)) wPatt_fifo <- mkBypassFIFOF();
   FIFOF#(Bit#(wAddrHWidth)) wAddr_indx_fifo <- mkBypassFIFOF();
   FIFOF#(Bit#(5)) wAddr_indc_fifo <- mkBypassFIFOF();
   FIFOF#(Bit#(5)) wIndx_fifo <- mkBypassFIFOF();
   FIFOF#(Bit#(32)) wIndc_fifo <- mkBypassFIFOF();
   FIFOF#(Bool) wIVld_fifo <- mkBypassFIFOF();
   FIFOF#(Bit#(indcWidth)) mIndc_fifo <- mkBypassFIFOF();

   Vector#(cdep, Ram9bx1k) ram <- replicateM(mkRam9bx1k());

   rule ram_wEnb;
      let wEnb_iVld <- toGet(wEnb_iVld_fifo).get;
      let wEnb_indx <- toGet(wEnb_indx_fifo).get;
      let wEnb_indc <- toGet(wEnb_indc_fifo).get;
      let wAddr_indx <- toGet(wAddr_indx_fifo).get;
      Vector#(cdep, Bool) wEnb = replicate(False);
      for (Integer i=0; i < valueOf(cdep); i=i+1) begin
         wEnb[i] = ((wAddr_indx >> 5) == fromInteger(i));
         ram[i].wEnb_iVld.enq(wEnb_iVld && wEnb[i]);
         ram[i].wEnb_indx.enq(wEnb_indx && wEnb[i]);
         ram[i].wEnb_indc.enq(wEnb_indc && wEnb[i]);
         ram[i].wAddr_indx.enq(wAddr_indx[4:0]);
      end
      $display("ram9b %d: write wEnb to all ram blocks", cycle);
   endrule

   rule ram_mPatt;
      let mPatt <- toGet(mPatt_fifo).get;
      for (Integer i=0; i < valueOf(cdep); i=i+1) begin
         ram[i].mPatt.enq(mPatt);
      end
      $display("ram9b %d: mPatt=%x", cycle, mPatt);
   endrule

   rule ram_wPatt;
      let wPatt <- toGet(wPatt_fifo).get;
      for (Integer i=0; i < valueOf(cdep); i=i+1) begin
          ram[i].wPatt.enq(wPatt);
      end
      $display("ram9b %d: wPatt=%x", cycle, wPatt);
   endrule

   rule ram_wAddr;
      let wAddr_indc <- toGet(wAddr_indc_fifo).get;
      let wIndx <- toGet(wIndx_fifo).get;
      let wIVld <- toGet(wIVld_fifo).get;
      let wIndc <- toGet(wIndc_fifo).get;
      for (Integer i=0; i < valueOf(cdep); i=i+1) begin
         ram[i].wAddr_indc.enq(wAddr_indc);
         ram[i].wIndx.enq(wIndx);
         ram[i].wIVld.enq(wIVld);
         ram[i].wIndc.enq(wIndc);
      end
      $display("ram9b %d: wAddr=%x", cycle, wAddr_indc);
   endrule

   rule ram_output;
      Vector#(cdep, Bit#(1024)) mIndc;
      for (Integer i=0; i < valueOf(cdep); i=i+1) begin
         let v <- toGet(ram[i].mIndc).get;
         mIndc[i] = v;
      end
      mIndc_fifo.enq(pack(mIndc));
      $display("ram9b %d: mIndc=%x", cycle, pack(mIndc));
   endrule

   interface PipeIn wEnb_iVld = toPipeIn(wEnb_iVld_fifo);
   interface PipeIn wEnb_indx = toPipeIn(wEnb_indx_fifo);
   interface PipeIn wEnb_indc = toPipeIn(wEnb_indc_fifo);
   interface PipeIn mPatt = toPipeIn(mPatt_fifo);
   interface PipeIn wPatt = toPipeIn(wPatt_fifo);
   interface PipeIn wAddr_indx = toPipeIn(wAddr_indx_fifo);
   interface PipeIn wAddr_indc = toPipeIn(wAddr_indc_fifo);
   interface PipeIn wIndx = toPipeIn(wIndx_fifo);
   interface PipeIn wIndc = toPipeIn(wIndc_fifo);
   interface PipeIn wIVld = toPipeIn(wIVld_fifo);
   interface PipeOut mIndc = toPipeOut(mIndc_fifo);
endmodule


change interface type to Bit#(64)

change interface type to Bit#(64)

// Copyright (c) 2014 Quanta Research Cambridge, Inc.

// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

import XilinxCells::*;
import XbsvXilinxCells::*;
import Gearbox::*;
import Pipe::*;
import FIFO::*;
import BRAMFIFO::*;
import Vector::*;
import Clocks::*;
import DefaultValue::*;

(* always_enabled *)
interface FMComms1ADCPins;
   method Action io_adc_data_p(Bit#(14) v);
   method Action io_adc_data_n(Bit#(14) v);
   method Action io_adc_or_p(Bit#(1) v);
   method Action io_adc_or_n(Bit#(1) v);
   method Action io_adc_dco_p(Bit#(1) v);
   method Action io_adc_dco_n(Bit#(1) v);
endinterface

typedef struct {
   Bit#(14) data_i;
   Bit#(1) z_i;
   Bit#(1) or_i;
   Bit#(14) data_q;
   Bit#(1) z_q;
   Bit#(1) or_q;
   } IQ deriving (Bits);

interface FMComms1ADC;
   interface FMComms1ADCPins pins;
   interface PipeOut#(Bit#(64)) adc;
endinterface

/* This module accepts inputs from an Analog Devices FMComms1
 * evaluation board Analog to Digital Converter, and delivers
 * the data as a PipeOut type on the default clock.
 *
 * Input is double data rate, with clock supplied by the FMComms1
 * Input data is 14 bits twos-complement or offset binary, plus
 * an overrange signa=
 *
 * Differential inputs are converted to single ended by using Xilinx IBUFDS
 * cells. The clock is converted to single ended by an IBUFGDS cell
 *
 * DDR data is convered to SDR using IDDR cells
 * At this point, the data is a 14 bit in-phase data signal, plus in-phase
 * overrange, but a 14 bit quadrature signal, plus overrange.
 *
 * The data is packed into a 64-bit IQ datatype, with overrange as the LSB
 *
 * The 32-bit data is converted to 64-bits by a Gearbox
 *
 * Clock conversion happens 64-bits wide using a SyncBRAMFIFO, which
 * presents a PipeOut channel to the rest of the logic.
 */

module mkFMComms1ADC(FMComms1ADC);

   Clock def_clock <- exposeCurrentClock;
   Reset def_reset <- exposeCurrentReset;

   function Bit#(1) foo(ReadOnly#(Bit#(1)) v);
      return (v._read());
   endfunction

   function ReadOnly#(Bit#(14)) rofromrov(Vector#(14, ReadOnly#(Bit#(1))) v);
      return(interface ReadOnly;
	     method Bit#(14) _read;
		return ( pack(map(foo, v)));
	     endmethod
	     endinterface
	     );
   endfunction

   Vector#(14, Wire#(Bit#(1))) adc_data_p = newVector;

   for (Integer i = 0; i < 14; i = i + 1)
      adc_data_p[i] <- mkDWire(0);
   Vector#(14, Wire#(Bit#(1))) adc_data_n = newVector;
   for (Integer i = 0; i < 14; i = i + 1)
      adc_data_n[i] <- mkDWire(0);

   Wire#(Bit#(1)) adc_or_p <- mkDWire(0);
   Wire#(Bit#(1)) adc_or_n <- mkDWire(0);
   Wire#(Bit#(1)) adc_dco_p <- mkDWire(0);
   Wire#(Bit#(1)) adc_dco_n <- mkDWire(0);

   Vector#(14, ReadOnly#(Bit#(1))) v_adc_data;   /* data */
   ReadOnly#(Bit#(14)) adc_data;

   ReadOnly#(Bit#(1)) adc_or;      /* overrange */
   Clock adc_dco;     /* DDR clock */

   adc_dco <- mkClockIBUFDS(adc_dco_p, adc_dco_n);

   Reset adc_reset <- mkAsyncReset(3, def_reset, adc_dco);
   for(Integer i = 0; i < 14; i = i + 1)
      v_adc_data[i] <- mkIBUFDS(adc_data_p[i], adc_data_n[i], clocked_by adc_dco);
   adc_data = rofromrov(v_adc_data);

   adc_or <- mkIBUFDS(adc_or_p, adc_or_n, clocked_by adc_dco);

   IDDRParams#(Bit#(14)) iddrparams_data = defaultValue;
   iddrparams_data.ddr_clk_edge = "SAME_EDGE_PIPELINED";
   IDDR#(Bit#(14)) adc_sdr_data <- mkIDDR(iddrparams_data, clocked_by adc_dco);

   IDDRParams#(Bit#(1)) iddrparams_or = defaultValue;
   iddrparams_or.ddr_clk_edge = "SAME_EDGE_PIPELINED";
   IDDR#(Bit#(1)) adc_sdr_or <- mkIDDR(iddrparams_or, clocked_by adc_dco);

   rule sendup_adc_data;
      adc_sdr_data.d(pack(adc_data));
   endrule

   rule sendup_adc_or;
      adc_sdr_or.d(adc_or);
   endrule

   Gearbox#(1, 2, IQ) gb <- mk1toNGearbox(adc_dco, adc_reset, adc_dco, adc_reset);
   SyncFIFOIfc#(Vector#(2, IQ)) infifo <- mkSyncBRAMFIFO(128, adc_dco, adc_reset, def_clock, def_reset);

   rule sendup_gb_data;
      gb.enq(unpack(pack(IQ{data_i: adc_sdr_data.q1, z_i: 0, or_i: adc_sdr_or.q1,
	 data_q: adc_sdr_data.q2, z_q: 0, or_q: adc_sdr_or.q2})));
   endrule

   rule sendup_adc_fifo_data;
      gb.deq();
      infifo.enq(gb.first());
   endrule

   interface FMComms1ADCPins pins;

      method Action io_adc_data_p(Bit#(14) v);
         for (Integer i = 0; i < 14; i = i + 1)
	    adc_data_p[i] <= v[i];
      endmethod

      method Action io_adc_data_n(Bit#(14) v);
         for (Integer i = 0; i < 14; i = i + 1)
	    adc_data_n[i] <= v[i];
      endmethod

      method Action io_adc_or_p(Bit#(1) v);
	 adc_or_p <= v;
      endmethod

      method Action io_adc_or_n(Bit#(1) v);
	 adc_or_n <= v;
      endmethod
      method Action io_adc_dco_p(Bit#(1) v);
	 adc_dco_p <= v;
      endmethod

      method Action io_adc_dco_n(Bit#(1) v);
	 adc_dco_n <= v;
      endmethod

   endinterface

   interface PipeOut adc;

      method Bit#(64) first();
	 return(unpack(pack(infifo.first)));
      endmethod

      method Action deq() = infifo.deq;

      method Bool notEmpty() = infifo.notEmpty;

   endinterface

endmodule

// Copyright (c) 2014 Quanta Research Cambridge, Inc.

// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

import XilinxCells::*;
import XbsvXilinxCells::*;
import Gearbox::*;
import Pipe::*;
import FIFO::*;
import BRAMFIFO::*;
import Vector::*;
import Clocks::*;
import DefaultValue::*;

(* always_enabled *)
interface FMComms1ADCPins;
   method Action io_adc_data_p(Bit#(14) v);
   method Action io_adc_data_n(Bit#(14) v);
   method Action io_adc_or_p(Bit#(1) v);
   method Action io_adc_or_n(Bit#(1) v);
   method Action io_adc_dco_p(Bit#(1) v);
   method Action io_adc_dco_n(Bit#(1) v);
endinterface

typedef struct {
   Bit#(14) data_i;
   Bit#(1) z_i;
   Bit#(1) or_i;
   Bit#(14) data_q;
   Bit#(1) z_q;
   Bit#(1) or_q;
   } IQ deriving (Bits);

interface FMComms1ADC;
   interface FMComms1ADCPins pins;
   interface PipeOut#(Vector#(2, IQ)) adc;
endinterface

/* This module accepts inputs from an Analog Devices FMComms1
 * evaluation board Analog to Digital Converter, and delivers
 * the data as a PipeOut type on the default clock.
 *
 * Input is double data rate, with clock supplied by the FMComms1
 * Input data is 14 bits twos-complement or offset binary, plus
 * an overrange signa=
 *
 * Differential inputs are converted to single ended by using Xilinx IBUFDS
 * cells. The clock is converted to single ended by an IBUFGDS cell
 *
 * DDR data is convered to SDR using IDDR cells
 * At this point, the data is a 14 bit in-phase data signal, plus in-phase
 * overrange, but a 14 bit quadrature signal, plus overrange.
 *
 * The data is packed into a 64-bit IQ datatype, with overrange as the LSB
 *
 * The 32-bit data is converted to 64-bits by a Gearbox
 *
 * Clock conversion happens 64-bits wide using a SyncBRAMFIFO, which
 * presents a PipeOut channel to the rest of the logic.
 */

module mkFMComms1ADC(FMComms1ADC);

   Clock def_clock <- exposeCurrentClock;
   Reset def_reset <- exposeCurrentReset;

   function Bit#(1) foo(ReadOnly#(Bit#(1)) v);
      return (v._read());
   endfunction

   function ReadOnly#(Bit#(14)) rofromrov(Vector#(14, ReadOnly#(Bit#(1))) v);
      return(interface ReadOnly;
	     method Bit#(14) _read;
		return ( pack(map(foo, v)));
	     endmethod
	     endinterface
	     );
   endfunction

   Vector#(14, Wire#(Bit#(1))) adc_data_p = newVector;

   for (Integer i = 0; i < 14; i = i + 1)
      adc_data_p[i] <- mkDWire(0);
   Vector#(14, Wire#(Bit#(1))) adc_data_n = newVector;
   for (Integer i = 0; i < 14; i = i + 1)
      adc_data_n[i] <- mkDWire(0);

   Wire#(Bit#(1)) adc_or_p <- mkDWire(0);
   Wire#(Bit#(1)) adc_or_n <- mkDWire(0);
   Wire#(Bit#(1)) adc_dco_p <- mkDWire(0);
   Wire#(Bit#(1)) adc_dco_n <- mkDWire(0);

   Vector#(14, ReadOnly#(Bit#(1))) v_adc_data;   /* data */
   ReadOnly#(Bit#(14)) adc_data;

   ReadOnly#(Bit#(1)) adc_or;      /* overrange */
   Clock adc_dco;     /* DDR clock */

   adc_dco <- mkClockIBUFDS(adc_dco_p, adc_dco_n);

   Reset adc_reset <- mkAsyncReset(3, def_reset, adc_dco);
   for(Integer i = 0; i < 14; i = i + 1)
      v_adc_data[i] <- mkIBUFDS(adc_data_p[i], adc_data_n[i], clocked_by adc_dco);
   adc_data = rofromrov(v_adc_data);

   adc_or <- mkIBUFDS(adc_or_p, adc_or_n, clocked_by adc_dco);

   IDDRParams#(Bit#(14)) iddrparams_data = defaultValue;
   iddrparams_data.ddr_clk_edge = "SAME_EDGE_PIPELINED";
   IDDR#(Bit#(14)) adc_sdr_data <- mkIDDR(iddrparams_data, clocked_by adc_dco);

   IDDRParams#(Bit#(1)) iddrparams_or = defaultValue;
   iddrparams_or.ddr_clk_edge = "SAME_EDGE_PIPELINED";
   IDDR#(Bit#(1)) adc_sdr_or <- mkIDDR(iddrparams_or, clocked_by adc_dco);

   rule sendup_adc_data;
      adc_sdr_data.d(pack(adc_data));
   endrule

   rule sendup_adc_or;
      adc_sdr_or.d(adc_or);
   endrule

   Gearbox#(1, 2, IQ) gb <- mk1toNGearbox(adc_dco, adc_reset, adc_dco, adc_reset);
   SyncFIFOIfc#(Vector#(2, IQ)) infifo <- mkSyncBRAMFIFO(128, adc_dco, adc_reset, def_clock, def_reset);

   rule sendup_gb_data;
      gb.enq(unpack(pack(IQ{data_i: adc_sdr_data.q1, z_i: 0, or_i: adc_sdr_or.q1,
	 data_q: adc_sdr_data.q2, z_q: 0, or_q: adc_sdr_or.q2})));
   endrule

   rule sendup_adc_fifo_data;
      gb.deq();
      infifo.enq(gb.first());
   endrule

   interface FMComms1ADCPins pins;

      method Action io_adc_data_p(Bit#(14) v);
         for (Integer i = 0; i < 14; i = i + 1)
	    adc_data_p[i] <= v[i];
      endmethod

      method Action io_adc_data_n(Bit#(14) v);
         for (Integer i = 0; i < 14; i = i + 1)
	    adc_data_n[i] <= v[i];
      endmethod

      method Action io_adc_or_p(Bit#(1) v);
	 adc_or_p <= v;
      endmethod

      method Action io_adc_or_n(Bit#(1) v);
	 adc_or_n <= v;
      endmethod
      method Action io_adc_dco_p(Bit#(1) v);
	 adc_dco_p <= v;
      endmethod

      method Action io_adc_dco_n(Bit#(1) v);
	 adc_dco_n <= v;
      endmethod

   endinterface

   interface PipeOut adc;

      method Vector#(2, IQ) first();
	 return(unpack(pack(infifo.first)));
      endmethod

      method Action deq() = infifo.deq;

      method Bool notEmpty() = infifo.notEmpty;

   endinterface

endmodule


updated tests/memread_manual to use memDataPipe

// Copyright (c) 2013 Quanta Research Cambridge, Inc.

// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
import FIFO::*;
import FIFOF::*;
import Vector::*;
import BuildVector::*;
import GetPut::*;
import ClientServer::*;

import Pipe::*;
import MemTypes::*;
import MemreadEngine::*;
import Pipe::*;
import HostInterface::*;

interface ReadTestRequest;
   method Action startRead(Bit#(32) pointer, Bit#(32) numBytes, Bit#(32) burstLen, Bit#(32) iterCnt);
endinterface

interface ReadTest;
   interface ReadTestRequest request;
   interface Vector#(1,MemReadClient#(DataBusWidth)) dmaClient;
endinterface

interface ReadTestIndication;
   method Action readDone(Bit#(32) mismatchCount);
endinterface

module mkReadTest#(ReadTestIndication indication) (ReadTest);

   Reg#(SGLId)   pointer <- mkReg(0);
   Reg#(Bit#(32))       numBytes <- mkReg(0);
   Reg#(Bit#(BurstLenSize)) burstLenBytes <- mkReg(0);
   Reg#(Bit#(32))  itersToFinish <- mkReg(0);
   Reg#(Bit#(32))   itersToStart <- mkReg(0);
   Reg#(Bit#(32))        wordsRead <- mkReg(0);
   Reg#(Bit#(32)) mismatchCounts <- mkReg(0);
   MemreadEngine#(DataBusWidth,1,1) re <- mkMemreadEngine;

   rule start (itersToStart > 0);
      $display("Test: request.put");
      re.read_servers[0].cmdServer.request.put(MemengineCmd{sglId:pointer, base:0, len:numBytes, burstLen:burstLenBytes});
      itersToStart <= itersToStart-1;
   endrule

   rule check;
      let v <- toGet(re.read_servers[0].memDataPipe).get;
      let rval = wordsRead/4;
      let expectedV = {rval+1,rval};
      let misMatch = v.data != expectedV;
      mismatchCounts <= mismatchCounts + (misMatch ? 1 : 0);
      let new_wordsRead = wordsRead + fromInteger(valueOf(DataBusWidth))/8;
      //$display("Test: check new=%x numBytes=%x wordsRead=%x misMatch=%x read=%x expect=%x", new_wordsRead, numBytes, wordsRead, misMatch, v, expectedV);
      if (v.last) begin
         $display("Test: itersToFinish %x", itersToFinish);
         if (itersToFinish == 1) begin
	    indication.readDone(mismatchCounts);
         end
         itersToFinish <= itersToFinish - 1;
	 new_wordsRead = 0;
      end
      wordsRead <= new_wordsRead;
   endrule

   rule finish;
      let rv <- re.read_servers[0].cmdServer.response.get;
   endrule

   interface dmaClient = vec(re.dmaClient);
   interface ReadTestRequest request;
      method Action startRead(Bit#(32) rp, Bit#(32) nb, Bit#(32) bl, Bit#(32) ic) if (itersToStart == 0 && itersToFinish == 0);
         $display("startRead pointer=%x numBytes %x burstLen %x iteration %x", rp, nb, bl, ic);
	 pointer <= rp;
	 numBytes  <= nb;
	 burstLenBytes  <= truncate(bl);
	 itersToFinish <= ic;
	 itersToStart <= ic;
	 mismatchCounts <= 0;
	 wordsRead <= 0;
      endmethod
   endinterface
endmodule

// Copyright (c) 2013 Quanta Research Cambridge, Inc.

// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
import FIFO::*;
import FIFOF::*;
import Vector::*;
import BuildVector::*;
import GetPut::*;
import ClientServer::*;

import Pipe::*;
import MemTypes::*;
import MemreadEngine::*;
import Pipe::*;
import HostInterface::*;

interface ReadTestRequest;
   method Action startRead(Bit#(32) pointer, Bit#(32) numBytes, Bit#(32) burstLen, Bit#(32) iterCnt);
endinterface

interface ReadTest;
   interface ReadTestRequest request;
   interface Vector#(1,MemReadClient#(DataBusWidth)) dmaClient;
endinterface

interface ReadTestIndication;
   method Action readDone(Bit#(32) mismatchCount);
endinterface

module mkReadTest#(ReadTestIndication indication) (ReadTest);

   Reg#(SGLId)   pointer <- mkReg(0);
   Reg#(Bit#(32))       numBytes <- mkReg(0);
   Reg#(Bit#(BurstLenSize)) burstLenBytes <- mkReg(0);
   Reg#(Bit#(32))  itersToFinish <- mkReg(0);
   Reg#(Bit#(32))   itersToStart <- mkReg(0);
   Reg#(Bit#(32))        wordsRead <- mkReg(0);
   Reg#(Bit#(32)) mismatchCounts <- mkReg(0);
   MemreadEngine#(DataBusWidth,1,1)        re <- mkMemreadEngine;
   FIFO#(Bit#(32)) checkDoneFifo <- mkFIFO();

   rule start (itersToStart > 0);
      $display("Test: request.put");
      re.read_servers[0].cmdServer.request.put(MemengineCmd{sglId:pointer, base:0, len:numBytes, burstLen:burstLenBytes});
      itersToStart <= itersToStart-1;
   endrule

   rule check;
      let v <- toGet(re.read_servers[0].dataPipe).get;
      let rval = wordsRead/4;
      let expectedV = {rval+1,rval};
      let misMatch = v != expectedV;
      mismatchCounts <= mismatchCounts + (misMatch ? 1 : 0);
      let new_wordsRead = wordsRead + fromInteger(valueOf(DataBusWidth))/8;
      //$display("Test: check new=%x numBytes=%x wordsRead=%x misMatch=%x read=%x expect=%x", new_wordsRead, numBytes, wordsRead, misMatch, v, expectedV);
      if (new_wordsRead >= truncate(numBytes)) begin
	 new_wordsRead = 0;
	 checkDoneFifo.enq(mismatchCounts);
      end
      wordsRead <= new_wordsRead;
   endrule

   rule finish if (itersToFinish > 0);
      $display("Test: response.get itersToFinish %x", itersToFinish);
      let mc <- toGet(checkDoneFifo).get();
      let rv <- re.read_servers[0].cmdServer.response.get;
      if (itersToFinish == 1) begin
	 indication.readDone(mismatchCounts);
      end
      itersToFinish <= itersToFinish - 1;
   endrule

   interface dmaClient = vec(re.dmaClient);
   interface ReadTestRequest request;
      method Action startRead(Bit#(32) rp, Bit#(32) nb, Bit#(32) bl, Bit#(32) ic) if (itersToStart == 0 && itersToFinish == 0);
         $display("startRead pointer=%x numBytes %x burstLen %x iteration %x", rp, nb, bl, ic);
	 pointer <= rp;
	 numBytes  <= nb;
	 burstLenBytes  <= truncate(bl);
	 itersToFinish <= ic;
	 itersToStart <= ic;
	 mismatchCounts <= 0;
	 wordsRead <= 0;
      endmethod
   endinterface
endmodule


fix initialization of GotohB

fix initialization of GotohB

// Copyright (c) 2014 Quanta Research Cambridge, Inc.

// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

import FIFO::*;
import FIFOF::*;
import SpecialFIFOs::*;
import GetPut::*;
import StmtFSM::*;
//import Vector::*;
import BRAM::*;
//import Gearbox::*;
import Connectable::*;

//import AxiMasterSlave::*;
import Dma::*;
import DmaUtils::*;
import Dma2BRAM::*;

// algorithm
import GotohB::*;
import GotohC::*;

interface SmithwatermanRequest;
   method Action setupA(Bit#(32) strPointer, Bit#(32) strOffset, Bit#(32) strLen);
   method Action setupB(Bit#(32) strPointer, Bit#(32) strOffset, Bit#(32) strLen);
   method Action start(Bit#(32) alg);
endinterface

interface SmithwatermanIndication;
   method Action searchResult(Bit#(32) v);
   method Action setupAComplete();
   method Action setupBComplete();
endinterface

typedef Bit#(64) DWord;
typedef Bit#(32) Word;

typedef 16384 MaxStringLen;
typedef 16384 MaxFetchLen;
typedef TLog#(MaxStringLen) StringIdxWidth;
typedef Bit#(StringIdxWidth) StringIdx;
typedef TLog#(MaxFetchLen) LIdxWidth;
typedef Bit#(LIdxWidth) LIdx;

module mkSmithwatermanRequest#(SmithwatermanIndication indication,
			ObjectReadServer#(busWidth)   setupA_read_server,
			ObjectReadServer#(busWidth)   setupB_read_server)(SmithwatermanRequest)

   provisos(Add#(a__, 8, busWidth),
	    Div#(busWidth,8,nc),
	    Mul#(nc,8,busWidth),
	    Add#(1, b__, nc),
	    Add#(c__, 32, busWidth),
	    Add#(1, d__, TDiv#(busWidth, 32)),
	    Mul#(TDiv#(busWidth, 32), 32, busWidth),
            Mul#(TDiv#(busWidth, 16), 16, busWidth),
            Add#(1, e__, TDiv#(busWidth, 16)),
            Add#(1, f__, TMul#(2, TDiv#(busWidth, 16))),
            Add#(TDiv#(busWidth, 16), g__, TMul#(2, TDiv#(busWidth, 16))));

  Reg#(Bit#(14)) aLenReg <- mkReg(0);
  Reg#(Bit#(14)) bLenReg <- mkReg(0);
  Reg#(Bit#(14)) rLenReg <- mkReg(0);
   BRAM2Port#(StringIdx, Bit#(8)) strA  <- mkBRAM2Server(defaultValue);
   BRAM2Port#(StringIdx, Bit#(8)) strB <- mkBRAM2Server(defaultValue);
   BRAM2Port#(LIdx, Bit#(16)) cc <- mkBRAM2Server(defaultValue);
   BRAM2Port#(LIdx, Bit#(16)) dd <- mkBRAM2Server(defaultValue);
   BRAM2Port#(LIdx, Bit#(16)) rr <- mkBRAM2Server(defaultValue);
   BRAM2Port#(LIdx, Bit#(16)) ss <- mkBRAM2Server(defaultValue);

   BRAMReadClient#(StringIdxWidth,busWidth) n2a <- mkBRAMReadClient(strA.portB);
   mkConnection(n2a.dmaClient, setupA_read_server);
   BRAMReadClient#(StringIdxWidth,busWidth) n2b <- mkBRAMReadClient(strB.portB);
   mkConnection(n2b.dmaClient, setupB_read_server);

   Reg#(Bool) gotohCRunning <- mkReg(False);

   GotohAlgorithm cgotohB1 <- mkGotohB(strA.portA, strB.portA, cc.portA, dd.portA, 1);
   GotohAlgorithm cgotohB0 <- mkGotohB(strA.portA, strB.portA, rr.portA, ss.porta, 0);
   SWAlgorithm gotohC <- mkGotohC(strA.portA, strB.portA, cgotohB0, cgotohB1, cc.portB, dd.portB, rr.portB, ss.portB);
   // create BRAM Write client for matL

   rule finish_setupA;
      $display("finish setupA");
      let x <- n2a.finish;
      indication.setupAComplete();
   endrule

   rule finish_setupB;
      $display("finish setupB");
      let x <- n2b.finish;
      indication.setupBComplete();
   endrule

   rule gotohC_completion (gotohCRunning && gotohC.fsm.done);
      gotohCRunning <= False;
      indication.searchResult(pack(zeroExtend(gotohC.result())));
      endrule

   method Action setupA(Bit#(32) strPointer, Bit#(32) strOffset, Bit#(32) strLen);
      aLenReg <= truncate(strLen);
      $display("setupA %h %h %d", strPointer, strOffset, strLen);
      n2a.start(strPointer, 0, pack(truncate(strOffset)), pack(truncate(strOffset + strLen-1)));
      gotohC.setupA(truncate(strOffset), pack(truncate(strLen)));
   endmethod

   method Action setupB(Bit#(32) strPointer, Bit#(32) strOffset, Bit#(32) strLen);
      bLenReg <= truncate(strLen);
      $display("setupB %h %h %d", strPointer, strOffset, strLen);
      n2b.start(strPointer, 0, pack(truncate(strOffset)), pack(truncate(strOffset + strLen-1)));
      gotohC.setupB(truncate(strOffset), pack(truncate(strLen)));
   endmethod

   method Action start(Bit#(32) alg);
      $display ("start %d", alg);
      case (alg)
	 3: begin
	       gotohC.fsm.start();
	       gotohCRunning <= True;
	    end
      endcase
   endmethod

endmodule

// Copyright (c) 2014 Quanta Research Cambridge, Inc.

// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

import FIFO::*;
import FIFOF::*;
import SpecialFIFOs::*;
import GetPut::*;
import StmtFSM::*;
//import Vector::*;
import BRAM::*;
//import Gearbox::*;
import Connectable::*;

//import AxiMasterSlave::*;
import Dma::*;
import DmaUtils::*;
import Dma2BRAM::*;

// algorithm
import GotohB::*;
import GotohC::*;

interface SmithwatermanRequest;
   method Action setupA(Bit#(32) strPointer, Bit#(32) strOffset, Bit#(32) strLen);
   method Action setupB(Bit#(32) strPointer, Bit#(32) strOffset, Bit#(32) strLen);
   method Action start(Bit#(32) alg);
endinterface

interface SmithwatermanIndication;
   method Action searchResult(Bit#(32) v);
   method Action setupAComplete();
   method Action setupBComplete();
endinterface

typedef Bit#(64) DWord;
typedef Bit#(32) Word;

typedef 16384 MaxStringLen;
typedef 16384 MaxFetchLen;
typedef TLog#(MaxStringLen) StringIdxWidth;
typedef Bit#(StringIdxWidth) StringIdx;
typedef TLog#(MaxFetchLen) LIdxWidth;
typedef Bit#(LIdxWidth) LIdx;

module mkSmithwatermanRequest#(SmithwatermanIndication indication,
			ObjectReadServer#(busWidth)   setupA_read_server,
			ObjectReadServer#(busWidth)   setupB_read_server)(SmithwatermanRequest)

   provisos(Add#(a__, 8, busWidth),
	    Div#(busWidth,8,nc),
	    Mul#(nc,8,busWidth),
	    Add#(1, b__, nc),
	    Add#(c__, 32, busWidth),
	    Add#(1, d__, TDiv#(busWidth, 32)),
	    Mul#(TDiv#(busWidth, 32), 32, busWidth),
            Mul#(TDiv#(busWidth, 16), 16, busWidth),
            Add#(1, e__, TDiv#(busWidth, 16)),
            Add#(1, f__, TMul#(2, TDiv#(busWidth, 16))),
            Add#(TDiv#(busWidth, 16), g__, TMul#(2, TDiv#(busWidth, 16))));

  Reg#(Bit#(14)) aLenReg <- mkReg(0);
  Reg#(Bit#(14)) bLenReg <- mkReg(0);
  Reg#(Bit#(14)) rLenReg <- mkReg(0);
   BRAM2Port#(StringIdx, Bit#(8)) strA  <- mkBRAM2Server(defaultValue);
   BRAM2Port#(StringIdx, Bit#(8)) strB <- mkBRAM2Server(defaultValue);
   BRAM2Port#(LIdx, Bit#(16)) cc <- mkBRAM2Server(defaultValue);
   BRAM2Port#(LIdx, Bit#(16)) dd <- mkBRAM2Server(defaultValue);
   BRAM2Port#(LIdx, Bit#(16)) rr <- mkBRAM2Server(defaultValue);
   BRAM2Port#(LIdx, Bit#(16)) ss <- mkBRAM2Server(defaultValue);

   BRAMReadClient#(StringIdxWidth,busWidth) n2a <- mkBRAMReadClient(strA.portB);
   mkConnection(n2a.dmaClient, setupA_read_server);
   BRAMReadClient#(StringIdxWidth,busWidth) n2b <- mkBRAMReadClient(strB.portB);
   mkConnection(n2b.dmaClient, setupB_read_server);

   Reg#(Bool) gotohCRunning <- mkReg(False);

   GotohAlgorithm cgotohB1 <- mkGotohB(strA.portA, strB.portA, matL0.portA, 1);
   GotohAlgorithm cgotohB0 <- mkGotohB(strA.portA, strB.portA, matL1.portA, 0);
   SWAlgorithm gotohC <- mkGotohC(strA.portA, strB.portA, cgotohB0, cgotohB1, cc.portB, dd.portB, rr.portB, ss.portB);
   // create BRAM Write client for matL

   rule finish_setupA;
      $display("finish setupA");
      let x <- n2a.finish;
      indication.setupAComplete();
   endrule

   rule finish_setupB;
      $display("finish setupB");
      let x <- n2b.finish;
      indication.setupBComplete();
   endrule

   rule gotohC_completion (gotohCRunning && gotohC.fsm.done);
      gotohCRunning <= False;
      indication.searchResult(pack(zeroExtend(gotohC.result())));
      endrule

   method Action setupA(Bit#(32) strPointer, Bit#(32) strOffset, Bit#(32) strLen);
      aLenReg <= truncate(strLen);
      $display("setupA %h %h %d", strPointer, strOffset, strLen);
      n2a.start(strPointer, 0, pack(truncate(strOffset)), pack(truncate(strOffset + strLen-1)));
      gotohC.setupA(truncate(strOffset), pack(truncate(strLen)));
   endmethod

   method Action setupB(Bit#(32) strPointer, Bit#(32) strOffset, Bit#(32) strLen);
      bLenReg <= truncate(strLen);
      $display("setupB %h %h %d", strPointer, strOffset, strLen);
      n2b.start(strPointer, 0, pack(truncate(strOffset)), pack(truncate(strOffset + strLen-1)));
      gotohC.setupB(truncate(strOffset), pack(truncate(strLen)));
   endmethod

   method Action start(Bit#(32) alg);
      $display ("start %d", alg);
      case (alg)
	 3: begin
	       gotohC.fsm.start();
	       gotohCRunning <= True;
	    end
      endcase
   endmethod

endmodule