yet another missing proviso that leaked out of something

// Copyright (c) 2015 Connectal Project

// 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 Vector::*;
import FIFO::*;
import FIFOF::*;
import GetPut::*;

import MemTypes::*;

`ifdef SIM_DMA_READ_LATENCY
typedef `SIM_DMA_READ_LATENCY SimDmaReadLatency;
`else
typedef 150 SimDmaReadLatency;
`endif
`ifdef SIM_DMA_WRITE_LATENCY
typedef `SIM_DMA_WRITE_LATENCY SimDmaWriteLatency;
`else
typedef 150 SimDmaWriteLatency;
`endif

interface SimDma#(numeric type dataWidth);
   method Action init(Bit#(32) id, Bit#(32) handle, Bit#(32) size);
   method Action initfd(Bit#(32) id, Bit#(32) fd);
   method Action idreturn(Bit#(32) id);
   method Action write(Bit#(32) handle, Bit#(32) addr, Bit#(dataWidth) v, Bit#(TDiv#(dataWidth,8)) byteEnable);
   method Action readrequest(Bit#(32) handle, Bit#(32) addr);
   method ActionValue#(Bit#(dataWidth)) readresponse();
endinterface

`ifdef BSIM
import "BDPI" function ActionValue#(Bit#(32)) simDma_init(Bit#(32) id, Bit#(32) handle, Bit#(32) size);
import "BDPI" function ActionValue#(Bit#(32)) simDma_initfd(Bit#(32) id, Bit#(32) fd);
import "BDPI" function ActionValue#(Bit#(32)) simDma_idreturn(Bit#(32) id);

// implemented in BsimDma.cpp
import "BDPI" function Action write_simDma32(Bit#(32) handle, Bit#(32) addr, Bit#(32) v, Bit#(4) byteEnable);
import "BDPI" function Action write_simDma64(Bit#(32) handle, Bit#(32) addr, Bit#(64) v, Bit#(8) byteEnable);
import "BDPI" function ActionValue#(Bit#(32)) read_simDma32(Bit#(32) handle, Bit#(32) addr);
import "BDPI" function ActionValue#(Bit#(64)) read_simDma64(Bit#(32) handle, Bit#(32) addr);

module mkSimDma(SimDma#(dataWidth) ifc)
   provisos (Mul#(TDiv#(dataWidth, 32), 32, dataWidth),
	     Bits#(Vector#(TDiv#(dataWidth, 32), Bit#(4)), TDiv#(dataWidth, 8))
	     );
   FIFO#(Bit#(dataWidth)) dataFifo <- mkFIFO();
      method Action init(Bit#(32) id, Bit#(32) handle, Bit#(32) size);
	 let v <- simDma_init(id, handle, size);
	 //return v;
      endmethod
      method Action initfd(Bit#(32) id, Bit#(32) fd);
	 let v <- simDma_initfd(id, fd);
	 //return v;
      endmethod
      method Action idreturn(Bit#(32) id);
	 let v <- simDma_idreturn(id);
	 //return v;
      endmethod
      method Action write(Bit#(32) handle, Bit#(32) addr, Bit#(dataWidth) v, Bit#(TDiv#(dataWidth,8)) byteEnable);
	  Vector#(TDiv#(dataWidth, 32), Bit#(32)) vs = unpack(v);
	  Vector#(TDiv#(dataWidth, 32), Bit#(4)) byteEnables = unpack(byteEnable);
	  function Action write32(Tuple3#(Integer,Bit#(32),Bit#(4)) tpl);
	     action
		match { .i, .vv, .byteEnable } = tpl;
		write_simDma32(handle, addr+4*fromInteger(i), vv, byteEnable);
	     endaction
	  endfunction
	  mapM_(write32, zip3(genVector(), vs, byteEnables));
      endmethod
      method Action  readrequest(Bit#(32) handle, Bit#(32) addr);
	  function ActionValue#(Bit#(32)) read32(Integer i);
	     actionvalue
		let v <- read_simDma32(handle, addr+4*fromInteger(i));
		return v;
	     endactionvalue
	  endfunction
   	  Vector#(TDiv#(dataWidth,32),Bit#(32)) vs <- mapM(read32, genVector());
	  dataFifo.enq(pack(vs));
      endmethod
      method ActionValue#(Bit#(dataWidth)) readresponse();
          let v <- toGet(dataFifo).get();
	  return v;
      endmethod
endmodule
`endif

`ifdef XSIM
interface XsimDmaReadWrite;
   method Action init(Bit#(32) id, Bit#(32) handle, Bit#(32) size);
   method Action initfd(Bit#(32) id, Bit#(32) fd);
   method Action idreturn(Bit#(32) id);
   method Action write32(Bit#(32) handle, Bit#(32) addr, Bit#(32) v, Bit#(4) byteEnable);
   method Action readrequest(Bit#(32) handle, Bit#(32) addr);
   method ActionValue#(Bit#(32)) readresponse();
endinterface

import "BVI" XsimDmaReadWrite =
module mkXsimReadWrite(XsimDmaReadWrite);
   method init(init_id, init_handle, init_size) enable (en_init);
   method initfd(initfd_id, initfd_fd) enable (en_initfd);
   method idreturn(idreturn_id) enable (en_idreturn);
   method write32(write32_handle, write32_addr, write32_data, write32_byteenable) enable (en_write32);
   method readrequest(readrequest_handle, readrequest_addr) enable (en_readrequest) ready (rdy_readrequest);
   method readresponse_data readresponse() enable (en_readresponse) ready (rdy_readresponse);
   schedule (init, initfd, write32, readrequest, readresponse, idreturn) CF (init, initfd, write32, readrequest, readresponse, idreturn);
endmodule

module mkSimDma(SimDma#(dataWidth) ifc)
   provisos (Mul#(TDiv#(dataWidth, 32), 32, dataWidth),
	     Bits#(Vector#(TDiv#(dataWidth, 32), Bit#(4)), TDiv#(dataWidth, 8)));
   Vector#(TDiv#(dataWidth,32),XsimDmaReadWrite) rws <- replicateM(mkXsimReadWrite());
   method Action init(Bit#(32) id, Bit#(32) handle, Bit#(32) size);
      rws[0].init(id, handle, size);
   endmethod
   method Action initfd(Bit#(32) id, Bit#(32) fd);
      rws[0].initfd(id, fd);
   endmethod
   method Action idreturn(Bit#(32) id);
      rws[0].idreturn(id);
   endmethod
   method Action write(Bit#(32) handle, Bit#(32) addr, Bit#(dataWidth) v, Bit#(TDiv#(dataWidth,8)) byteEnable);
      Vector#(TDiv#(dataWidth, 32), Bit#(32)) vs = unpack(v);
      Vector#(TDiv#(dataWidth, 32), Bit#(4)) byteEnables = unpack(byteEnable);
      function Action write32(Tuple3#(Integer,Bit#(32),Bit#(4)) tpl);
	 action
	    match { .i, .vv, .byteEnable } = tpl;
	    rws[i].write32(handle, addr+4*fromInteger(i), vv, byteEnable);
	 endaction
      endfunction
      mapM_(write32, zip3(genVector(), vs, byteEnables));
   endmethod
   method Action readrequest(Bit#(32) handle, Bit#(32) addr);
      function Action doreadrequest(Integer i);
	 action
	    rws[i].readrequest(handle, addr+4*fromInteger(i));
	 endaction
      endfunction
      Vector#(TDiv#(dataWidth,32),Integer) indexes = genVector();
      mapM_(doreadrequest, indexes);
   endmethod
   method ActionValue#(Bit#(dataWidth)) readresponse();
      function ActionValue#(Bit#(32)) readresponse32(Integer i);
	 actionvalue
	    let v <- rws[i].readresponse();
	    return v;
	 endactionvalue
      endfunction
      Vector#(TDiv#(dataWidth,32),Bit#(32)) vs <- mapM(readresponse32, genVector());
      return pack(vs);
   endmethod
endmodule
`endif

`ifndef BSIM
`ifndef XSIM
module mkSimDma(SimDma#(dataWidth) ifc);
   method Action init(Bit#(32) id, Bit#(32) handle, Bit#(32) size);
   endmethod
   method Action initfd(Bit#(32) id, Bit#(32) fd);
   endmethod
   method Action idreturn(Bit#(32) id);
   endmethod
   method Action write(Bit#(32) handle, Bit#(32) addr, Bit#(dataWidth) v, Bit#(TDiv#(dataWidth,8)) byteEnable);
   endmethod
   method Action readrequest(Bit#(32) handle, Bit#(32) addr);
   endmethod
   method ActionValue#(Bit#(dataWidth)) readresponse();
      return 0;
   endmethod
endmodule
`endif
`endif

module mkSimDmaDmaMaster(PhysMemSlave#(serverAddrWidth,serverBusWidth))
   provisos(Div#(serverBusWidth,8,dataWidthBytes),
	    Mul#(dataWidthBytes,8,serverBusWidth),
	    Log#(dataWidthBytes,beatShift),
	    Mul#(TDiv#(serverBusWidth, 32), 32, serverBusWidth),
	    Mul#(TDiv#(serverBusWidth, 32), 4, TDiv#(serverBusWidth, 8)),
	    Bits#(Tuple2#(Bit#(64), PhysMemRequest#(serverAddrWidth,serverBusWidth)), a__),
	    Add#(b__, ByteEnableSize, TDiv#(serverBusWidth, 8))
	    );

   let verbose = False;
   SimDma#(serverBusWidth) rw <- mkSimDma();

   Reg#(Bit#(BurstLenSize))  readLenReg <- mkReg(0);
   Reg#(Bit#(32))         readOffsetReg <- mkReg(0);

   Reg#(Bit#(BurstLenSize))  writeLenReg <- mkReg(0);
   Reg#(Bit#(32))         writeOffsetReg <- mkReg(0);

   let readLatency_I = valueOf(SimDmaReadLatency);
   let writeLatency_I = valueOf(SimDmaWriteLatency);

   Bit#(64) readLatency = fromInteger(readLatency_I);
   Bit#(64) writeLatency = fromInteger(writeLatency_I);

   Reg#(Bit#(64)) req_ar_b_ts <- mkReg(0);
   Reg#(Bit#(64)) req_aw_b_ts <- mkReg(0);
   Reg#(Bit#(64)) cycles <- mkReg(0);
   Reg#(Bit#(64)) last_reqAr <- mkReg(0);
   Reg#(Bit#(64)) last_read_eob <- mkReg(0);
   Reg#(Bit#(64)) last_write_eob <- mkReg(0);

   FIFOF#(Tuple2#(Bit#(64), PhysMemRequest#(serverAddrWidth,serverBusWidth)))  readDelayFifo <- mkSizedFIFOF(readLatency_I);
   FIFOF#(Tuple2#(Bit#(64),PhysMemRequest#(serverAddrWidth,serverBusWidth))) writeDelayFifo <- mkSizedFIFOF(writeLatency_I);

   FIFOF#(Tuple2#(Bit#(64), Bit#(MemTagSize))) bFifo <- mkSizedFIFOF(writeLatency_I);
   FIFOF#(Tuple2#(Bit#(MemTagSize),Bool)) taglastfifo <- mkFIFOF();
   rule increment_cycle;
      cycles <= cycles+1;
   endrule

   let read_jitter = True; //cycles[4:0] == 0;
   let write_jitter = True; //cycles[4:0] == 5;

   Reg#(Bit#(8))  burstReg <- mkReg(0);
   FIFO#(Bit#(8)) reqs <- mkSizedFIFO(32);

   let beat_shift = fromInteger(valueOf(beatShift));

   rule read_rule if (readDelayFifo.notEmpty() && (cycles-tpl_1(readDelayFifo.first) >= readLatency));
	 match { .reqTime, .req } = readDelayFifo.first;
	 Bit#(BurstLenSize) readLen = readLenReg;
	 Bit#(32) readOffset = readOffsetReg;
	 Bit#(MemTagSize) tag = req.tag;
	 Bit#(8) handle = req.addr[39:32];

	 if (readLen == 0) begin
	    req_ar_b_ts <= cycles;
	    readLen     = req.burstLen>>beat_shift;
	    readOffset  = 0;
	 end
	 rw.readrequest(extend(handle), req.addr[31:0]+readOffset);
	 let last = (readLen == 1);
	 if (last)
	    readDelayFifo.deq();
	 taglastfifo.enq(tuple2(tag, last));
	 readLenReg <= readLen - 1;
	 readOffsetReg <= readOffset + fromInteger(valueOf(serverBusWidth)/8);
   endrule

   interface PhysMemReadServer read_server;
      interface Put readReq;
	 method Action put(PhysMemRequest#(serverAddrWidth,serverBusWidth) req);
            if (verbose) $display("mkSimDmaDmaMaster::%d axiSlave.read.readAddr %h bc %d", cycles, req.addr, req.burstLen);
	    //readAddrGenerator.request.put(req);
	    readDelayFifo.enq(tuple2(cycles,req));
	 endmethod
      endinterface
      interface Get readData;
	 method ActionValue#(MemData#(serverBusWidth)) get();
	     match { .tag, .last } <- toGet(taglastfifo).get();
 	     let v <- rw.readresponse();
 	     //if (verbose) $display("mkSimDmaDmaMaster::%d axiSlave.read.readData %h tag %d last %d", cycles, v, tag, last);
	     return MemData { data: v, tag: tag, last: last };
	 endmethod
      endinterface
   endinterface
   interface PhysMemWriteServer write_server;
      interface Put writeReq;
	 method Action put(PhysMemRequest#(serverAddrWidth,serverBusWidth) req);
	 //$display("mkSimDmaDmaMaster::req_aw id=%d", req.tag);
	 writeDelayFifo.enq(tuple2(cycles,req));
	 endmethod
      endinterface
      interface Put writeData;
	 method Action put(MemData#(serverBusWidth) resp) if (writeDelayFifo.notEmpty && (cycles-tpl_1(writeDelayFifo.first)) >= writeLatency);
	    match { .reqTime, .req } = writeDelayFifo.first;
	    Bit#(BurstLenSize) writeLen = writeLenReg;
	    Bit#(32) writeOffset = writeOffsetReg;
	    Bit#(MemTagSize) tag = req.tag;
	    Bit#(8) handle = req.addr[39:32];
	    Bit#(ByteEnableSize) byteEnable = maxBound;
`ifdef BYTE_ENABLES
	    if (writeLen == 1) byteEnable = req.lastbe;
`endif
	    if (writeLenReg == 0) begin
	       req_aw_b_ts <= cycles;
	       writeLen = req.burstLen>>beat_shift;
	       writeOffset = 0;
`ifdef BYTE_ENABLES
	       byteEnable = req.firstbe;
`endif
	    end
	    rw.write(extend(handle), req.addr[31:0] + writeOffset, resp.data, extend(byteEnable));
	    writeLenReg <= writeLen - 1;
	    writeOffsetReg <= writeOffset + fromInteger(valueOf(serverBusWidth)/8);
	    if (writeLen == 1) begin
	       bFifo.enq(tuple2(cycles,tag));
	       writeDelayFifo.deq;
	    end
	 endmethod
      endinterface
      interface Get writeDone;
	 method ActionValue#(Bit#(MemTagSize)) get() if ((cycles-tpl_1(bFifo.first)) >= writeLatency);
	 bFifo.deq();
	 return tpl_2(bFifo.first());
	 endmethod
      endinterface
   endinterface
endmodule

// Copyright (c) 2015 Connectal Project

// 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 Vector::*;
import FIFO::*;
import FIFOF::*;
import GetPut::*;

import MemTypes::*;

`ifdef SIM_DMA_READ_LATENCY
typedef `SIM_DMA_READ_LATENCY SimDmaReadLatency;
`else
typedef 150 SimDmaReadLatency;
`endif
`ifdef SIM_DMA_WRITE_LATENCY
typedef `SIM_DMA_WRITE_LATENCY SimDmaWriteLatency;
`else
typedef 150 SimDmaWriteLatency;
`endif

interface SimDma#(numeric type dataWidth);
   method Action init(Bit#(32) id, Bit#(32) handle, Bit#(32) size);
   method Action initfd(Bit#(32) id, Bit#(32) fd);
   method Action idreturn(Bit#(32) id);
   method Action write(Bit#(32) handle, Bit#(32) addr, Bit#(dataWidth) v, Bit#(TDiv#(dataWidth,8)) byteEnable);
   method Action readrequest(Bit#(32) handle, Bit#(32) addr);
   method ActionValue#(Bit#(dataWidth)) readresponse();
endinterface

`ifdef BSIM
import "BDPI" function ActionValue#(Bit#(32)) simDma_init(Bit#(32) id, Bit#(32) handle, Bit#(32) size);
import "BDPI" function ActionValue#(Bit#(32)) simDma_initfd(Bit#(32) id, Bit#(32) fd);
import "BDPI" function ActionValue#(Bit#(32)) simDma_idreturn(Bit#(32) id);

// implemented in BsimDma.cpp
import "BDPI" function Action write_simDma32(Bit#(32) handle, Bit#(32) addr, Bit#(32) v, Bit#(4) byteEnable);
import "BDPI" function Action write_simDma64(Bit#(32) handle, Bit#(32) addr, Bit#(64) v, Bit#(8) byteEnable);
import "BDPI" function ActionValue#(Bit#(32)) read_simDma32(Bit#(32) handle, Bit#(32) addr);
import "BDPI" function ActionValue#(Bit#(64)) read_simDma64(Bit#(32) handle, Bit#(32) addr);

module mkSimDma(SimDma#(dataWidth) ifc)
   provisos (Mul#(TDiv#(dataWidth, 32), 32, dataWidth),
	     Bits#(Vector#(TDiv#(dataWidth, 32), Bit#(4)), TDiv#(dataWidth, 8))
	     );
   FIFO#(Bit#(dataWidth)) dataFifo <- mkFIFO();
      method Action init(Bit#(32) id, Bit#(32) handle, Bit#(32) size);
	 let v <- simDma_init(id, handle, size);
	 //return v;
      endmethod
      method Action initfd(Bit#(32) id, Bit#(32) fd);
	 let v <- simDma_initfd(id, fd);
	 //return v;
      endmethod
      method Action idreturn(Bit#(32) id);
	 let v <- simDma_idreturn(id);
	 //return v;
      endmethod
      method Action write(Bit#(32) handle, Bit#(32) addr, Bit#(dataWidth) v, Bit#(TDiv#(dataWidth,8)) byteEnable);
	  Vector#(TDiv#(dataWidth, 32), Bit#(32)) vs = unpack(v);
	  Vector#(TDiv#(dataWidth, 32), Bit#(4)) byteEnables = unpack(byteEnable);
	  function Action write32(Tuple3#(Integer,Bit#(32),Bit#(4)) tpl);
	     action
		match { .i, .vv, .byteEnable } = tpl;
		write_simDma32(handle, addr+4*fromInteger(i), vv, byteEnable);
	     endaction
	  endfunction
	  mapM_(write32, zip3(genVector(), vs, byteEnables));
      endmethod
      method Action  readrequest(Bit#(32) handle, Bit#(32) addr);
	  function ActionValue#(Bit#(32)) read32(Integer i);
	     actionvalue
		let v <- read_simDma32(handle, addr+4*fromInteger(i));
		return v;
	     endactionvalue
	  endfunction
   	  Vector#(TDiv#(dataWidth,32),Bit#(32)) vs <- mapM(read32, genVector());
	  dataFifo.enq(pack(vs));
      endmethod
      method ActionValue#(Bit#(dataWidth)) readresponse();
          let v <- toGet(dataFifo).get();
	  return v;
      endmethod
endmodule
`endif

`ifdef XSIM
interface XsimDmaReadWrite;
   method Action init(Bit#(32) id, Bit#(32) handle, Bit#(32) size);
   method Action initfd(Bit#(32) id, Bit#(32) fd);
   method Action idreturn(Bit#(32) id);
   method Action write32(Bit#(32) handle, Bit#(32) addr, Bit#(32) v, Bit#(4) byteEnable);
   method Action readrequest(Bit#(32) handle, Bit#(32) addr);
   method ActionValue#(Bit#(32)) readresponse();
endinterface

import "BVI" XsimDmaReadWrite =
module mkXsimReadWrite(XsimDmaReadWrite);
   method init(init_id, init_handle, init_size) enable (en_init);
   method initfd(initfd_id, initfd_fd) enable (en_initfd);
   method idreturn(idreturn_id) enable (en_idreturn);
   method write32(write32_handle, write32_addr, write32_data, write32_byteenable) enable (en_write32);
   method readrequest(readrequest_handle, readrequest_addr) enable (en_readrequest) ready (rdy_readrequest);
   method readresponse_data readresponse() enable (en_readresponse) ready (rdy_readresponse);
   schedule (init, initfd, write32, readrequest, readresponse, idreturn) CF (init, initfd, write32, readrequest, readresponse, idreturn);
endmodule

module mkSimDma(SimDma#(dataWidth) ifc)
   provisos (Mul#(TDiv#(dataWidth, 32), 32, dataWidth),
	     Bits#(Vector#(TDiv#(dataWidth, 32), Bit#(4)), TDiv#(dataWidth, 8)));
   Vector#(TDiv#(dataWidth,32),XsimDmaReadWrite) rws <- replicateM(mkXsimReadWrite());
   method Action init(Bit#(32) id, Bit#(32) handle, Bit#(32) size);
      rws[0].init(id, handle, size);
   endmethod
   method Action initfd(Bit#(32) id, Bit#(32) fd);
      rws[0].initfd(id, fd);
   endmethod
   method Action idreturn(Bit#(32) id);
      rws[0].idreturn(id);
   endmethod
   method Action write(Bit#(32) handle, Bit#(32) addr, Bit#(dataWidth) v, Bit#(TDiv#(dataWidth,8)) byteEnable);
      Vector#(TDiv#(dataWidth, 32), Bit#(32)) vs = unpack(v);
      Vector#(TDiv#(dataWidth, 32), Bit#(4)) byteEnables = unpack(byteEnable);
      function Action write32(Tuple3#(Integer,Bit#(32),Bit#(4)) tpl);
	 action
	    match { .i, .vv, .byteEnable } = tpl;
	    rws[i].write32(handle, addr+4*fromInteger(i), vv, byteEnable);
	 endaction
      endfunction
      mapM_(write32, zip3(genVector(), vs, byteEnables));
   endmethod
   method Action readrequest(Bit#(32) handle, Bit#(32) addr);
      function Action doreadrequest(Integer i);
	 action
	    rws[i].readrequest(handle, addr+4*fromInteger(i));
	 endaction
      endfunction
      Vector#(TDiv#(dataWidth,32),Integer) indexes = genVector();
      mapM_(doreadrequest, indexes);
   endmethod
   method ActionValue#(Bit#(dataWidth)) readresponse();
      function ActionValue#(Bit#(32)) readresponse32(Integer i);
	 actionvalue
	    let v <- rws[i].readresponse();
	    return v;
	 endactionvalue
      endfunction
      Vector#(TDiv#(dataWidth,32),Bit#(32)) vs <- mapM(readresponse32, genVector());
      return pack(vs);
   endmethod
endmodule
`endif

`ifndef BSIM
`ifndef XSIM
module mkSimDma(SimDma#(dataWidth) ifc);
   method Action init(Bit#(32) id, Bit#(32) handle, Bit#(32) size);
   endmethod
   method Action initfd(Bit#(32) id, Bit#(32) fd);
   endmethod
   method Action idreturn(Bit#(32) id);
   endmethod
   method Action write(Bit#(32) handle, Bit#(32) addr, Bit#(dataWidth) v, Bit#(TDiv#(dataWidth,8)) byteEnable);
   endmethod
   method Action readrequest(Bit#(32) handle, Bit#(32) addr);
   endmethod
   method ActionValue#(Bit#(dataWidth)) readresponse();
      return 0;
   endmethod
endmodule
`endif
`endif

module mkSimDmaDmaMaster(PhysMemSlave#(serverAddrWidth,serverBusWidth))
   provisos(Div#(serverBusWidth,8,dataWidthBytes),
	    Mul#(dataWidthBytes,8,serverBusWidth),
	    Log#(dataWidthBytes,beatShift),
	    Mul#(TDiv#(serverBusWidth, 32), 32, serverBusWidth),
	    Bits#(Tuple2#(Bit#(64), PhysMemRequest#(serverAddrWidth,serverBusWidth)), a__),
	    Add#(b__, ByteEnableSize, TDiv#(serverBusWidth, 8))
	    );

   let verbose = False;
   SimDma#(serverBusWidth) rw <- mkSimDma();

   Reg#(Bit#(BurstLenSize))  readLenReg <- mkReg(0);
   Reg#(Bit#(32))         readOffsetReg <- mkReg(0);

   Reg#(Bit#(BurstLenSize))  writeLenReg <- mkReg(0);
   Reg#(Bit#(32))         writeOffsetReg <- mkReg(0);

   let readLatency_I = valueOf(SimDmaReadLatency);
   let writeLatency_I = valueOf(SimDmaWriteLatency);

   Bit#(64) readLatency = fromInteger(readLatency_I);
   Bit#(64) writeLatency = fromInteger(writeLatency_I);

   Reg#(Bit#(64)) req_ar_b_ts <- mkReg(0);
   Reg#(Bit#(64)) req_aw_b_ts <- mkReg(0);
   Reg#(Bit#(64)) cycles <- mkReg(0);
   Reg#(Bit#(64)) last_reqAr <- mkReg(0);
   Reg#(Bit#(64)) last_read_eob <- mkReg(0);
   Reg#(Bit#(64)) last_write_eob <- mkReg(0);

   FIFOF#(Tuple2#(Bit#(64), PhysMemRequest#(serverAddrWidth,serverBusWidth)))  readDelayFifo <- mkSizedFIFOF(readLatency_I);
   FIFOF#(Tuple2#(Bit#(64),PhysMemRequest#(serverAddrWidth,serverBusWidth))) writeDelayFifo <- mkSizedFIFOF(writeLatency_I);

   FIFOF#(Tuple2#(Bit#(64), Bit#(MemTagSize))) bFifo <- mkSizedFIFOF(writeLatency_I);
   FIFOF#(Tuple2#(Bit#(MemTagSize),Bool)) taglastfifo <- mkFIFOF();
   rule increment_cycle;
      cycles <= cycles+1;
   endrule

   let read_jitter = True; //cycles[4:0] == 0;
   let write_jitter = True; //cycles[4:0] == 5;

   Reg#(Bit#(8))  burstReg <- mkReg(0);
   FIFO#(Bit#(8)) reqs <- mkSizedFIFO(32);

   let beat_shift = fromInteger(valueOf(beatShift));

   rule read_rule if (readDelayFifo.notEmpty() && (cycles-tpl_1(readDelayFifo.first) >= readLatency));
	 match { .reqTime, .req } = readDelayFifo.first;
	 Bit#(BurstLenSize) readLen = readLenReg;
	 Bit#(32) readOffset = readOffsetReg;
	 Bit#(MemTagSize) tag = req.tag;
	 Bit#(8) handle = req.addr[39:32];

	 if (readLen == 0) begin
	    req_ar_b_ts <= cycles;
	    readLen     = req.burstLen>>beat_shift;
	    readOffset  = 0;
	 end
	 rw.readrequest(extend(handle), req.addr[31:0]+readOffset);
	 let last = (readLen == 1);
	 if (last)
	    readDelayFifo.deq();
	 taglastfifo.enq(tuple2(tag, last));
	 readLenReg <= readLen - 1;
	 readOffsetReg <= readOffset + fromInteger(valueOf(serverBusWidth)/8);
   endrule

   interface PhysMemReadServer read_server;
      interface Put readReq;
	 method Action put(PhysMemRequest#(serverAddrWidth,serverBusWidth) req);
            if (verbose) $display("mkSimDmaDmaMaster::%d axiSlave.read.readAddr %h bc %d", cycles, req.addr, req.burstLen);
	    //readAddrGenerator.request.put(req);
	    readDelayFifo.enq(tuple2(cycles,req));
	 endmethod
      endinterface
      interface Get readData;
	 method ActionValue#(MemData#(serverBusWidth)) get();
	     match { .tag, .last } <- toGet(taglastfifo).get();
 	     let v <- rw.readresponse();
 	     //if (verbose) $display("mkSimDmaDmaMaster::%d axiSlave.read.readData %h tag %d last %d", cycles, v, tag, last);
	     return MemData { data: v, tag: tag, last: last };
	 endmethod
      endinterface
   endinterface
   interface PhysMemWriteServer write_server;
      interface Put writeReq;
	 method Action put(PhysMemRequest#(serverAddrWidth,serverBusWidth) req);
	 //$display("mkSimDmaDmaMaster::req_aw id=%d", req.tag);
	 writeDelayFifo.enq(tuple2(cycles,req));
	 endmethod
      endinterface
      interface Put writeData;
	 method Action put(MemData#(serverBusWidth) resp) if (writeDelayFifo.notEmpty && (cycles-tpl_1(writeDelayFifo.first)) >= writeLatency);
	    match { .reqTime, .req } = writeDelayFifo.first;
	    Bit#(BurstLenSize) writeLen = writeLenReg;
	    Bit#(32) writeOffset = writeOffsetReg;
	    Bit#(MemTagSize) tag = req.tag;
	    Bit#(8) handle = req.addr[39:32];
	    Bit#(ByteEnableSize) byteEnable = maxBound;
`ifdef BYTE_ENABLES
	    if (writeLen == 1) byteEnable = req.lastbe;
`endif
	    if (writeLenReg == 0) begin
	       req_aw_b_ts <= cycles;
	       writeLen = req.burstLen>>beat_shift;
	       writeOffset = 0;
`ifdef BYTE_ENABLES
	       byteEnable = req.firstbe;
`endif
	    end
	    rw.write(extend(handle), req.addr[31:0] + writeOffset, resp.data, extend(byteEnable));
	    writeLenReg <= writeLen - 1;
	    writeOffsetReg <= writeOffset + fromInteger(valueOf(serverBusWidth)/8);
	    if (writeLen == 1) begin
	       bFifo.enq(tuple2(cycles,tag));
	       writeDelayFifo.deq;
	    end
	 endmethod
      endinterface
      interface Get writeDone;
	 method ActionValue#(Bit#(MemTagSize)) get() if ((cycles-tpl_1(bFifo.first)) >= writeLatency);
	 bFifo.deq();
	 return tpl_2(bFifo.first());
	 endmethod
      endinterface
   endinterface
endmodule


compiler error fixes

compiler error fixes

// 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 FIFOF::*;
import GetPutF::*;
import PortalRMemory::*;
import RingTypes::*;
import StmtFSM::*;

// The interface to the copyengine is a pair of fifos which supply and accept
// blocks of 8 64 bit words
// A Command:
//  word 0: COPY[63:56] TAG[31:0]
//  word 1: readMemHandle[63:32]
//  word 1: readAddress[23:0]
//  word 2  writeMemHandle[63:32]
//  word 2: writeAddress[23:0]
//  word 3: bytecount[15:0]
//  word 4-7 unused
// Status
//  word0-6 all 0
//  word7  TAG[31:0]

module mkCopyEngine#(DMAReadServer#(64) copy_read_chan, DMAWriteServer#(64) copy_write_chan) ( ServerF#(Bit#(64), Bit#(64)));
   FIFOF#(Bit#(64)) f_in  <- mkSizedFIFOF(16);    // to buffer incoming requests
   FIFOF#(Bit#(64)) f_out <- mkSizedFIFOF(16);    // to buffer outgoing responses
   Reg#(Bit#(16)) copyReadCount <- mkReg(0);
   Reg#(Bit#(16)) copyWriteCount <- mkReg(0);
   Reg#(Bit#(DmaAddrSize)) copyReadAddr <- mkReg(0);
   Reg#(Bit#(DmaAddrSize)) copyWriteAddr <- mkReg(0);
   Reg#(DmaMemHandle) copyReadHandle <- mkReg(0);
   Reg#(DmaMemHandle) copyWriteHandle <- mkReg(0);
   Reg#(Bit#(32)) copyTag <- mkReg(0);
   Reg#(Bool) copyBusy <- mkReg(False);
   Stmt copyStart =
   seq
      while(True)
	 seq
	    while (copyBusy) noAction;
	    action
	       copyTag <= f_in.first()[31:0];
	       f_in.deq();  // word 0
	    endaction
	    action
	       copyReadHandle <= f_in.first()[63:32];
	       copyReadAddr <= f_in.first()[23:0];
	       f_in.deq();  // word 1
	    endaction
	    action
	       copyWriteHandle <= f_in.first()[63:32];
	       copyWriteAddr <= f_in.first()[23:0];
	       f_in.deq();  // word 2
	    endaction
	    action
	       copyReadCount <= f_in.first()[15:0];
	       copyWriteCount <= f_in.first()[15:0];
	       f_in.deq();  // word 3
	    endaction
	       f_in.deq;  // discard words 4-7
	       f_in.deq;  // discard words 4-7
	       f_in.deq;  // discard words 4-7
	       f_in.deq;  // discard words 4-7
	    copyBusy <= True;
	 endseq
   endseq;

    rule copyReadRule (copyBusy && (copyReadCount != 0));
       $display("copyRead %h, count %h", copyReadAddr, copyReadCount);
       copy_read_chan.readReq.put(DMAAddressRequest{handle: copyReadHandle, address: copyReadAddr, burstLen: 1, tag: copyReadAddr[8:3]});
       copyReadAddr <= copyReadAddr + 8;
       copyReadCount <= copyReadCount - 8;
    endrule

    rule copyReadWriteRule (copyBusy);
       let data <- copy_read_chan.readData.get;
       $display("copyReadWrite addr %h", copyWriteAddr);
       copy_write_chan.writeReq.put(DMAAddressRequest{handle: copyWriteHandle, address: copyWriteAddr, burstLen: 1, tag: copyWriteAddr[8:3]});
       copy_write_chan.writeData.put(DMAData{data: data.data, tag: copyWriteAddr[8:3]});
       copyWriteAddr <= copyWriteAddr + 8;
    endrule

   Stmt copyFinish =
   seq
      while(True)
	 seq
	    while (!copyBusy) noAction;
	    while (copyWriteCount > 0)
	       action
		  let v <- copy_write_chan.writeDone.get;
		  copyWriteCount <= copyWriteCount - 8;
	       endaction
	    f_out.enq(0);
	    f_out.enq(0);
	    f_out.enq(0);
	    f_out.enq(0);
	    f_out.enq(0);
	    f_out.enq(0);
	    f_out.enq(0);
	    f_out.enq(extend(copyTag));
	    copyBusy <= False;
	 endseq
   endseq;

   mkAutoFSM(copyStart);
   mkAutoFSM(copyFinish);

   interface PutF request = toPutF(f_in);
   interface GetF response = toGetF (f_out);

endmodule: mkCopyEngine

// 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 GetPutF::*;
import PortalRMemory::*;
import RingTypes::*;
import StmtFSM::*;

// The interface to the copyengine is a pair of fifos which supply and accept
// blocks of 8 64 bit words
// A Command:
//  word 0: COPY[63:56] TAG[31:0]
//  word 1: readMemHandle[63:32]
//  word 1: readAddress[23:0]
//  word 2  writeMemHandle[63:32]
//  word 2: writeAddress[23:0]
//  word 3: bytecount[15:0]
//  word 4-7 unused
// Status
//  word0-6 all 0
//  word7  TAG[31:0]

module mkCopyEngine#(DMAReadServer#(64) copy_read_chan, DMAWriteServer#(64) copy_write_chan) ( ServerF#(Bit#(64), Bit#(64)));
   FIFO#(Bit#(64)) f_in  <- mkSizedFIFO(16);    // to buffer incoming requests
   FIFO#(Bit#(64)) f_out <- mkSizedFIFO(16);    // to buffer outgoing responses
   Reg#(Bit#(16)) copyReadCount <- mkReg(0);
   Reg#(Bit#(16)) copyWriteCount <- mkReg(0);
   Reg#(Bit#(DmaAddrSize)) copyReadAddr <- mkReg(0);
   Reg#(Bit#(DmaAddrSize)) copyWriteAddr <- mkReg(0);
   Reg#(DmaMemHandle) copyReadHandle <- mkReg(0);
   Reg#(DmaMemHandle) copyWriteHandle <- mkReg(0);
   Reg#(Bit#(32)) copyTag <- mkReg(0);
   Reg#(Bool) copyBusy <- mkReg(False);

   Stmt copyStart =
   seq
      while(True)
	 seq
	    while (copyBusy) noAction;
	    action
	       copyTag <= f_in.first()[31:0];
	       f_in.deq();  // word 0
	    endaction
	    action
	       copyReadHandle <= f_in.first()[63:32];
	       copyReadAddr <= f_in.first()[23:0];
	       f_in.deq();  // word 1
	    endaction
	    action
	       copyWriteHandle <= f_in.first()[63:32];
	       copyWriteAddr <= f_in.first()[23:0];
	       f_in.deq();  // word 2
	    endaction
	    action
	       copyReadCount <= f_in.first()[15:0];
	       copyWriteCount <= f_in.first()[15:0];
	       f_in.deq();  // word 3
	    endaction
	    for (ii <= 4; ii < 8; ii <= ii+1)
	       f_in.deq;  // discard words 4-7
	    copyBusy <= True;
	 endseq
   endseq;

    rule copyReadRule (copyBusy && (copyReadCount != 0));
       $display("copyRead %h, count %h", copyReadAddr, copyReadCount);
       copy_read_chan.readReq.put(DMAAddressRequest{handle: copyReadHandle, address: copyReadAddr, burstLen: extend(1), tag: truncate(copyReadAddr >> 3)});
       copyReadAddr <= copyReadAddr + 8;
       copyReadCount <= copyReadCount - 8;
    endrule

    rule copyReadWriteRule (copyBusy);
       let data <- copy_read_chan.readData.get;
       $display("copyReadWrite addr %h", copyWriteAddr);
       copy_write_chan.writeReq.put(DMAAddressRequest{handle: copyWriteHandle, address: copyWriteAddr, burstLen: extend(1), tag: truncate(copyWriteAddr >> 3)});
       copy_write_chan.writeData.put(DMAData{data: data.data, tag: copyWriteAddr >> 3});
       copyWriteAddr <= copyWriteAddr + 8;
    endrule

   Stmt copyFinish =
   seq
      while(True)
	 seq
	    while (!copyBusy) noAction;
	    while (copyWriteCount > 0)
	       action
		  let v <- copy_write_chan.writeDone.get;
		  copyWriteCount <= copyWriteCount - 8;
	       endaction
	    for (ii <= 0; ii < 7; ii <= ii + 1)
	       f_out.enq(0);
	    f_out.enq(extend(copyTag));
	    copyBusy <= False;
	 endseq
   endseq;

   mkAutoFSM(copyStart);
   mkAutoFSM(copyFinish);

   interface PutF request = toPutF(f_in);
   interface GetF response = toGetF (f_out);

endmodule: mkCopyEngine