parameterize mkAxiDmaSlave over axiIdSize

// 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.
`include "ConnectalProjectConfig.bsv"
import ConnectalConfig::*;
import FIFO::*;
import GetPut::*;
import ClientServer::*;
import AxiMasterSlave::*;
import Axi4MasterSlave::*;
import ConnectalMemTypes::*;
import ConnectalMemory::*;

module mkAxiDmaSlave#(PhysMemSlave#(addrWidth,dataWidth) slave) (Axi3Slave#(addrWidth,dataWidth,axiIdSize))
       provisos (Add#(MemTagSize, sz__, axiIdSize));
   let beatShift = fromInteger(valueOf(TLog#(TDiv#(dataWidth,8))));
   interface Put req_ar;
      method Action put((Axi3ReadRequest#(addrWidth, axiIdSize)) req);
	 let burstLen = extend(req.len+1) << beatShift;
	 slave.read_server.readReq.put(PhysMemRequest{addr:req.address, burstLen:burstLen,  tag:truncate(req.id)
`ifdef BYTE_ENABLES
						      , firstbe: maxBound, lastbe: maxBound
`endif
						      });
      endmethod
   endinterface
   interface Get resp_read;
      method ActionValue#(Axi3ReadResponse#(dataWidth, axiIdSize)) get;
	 let resp <- slave.read_server.readData.get;
	 return Axi3ReadResponse{data:resp.data, resp:0, last:1, id:extend(resp.tag)};
      endmethod
   endinterface
   interface Put req_aw;
      method Action put(Axi3WriteRequest#(addrWidth, axiIdSize) req);
	 let burstLen = extend(req.len+1) << beatShift;
	 slave.write_server.writeReq.put(PhysMemRequest{addr:req.address, burstLen:burstLen, tag:truncate(req.id)
`ifdef BYTE_ENABLES
							, firstbe: maxBound, lastbe: maxBound
`endif
							});
      endmethod
   endinterface
   interface Put resp_write;
      method Action put(Axi3WriteData#(dataWidth, axiIdSize) resp);
	 slave.write_server.writeData.put(MemData{data:resp.data, tag:truncate(resp.id), last: resp.last == 1});
      endmethod
   endinterface
   interface Get resp_b;
      method ActionValue#(Axi3WriteResponse#(axiIdSize)) get;
	 let rv <- slave.write_server.writeDone.get;
	 return Axi3WriteResponse{resp:0, id:extend(rv)};
      endmethod
   endinterface
endmodule

module mkAxiDmaMaster#(PhysMemMaster#(addrWidth,dataWidth) master) (Axi3Master#(addrWidth,dataWidth,tagWidth))

   provisos(Div#(dataWidth,8,dataWidthBytes),
	    Mul#(dataWidthBytes,8,dataWidth),
	    Log#(dataWidthBytes,beatShift),
	    Add#(tagWidth,a__,MemTagSize),
	    Add#(TDiv#(dataWidth,8),b__,dataWidthBytes),
	    Bits#(Tuple3#(Bit#(8),Bit#(TDiv#(dataWidth,8)),Bit#(TDiv#(dataWidth,8))),c__));

   Reg#(Bit#(8))  burstReg <- mkReg(0);
   FIFO#(Tuple3#(Bit#(8),Bit#(TDiv#(dataWidth,8)),Bit#(TDiv#(dataWidth,8)))) reqs <- mkSizedFIFO(32);
   Reg#(Bit#(dataWidthBytes)) lastbeReg <- mkReg(maxBound);

   let beat_shift = fromInteger(valueOf(beatShift));

   interface Get req_aw;
      method ActionValue#(Axi3WriteRequest#(addrWidth,tagWidth)) get();
	 let req <- master.write_client.writeReq.get;
	 reqs.enq(tuple3(truncate(req.burstLen),reqFirstByteEnable(req),reqLastByteEnable(req)));
	 return Axi3WriteRequest{address:req.addr, len:truncate((req.burstLen>>beat_shift)-1), id:truncate(req.tag), size: axiBusSize(valueOf(dataWidth)), burst: 1, prot: 0, cache: 15, lock:0, qos:0};
      endmethod
   endinterface
   interface Get resp_write;
      method ActionValue#(Axi3WriteData#(dataWidth,tagWidth)) get();
	 let tagdata <- master.write_client.writeData.get();
	 let burstLen = burstReg;
	 Bit#(dataWidthBytes) byteEnable = extend((burstLen == 1) ? lastbeReg : maxBound);
	 if (burstLen == 0) begin
	    match { .bl, .firstbe, .lastbe } = reqs.first;
	    burstLen = bl >> beat_shift;
	    reqs.deq;
`ifdef BYTE_ENABLES
	    byteEnable = extend(firstbe);
	    lastbeReg <= lastbe;
`endif
	 end
	 burstReg <= burstLen-1;
	 Bit#(1) last = burstLen == 1 ? 1'b1 : 1'b0;

	 return Axi3WriteData { data: tagdata.data, byteEnable: byteEnable, last: last, id: truncate(tagdata.tag) };
      endmethod
   endinterface
   interface Put resp_b;
      method Action put(Axi3WriteResponse#(tagWidth) resp);
	 master.write_client.writeDone.put(extend(resp.id));
      endmethod
   endinterface
   interface Get req_ar;
      method ActionValue#(Axi3ReadRequest#(addrWidth,tagWidth)) get();
	 let req <- master.read_client.readReq.get;
	 //$display("req_ar %h", req.tag);
	 return Axi3ReadRequest{address:req.addr, len:truncate((req.burstLen>>beat_shift)-1), id:truncate(req.tag), size: axiBusSize(valueOf(dataWidth)), burst: 1, prot: 0, cache: 15, lock:0, qos:0};
      endmethod
   endinterface
   interface Put resp_read;
      method Action put(Axi3ReadResponse#(dataWidth,tagWidth) response);
	 //$display("resp_read %h %h", response.data, response.id);
	 master.read_client.readData.put(MemData { data: response.data, tag: extend(response.id), last: response.last == 1 });
      endmethod
   endinterface

endmodule

module mkAxi4DmaSlave#(PhysMemSlave#(addrWidth,dataWidth) slave) (Axi4Slave#(addrWidth,dataWidth,axiIdSize))
       provisos (Add#(MemTagSize, sz__, axiIdSize));
   let beatShift = fromInteger(valueOf(TLog#(TDiv#(dataWidth,8))));
   interface Put req_ar;
      method Action put((Axi4ReadRequest#(addrWidth, axiIdSize)) req);
	 let burstLen = extend(req.len+1) << beatShift;
	 slave.read_server.readReq.put(PhysMemRequest{addr:req.address, burstLen:burstLen,  tag:truncate(req.id)
`ifdef BYTE_ENABLES
						      , firstbe: maxBound, lastbe: maxBound
`endif
						      });
      endmethod
   endinterface
   interface Get resp_read;
      method ActionValue#(Axi4ReadResponse#(dataWidth, axiIdSize)) get;
	 let resp <- slave.read_server.readData.get;
	 return Axi4ReadResponse{data:resp.data, resp:0, last:1, id:extend(resp.tag)};
      endmethod
   endinterface
   interface Put req_aw;
      method Action put(Axi4WriteRequest#(addrWidth, axiIdSize) req);
	 let burstLen = extend(req.len+1) << beatShift;
	 slave.write_server.writeReq.put(PhysMemRequest{addr:req.address, burstLen:burstLen, tag:truncate(req.id)
`ifdef BYTE_ENABLES
							, firstbe: maxBound, lastbe: maxBound
`endif
							});
      endmethod
   endinterface
   interface Put resp_write;
      method Action put(Axi4WriteData#(dataWidth, axiIdSize) resp);
	 slave.write_server.writeData.put(MemData{data:resp.data, tag:truncate(resp.id), last: resp.last == 1});
      endmethod
   endinterface
   interface Get resp_b;
      method ActionValue#(Axi4WriteResponse#(axiIdSize)) get;
	 let rv <- slave.write_server.writeDone.get;
	 return Axi4WriteResponse{resp:0, id:extend(rv)};
      endmethod
   endinterface
endmodule

module mkAxi4DmaMaster#(PhysMemMaster#(addrWidth,dataWidth) master) (Axi4Master#(addrWidth,dataWidth,tagWidth))

   provisos(Div#(dataWidth,8,dataWidthBytes),
	    Mul#(dataWidthBytes,8,dataWidth),
	    Log#(dataWidthBytes,beatShift),
	    Add#(tagWidth,a__,MemTagSize),
	    Add#(TDiv#(dataWidth,8),b__,dataWidthBytes),
	    Bits#(Tuple3#(Bit#(8),Bit#(TDiv#(dataWidth,8)),Bit#(TDiv#(dataWidth,8))),c__));

   Reg#(Bit#(8))  burstReg <- mkReg(0);
   FIFO#(Tuple3#(Bit#(8),Bit#(TDiv#(dataWidth,8)),Bit#(TDiv#(dataWidth,8)))) reqs <- mkSizedFIFO(32);
   Reg#(Bit#(dataWidthBytes)) lastbeReg <- mkReg(maxBound);

   let beat_shift = fromInteger(valueOf(beatShift));

   interface Get req_aw;
      method ActionValue#(Axi4WriteRequest#(addrWidth,tagWidth)) get();
	 let req <- master.write_client.writeReq.get;
	 reqs.enq(tuple3(truncate(req.burstLen),reqFirstByteEnable(req),reqLastByteEnable(req)));
	 return Axi4WriteRequest{address:req.addr, len:truncate((req.burstLen>>beat_shift)-1), id:truncate(req.tag), size: axiBusSize(valueOf(dataWidth)), burst: 1, prot: 0, cache: 15, lock:0, qos:0};
      endmethod
   endinterface
   interface Get resp_write;
      method ActionValue#(Axi4WriteData#(dataWidth,tagWidth)) get();
	 let tagdata <- master.write_client.writeData.get();
	 let burstLen = burstReg;
	 Bit#(dataWidthBytes) byteEnable = extend((burstLen == 1) ? lastbeReg : maxBound);
	 if (burstLen == 0) begin
	    match { .bl, .firstbe, .lastbe } = reqs.first;
	    burstLen = bl >> beat_shift;
	    reqs.deq;
`ifdef BYTE_ENABLES
	    byteEnable = extend(firstbe);
	    lastbeReg <= lastbe;
`endif
	 end
	 burstReg <= burstLen-1;
	 Bit#(1) last = burstLen == 1 ? 1'b1 : 1'b0;

	 return Axi4WriteData { data: tagdata.data, byteEnable: byteEnable, last: last, id: truncate(tagdata.tag) };
      endmethod
   endinterface
   interface Put resp_b;
      method Action put(Axi4WriteResponse#(tagWidth) resp);
	 master.write_client.writeDone.put(extend(resp.id));
      endmethod
   endinterface
   interface Get req_ar;
      method ActionValue#(Axi4ReadRequest#(addrWidth,tagWidth)) get();
	 let req <- master.read_client.readReq.get;
	 //$display("req_ar %h", req.tag);
	 return Axi4ReadRequest{address:req.addr, len:truncate((req.burstLen>>beat_shift)-1), id:truncate(req.tag), size: axiBusSize(valueOf(dataWidth)), burst: 1, prot: 0, cache: 15, lock:0, qos:0};
      endmethod
   endinterface
   interface Put resp_read;
      method Action put(Axi4ReadResponse#(dataWidth,tagWidth) response);
	 //$display("resp_read %h %h", response.data, response.id);
	 master.read_client.readData.put(MemData { data: response.data, tag: extend(response.id), last: response.last == 1 });
      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.
`include "ConnectalProjectConfig.bsv"
import ConnectalConfig::*;
import FIFO::*;
import GetPut::*;
import ClientServer::*;
import AxiMasterSlave::*;
import Axi4MasterSlave::*;
import ConnectalMemTypes::*;
import ConnectalMemory::*;

module mkAxiDmaSlave#(PhysMemSlave#(addrWidth,dataWidth) slave) (Axi3Slave#(addrWidth,dataWidth,12));
   let beatShift = fromInteger(valueOf(TLog#(TDiv#(dataWidth,8))));
   interface Put req_ar;
      method Action put((Axi3ReadRequest#(addrWidth, 12)) req);
	 let burstLen = extend(req.len+1) << beatShift;
	 slave.read_server.readReq.put(PhysMemRequest{addr:req.address, burstLen:burstLen,  tag:truncate(req.id)
`ifdef BYTE_ENABLES
						      , firstbe: maxBound, lastbe: maxBound
`endif
						      });
      endmethod
   endinterface
   interface Get resp_read;
      method ActionValue#(Axi3ReadResponse#(dataWidth, 12)) get;
	 let resp <- slave.read_server.readData.get;
	 return Axi3ReadResponse{data:resp.data, resp:0, last:1, id:extend(resp.tag)};
      endmethod
   endinterface
   interface Put req_aw;
      method Action put(Axi3WriteRequest#(addrWidth, 12) req);
	 let burstLen = extend(req.len+1) << beatShift;
	 slave.write_server.writeReq.put(PhysMemRequest{addr:req.address, burstLen:burstLen, tag:truncate(req.id)
`ifdef BYTE_ENABLES
							, firstbe: maxBound, lastbe: maxBound
`endif
							});
      endmethod
   endinterface
   interface Put resp_write;
      method Action put(Axi3WriteData#(dataWidth, 12) resp);
	 slave.write_server.writeData.put(MemData{data:resp.data, tag:truncate(resp.id), last: resp.last == 1});
      endmethod
   endinterface
   interface Get resp_b;
      method ActionValue#(Axi3WriteResponse#(12)) get;
	 let rv <- slave.write_server.writeDone.get;
	 return Axi3WriteResponse{resp:0, id:extend(rv)};
      endmethod
   endinterface
endmodule

module mkAxiDmaMaster#(PhysMemMaster#(addrWidth,dataWidth) master) (Axi3Master#(addrWidth,dataWidth,tagWidth))

   provisos(Div#(dataWidth,8,dataWidthBytes),
	    Mul#(dataWidthBytes,8,dataWidth),
	    Log#(dataWidthBytes,beatShift),
	    Add#(tagWidth,a__,MemTagSize),
	    Add#(TDiv#(dataWidth,8),b__,dataWidthBytes),
	    Bits#(Tuple3#(Bit#(8),Bit#(TDiv#(dataWidth,8)),Bit#(TDiv#(dataWidth,8))),c__));

   Reg#(Bit#(8))  burstReg <- mkReg(0);
   FIFO#(Tuple3#(Bit#(8),Bit#(TDiv#(dataWidth,8)),Bit#(TDiv#(dataWidth,8)))) reqs <- mkSizedFIFO(32);
   Reg#(Bit#(dataWidthBytes)) lastbeReg <- mkReg(maxBound);

   let beat_shift = fromInteger(valueOf(beatShift));

   interface Get req_aw;
      method ActionValue#(Axi3WriteRequest#(addrWidth,tagWidth)) get();
	 let req <- master.write_client.writeReq.get;
	 reqs.enq(tuple3(truncate(req.burstLen),reqFirstByteEnable(req),reqLastByteEnable(req)));
	 return Axi3WriteRequest{address:req.addr, len:truncate((req.burstLen>>beat_shift)-1), id:truncate(req.tag), size: axiBusSize(valueOf(dataWidth)), burst: 1, prot: 0, cache: 15, lock:0, qos:0};
      endmethod
   endinterface
   interface Get resp_write;
      method ActionValue#(Axi3WriteData#(dataWidth,tagWidth)) get();
	 let tagdata <- master.write_client.writeData.get();
	 let burstLen = burstReg;
	 Bit#(dataWidthBytes) byteEnable = extend((burstLen == 1) ? lastbeReg : maxBound);
	 if (burstLen == 0) begin
	    match { .bl, .firstbe, .lastbe } = reqs.first;
	    burstLen = bl >> beat_shift;
	    reqs.deq;
`ifdef BYTE_ENABLES
	    byteEnable = extend(firstbe);
	    lastbeReg <= lastbe;
`endif
	 end
	 burstReg <= burstLen-1;
	 Bit#(1) last = burstLen == 1 ? 1'b1 : 1'b0;

	 return Axi3WriteData { data: tagdata.data, byteEnable: byteEnable, last: last, id: truncate(tagdata.tag) };
      endmethod
   endinterface
   interface Put resp_b;
      method Action put(Axi3WriteResponse#(tagWidth) resp);
	 master.write_client.writeDone.put(extend(resp.id));
      endmethod
   endinterface
   interface Get req_ar;
      method ActionValue#(Axi3ReadRequest#(addrWidth,tagWidth)) get();
	 let req <- master.read_client.readReq.get;
	 //$display("req_ar %h", req.tag);
	 return Axi3ReadRequest{address:req.addr, len:truncate((req.burstLen>>beat_shift)-1), id:truncate(req.tag), size: axiBusSize(valueOf(dataWidth)), burst: 1, prot: 0, cache: 15, lock:0, qos:0};
      endmethod
   endinterface
   interface Put resp_read;
      method Action put(Axi3ReadResponse#(dataWidth,tagWidth) response);
	 //$display("resp_read %h %h", response.data, response.id);
	 master.read_client.readData.put(MemData { data: response.data, tag: extend(response.id), last: response.last == 1 });
      endmethod
   endinterface

endmodule

module mkAxi4DmaSlave#(PhysMemSlave#(addrWidth,dataWidth) slave) (Axi4Slave#(addrWidth,dataWidth,12));
   let beatShift = fromInteger(valueOf(TLog#(TDiv#(dataWidth,8))));
   interface Put req_ar;
      method Action put((Axi4ReadRequest#(addrWidth, 12)) req);
	 let burstLen = extend(req.len+1) << beatShift;
	 slave.read_server.readReq.put(PhysMemRequest{addr:req.address, burstLen:burstLen,  tag:truncate(req.id)
`ifdef BYTE_ENABLES
						      , firstbe: maxBound, lastbe: maxBound
`endif
						      });
      endmethod
   endinterface
   interface Get resp_read;
      method ActionValue#(Axi4ReadResponse#(dataWidth, 12)) get;
	 let resp <- slave.read_server.readData.get;
	 return Axi4ReadResponse{data:resp.data, resp:0, last:1, id:extend(resp.tag)};
      endmethod
   endinterface
   interface Put req_aw;
      method Action put(Axi4WriteRequest#(addrWidth, 12) req);
	 let burstLen = extend(req.len+1) << beatShift;
	 slave.write_server.writeReq.put(PhysMemRequest{addr:req.address, burstLen:burstLen, tag:truncate(req.id)
`ifdef BYTE_ENABLES
							, firstbe: maxBound, lastbe: maxBound
`endif
							});
      endmethod
   endinterface
   interface Put resp_write;
      method Action put(Axi4WriteData#(dataWidth, 12) resp);
	 slave.write_server.writeData.put(MemData{data:resp.data, tag:truncate(resp.id), last: resp.last == 1});
      endmethod
   endinterface
   interface Get resp_b;
      method ActionValue#(Axi4WriteResponse#(12)) get;
	 let rv <- slave.write_server.writeDone.get;
	 return Axi4WriteResponse{resp:0, id:extend(rv)};
      endmethod
   endinterface
endmodule

module mkAxi4DmaMaster#(PhysMemMaster#(addrWidth,dataWidth) master) (Axi4Master#(addrWidth,dataWidth,tagWidth))

   provisos(Div#(dataWidth,8,dataWidthBytes),
	    Mul#(dataWidthBytes,8,dataWidth),
	    Log#(dataWidthBytes,beatShift),
	    Add#(tagWidth,a__,MemTagSize),
	    Add#(TDiv#(dataWidth,8),b__,dataWidthBytes),
	    Bits#(Tuple3#(Bit#(8),Bit#(TDiv#(dataWidth,8)),Bit#(TDiv#(dataWidth,8))),c__));

   Reg#(Bit#(8))  burstReg <- mkReg(0);
   FIFO#(Tuple3#(Bit#(8),Bit#(TDiv#(dataWidth,8)),Bit#(TDiv#(dataWidth,8)))) reqs <- mkSizedFIFO(32);
   Reg#(Bit#(dataWidthBytes)) lastbeReg <- mkReg(maxBound);

   let beat_shift = fromInteger(valueOf(beatShift));

   interface Get req_aw;
      method ActionValue#(Axi4WriteRequest#(addrWidth,tagWidth)) get();
	 let req <- master.write_client.writeReq.get;
	 reqs.enq(tuple3(truncate(req.burstLen),reqFirstByteEnable(req),reqLastByteEnable(req)));
	 return Axi4WriteRequest{address:req.addr, len:truncate((req.burstLen>>beat_shift)-1), id:truncate(req.tag), size: axiBusSize(valueOf(dataWidth)), burst: 1, prot: 0, cache: 15, lock:0, qos:0};
      endmethod
   endinterface
   interface Get resp_write;
      method ActionValue#(Axi4WriteData#(dataWidth,tagWidth)) get();
	 let tagdata <- master.write_client.writeData.get();
	 let burstLen = burstReg;
	 Bit#(dataWidthBytes) byteEnable = extend((burstLen == 1) ? lastbeReg : maxBound);
	 if (burstLen == 0) begin
	    match { .bl, .firstbe, .lastbe } = reqs.first;
	    burstLen = bl >> beat_shift;
	    reqs.deq;
`ifdef BYTE_ENABLES
	    byteEnable = extend(firstbe);
	    lastbeReg <= lastbe;
`endif
	 end
	 burstReg <= burstLen-1;
	 Bit#(1) last = burstLen == 1 ? 1'b1 : 1'b0;

	 return Axi4WriteData { data: tagdata.data, byteEnable: byteEnable, last: last, id: truncate(tagdata.tag) };
      endmethod
   endinterface
   interface Put resp_b;
      method Action put(Axi4WriteResponse#(tagWidth) resp);
	 master.write_client.writeDone.put(extend(resp.id));
      endmethod
   endinterface
   interface Get req_ar;
      method ActionValue#(Axi4ReadRequest#(addrWidth,tagWidth)) get();
	 let req <- master.read_client.readReq.get;
	 //$display("req_ar %h", req.tag);
	 return Axi4ReadRequest{address:req.addr, len:truncate((req.burstLen>>beat_shift)-1), id:truncate(req.tag), size: axiBusSize(valueOf(dataWidth)), burst: 1, prot: 0, cache: 15, lock:0, qos:0};
      endmethod
   endinterface
   interface Put resp_read;
      method Action put(Axi4ReadResponse#(dataWidth,tagWidth) response);
	 //$display("resp_read %h %h", response.data, response.id);
	 master.read_client.readData.put(MemData { data: response.data, tag: extend(response.id), last: response.last == 1 });
      endmethod
   endinterface

endmodule


added msgSink and msgSource methods for xsim to use with mkBluenocTop

// Copyright (c) 2015 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.

typedef enum { XsimMemSlaveRequest, XsimMemSlaveIndication } XsimIfcNames;

interface XsimMemSlaveRequest;
   method Action connect();
   method Action enableint(Bit#(32) fpgaId, Bit#(1) val);
   method Action read(Bit#(32) fpgaId, Bit#(32) addr);
   method Action write(Bit#(32) fpgaId, Bit#(32) addr, Bit#(32) data);
   // for bluenoc top
   method Action msgSink(Bit#(32) data);
endinterface
interface XsimMemSlaveIndication;
   method Action directory(Bit#(32) fpgaNumber, Bit#(32) fpgaId, Bit#(1) last);
   method Action readData(Bit#(32) data);
   method Action interrupt(Bit#(4) intrNum);
   // for bluenoc top
   method Action msgSource(Bit#(32) data);
endinterface

// Copyright (c) 2015 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.

typedef enum { XsimMemSlaveRequest, XsimMemSlaveIndication } XsimIfcNames;

interface XsimMemSlaveRequest;
   method Action connect();
   method Action enableint(Bit#(32) fpgaId, Bit#(1) val);
   method Action read(Bit#(32) fpgaId, Bit#(32) addr);
   method Action write(Bit#(32) fpgaId, Bit#(32) addr, Bit#(32) data);
endinterface
interface XsimMemSlaveIndication;
   method Action directory(Bit#(32) fpgaNumber, Bit#(32) fpgaId, Bit#(1) last);
   method Action readData(Bit#(32) data);
   method Action interrupt(Bit#(4) intrNum);
endinterface


remove dangling reference to tlpCompleterRequest

// Copyright (c) 2014-2015 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 Vector            :: *;
import BuildVector       :: *;
import Clocks            :: *;
import GetPut            :: *;
import FIFO              :: *;
import Connectable       :: *;
import ClientServer      :: *;
import BRAM              :: *;
import DefaultValue      :: *;
import PcieSplitter      :: *;
import PcieTracer        :: *;
import Xilinx            :: *;
import Bscan             :: *;
import Portal            :: *;
import MemToPcie    :: *;
import PcieToMem   :: *;
import PcieCsr           :: *;
import MemTypes          :: *;
`ifndef BSIM
`ifdef XILINX
`ifdef PCIE1
import PCIEWRAPPER       :: *;
import PcieEndpointX7    :: *;
`endif // pcie1
`ifdef PCIE2
import PCIEWRAPPER2       :: *;
import PcieEndpointX7Gen2 :: *;
`endif // pcie2
`ifdef PCIE3
import PCIEWRAPPER3      :: *;
import Pcie3EndpointX7   :: *;
`endif // pcie3
`elsif ALTERA
import PcieEndpointS5    :: *;
`elsif VSIM
import PcieEndpointS5    :: *;
`endif
`endif
import HostInterface     :: *;

// implemented in TlpReplay.cpp
import "BDPI" function Action put_tlp(TLPData#(16) d);
import "BDPI" function ActionValue#(TLPData#(16)) get_tlp();
import "BDPI" function Bool can_put_tlp();
import "BDPI" function Bool can_get_tlp();

(* synthesize *)
module mkMemToPcieSynth#(PciId my_id)(MemToPcie#(DataBusWidth));
   let memSlaveEngine <- mkMemToPcie(my_id);
   return memSlaveEngine;
endmodule

// ==================================================
// PCIE Gen3  PcieHost
//
`ifdef PCIE3
(* synthesize *)
module mkPcieHost#(PciId my_pciId)(PcieHost#(DataBusWidth, NumberOfMasters));
   TLPDispatcher dispatcher <- mkTLPDispatcher;
   TLPArbiter arbiter <- mkTLPArbiter;
   MemToPcie#(DataBusWidth) sEngine <- mkMemToPcieSynth(my_pciId);
`ifdef PCIE3
   MemInterrupt intr <- mkMemInterrupt(my_pciId);
`endif
   Vector#(PortMax, PcieToMem) mvec;
   for (Integer i=0; i < valueOf(PortMax) - 1; i=i+1) begin
      let tlp;
      if (i == portInterrupt)
         tlp = intr.tlp;
      else begin
         mvec[i] <- mkPcieToMem(my_pciId);
         tlp = mvec[i].tlp;
      end
      mkConnection((interface Server;
                       interface response = dispatcher.out[i];
                       interface request = arbiter.in[i];
                    endinterface), tlp);
   end

   PcieTracer traceif <- mkPcieTracer();
   let splitter = (interface Client;
                      interface request = arbiter.outToBus;
                      interface response = dispatcher.inFromBus;
                  endinterface);
`ifdef TRACE_PORTAL
   mkConnection(traceif.bus, splitter);
`else
   mkConnection(traceif.bus, sEngine.tlp);
`endif

   PcieControlAndStatusRegs csr <- mkPcieControlAndStatusRegs();
   mkConnection(mvec[portConfig].master, csr.memSlave);

   mkConnection(csr.traceClient, traceif.traceServer);
   interface msixEntry = csr.msixEntry;
   interface master = mvec[portPortal].master;
   interface slave = vec(sEngine.slave);
   interface interruptRequest = intr.interruptRequest;
`ifdef TRACE_PORTAL
   interface pcic = traceif.pci;
   interface pcir = sEngine.tlp;
`else
   interface pcic = splitter;
   interface pcir = traceif.pci;
`endif
endmodule: mkPcieHost
`else //NOT PCIE3
// ======================================================
// PCIE GEN1 and GEN2 PcieHost
//(* synthesize *) commented out so that the guards in MemServer aren't destroyed (mdk)
module  mkPcieHost#(PciId my_pciId)(PcieHost#(DataBusWidth, NumberOfMasters));
   let dispatcher <- mkTLPDispatcher;
   let arbiter    <- mkTLPArbiter;
   Vector#(NumberOfMasters,MemToPcie#(DataBusWidth)) sEngine <- replicateM(mkMemToPcieSynth(my_pciId));
   Vector#(NumberOfMasters,PhysMemSlave#(PciePhysAddrWidth,DataBusWidth)) slavearr;
   MemInterrupt intr <- mkMemInterrupt(my_pciId);
`ifdef PCIE_BSCAN
   BscanTop bscan <- mkBscanTop(3); // Use USER3  (JTAG IDCODE address 0x22)
   BscanLocal lbscan <- mkBscanLocal(bscan, clocked_by bscan.tck, reset_by bscan.rst);
`endif

   Vector#(PortMax, PcieToMem) mvec;
   for (Integer i = 0; i < valueOf(PortMax) - 1 + valueOf(NumberOfMasters); i=i+1) begin
       let tlp;
       if (i == portInterrupt)
           tlp = intr.tlp;
       else if (i >= portAxi) begin
           tlp = sEngine[i - portAxi].tlp;
           slavearr[i - portAxi] = sEngine[i - portAxi].slave;
       end
       else begin
           mvec[i] <- mkPcieToMem(my_pciId);
           tlp = mvec[i].tlp;
       end
       mkConnection((interface Server;
                        interface response = dispatcher.out[i];
                        interface request = arbiter.in[i];
                     endinterface), tlp);
   end

   PcieTracer  traceif <- mkPcieTracer();
   mkConnection(traceif.bus, (interface Client;
                                 interface request = arbiter.outToBus;
                                 interface response = dispatcher.inFromBus;
                              endinterface));

`ifndef BSIM
`ifdef PCIE_BSCAN
   Reg#(Bit#(TAdd#(TlpTraceAddrSize,1))) bscanPcieTraceBramWrAddrReg <- mkReg(0);
   BscanBram#(Bit#(TAdd#(TlpTraceAddrSize,1)), TimestampedTlpData) pcieBscanBram <- mkBscanBram(127, bscanPcieTraceBramWrAddrReg, lbscan.loc[1]);
   mkConnection(pcieBscanBram.bramClient, traceif.tlpdata.bscanBramServer);
   rule tdorule;
      lbscan.loc[1].tdo(pcieBscanBram.data_out());
   endrule
`endif
`endif

   PcieControlAndStatusRegs csr <- mkPcieControlAndStatusRegs;
   mkConnection(mvec[portConfig].master, csr.memSlave);
   mkConnection(csr.traceClient, traceif.traceServer);

   interface msixEntry = csr.msixEntry;
   interface master = mvec[portPortal].master;
   interface slave = slavearr;
   interface interruptRequest = intr.interruptRequest;
   interface pci = traceif.pci;
`ifdef PCIE_BSCAN
   interface BscanTop bscanif = lbscan.loc[0];
`else
`ifdef PCIE_TRACE_PORT
   interface BRAMServer traceBramServer = traceif.tlpdata.bscanBramServer;
`endif
`endif
endmodule: mkPcieHost
`endif //PCIE3

interface PcieTop#(type ipins);
`ifndef BSIM
   (* prefix="PCIE" *)
   interface PciewrapPci_exp#(PcieLanes) pcie;
   (* always_ready *)
   (* prefix="" *)
   interface ipins       pins;
`endif
endinterface

`ifdef BSIM
module mkBsimPcieHostTop #(Clock pci_sys_clk_p, Clock pci_sys_clk_n, Clock sys_clk_p, Clock sys_clk_n, Reset pci_sys_reset_n)(PcieHostTop);
   let dc <- exposeCurrentClock;
   let dr <- exposeCurrentReset;
   PcieHost#(DataBusWidth, NumberOfMasters) pciehost <- mkPcieHost(PciId{ bus:0, dev:0, func:0});
   // connect pciehost.pci to bdip functions here
   rule from_bdpi if (can_get_tlp);
      TLPData#(16) foo <- get_tlp;
      pciehost.pci.response.put(foo);
      //$display("from_bdpi: %h %d", foo, valueOf(SizeOf#(TLPData#(16))));
   endrule
   rule to_bdpi if (can_put_tlp);
      TLPData#(16) foo <- pciehost.pci.request.get;
      put_tlp(foo);
      //$display("to_bdpi");
   endrule
   interface Clock pcieClock = dc;
   interface Reset pcieReset = dr;
   interface PcieHost tpciehost = pciehost;
endmodule
`endif

`ifdef XILINX
(* no_default_clock, no_default_reset *)
module mkXilinxPcieHostTop #(Clock pci_sys_clk_p, Clock pci_sys_clk_n, Clock sys_clk_p, Clock sys_clk_n, Reset pci_sys_reset_n)(PcieHostTop);

// Clock and PcieEndpoint for Xilinx
   Clock sys_clk_200mhz <- mkClockIBUFDS(
`ifdef ClockDefaultParam
       defaultValue,
`endif
       sys_clk_p, sys_clk_n);
   Clock sys_clk_200mhz_buf <- mkClockBUFG(clocked_by sys_clk_200mhz);
   Clock pci_clk_100mhz_buf <- mkClockIBUFDS_GTE2(
`ifdef ClockDefaultParam
       defaultValue,
`endif
       True, pci_sys_clk_p, pci_sys_clk_n);
   // Instantiate the PCIE endpoint
   PcieEndpointX7#(PcieLanes) ep7 <- mkPcieEndpointX7( clocked_by pci_clk_100mhz_buf, reset_by pci_sys_reset_n);

   Clock pcieClock_ = ep7.epPcieClock;
   Reset pcieReset_ = ep7.epPcieReset;
   PcieHost#(DataBusWidth, NumberOfMasters) pciehost <- mkPcieHost(
`ifdef PCIE3
         PciId{bus: 0, dev: 0, func:0},
`else
         PciId{ bus:  ep7.cfg.bus_number(), dev: ep7.cfg.device_number(), func: ep7.cfg.function_number()},
`endif
         clocked_by pcieClock_, reset_by pcieReset_);
`ifdef PCIE3
   mkConnection(ep7.tlpr, pciehost.pcir, clocked_by pcieClock_, reset_by pcieReset_);
   mkConnection(ep7.tlpc, pciehost.pcic, clocked_by pcieClock_, reset_by pcieReset_);
   let ipciehost = (interface PcieHost;
		    interface msixEntry = pciehost.msixEntry;
		    interface master = pciehost.master;
		    interface slave = pciehost.slave;
		    interface pcir = pciehost.pcir;
		    interface pcic = pciehost.pcic;
		    interface trace = pciehost.trace;
		    interface interruptRequest = ep7.interruptRequest;
		    endinterface);
`else
   mkConnection(ep7.tlp, pciehost.pci, clocked_by pcieClock_, reset_by pcieReset_);
   let ipciehost = pciehost;
`endif

   interface Clock tsys_clk_200mhz = sys_clk_200mhz;
   interface Clock tsys_clk_200mhz_buf = sys_clk_200mhz_buf;
   interface Clock tpci_clk_100mhz_buf = pci_clk_100mhz_buf;

   interface PcieEndpointX7 tep7 = ep7;
   interface PcieHost tpciehost = ipciehost;

   interface pcieClock = ep7.epPcieClock;
   interface pcieReset = ep7.epPcieReset;
   interface portalClock = ep7.epPortalClock;
   interface portalReset = ep7.epPortalReset;
   interface derivedClock = ep7.epDerivedClock;
   interface derivedReset = ep7.epDerivedReset;
endmodule
`endif

`ifdef ALTERA
`define ALTERA_TOP
`elsif VSIM
`define ALTERA_TOP
`endif

`ifdef ALTERA_TOP
(* no_default_clock, no_default_reset *)
module mkAlteraPcieHostTop #(Clock clk_100MHz, Clock clk_50MHz, Reset perst_n)(PcieHostTop);

   PcieEndpointS5#(PcieLanes) ep7 <- mkPcieEndpointS5(clk_100MHz, clk_50MHz, perst_n, clocked_by clk_100MHz, reset_by perst_n);

   Clock epPcieClock = ep7.epPcieClock;
   Reset epPcieReset = ep7.epPcieReset;

   Clock portalClock_ = epPcieClock;
   Reset portalReset_ = epPcieReset;

   PcieHost#(DataBusWidth, NumberOfMasters) pciehost <- mkPcieHost(ep7.device, clocked_by portalClock_, reset_by portalReset_);
   mkConnection(ep7.tlp, pciehost.pci, clocked_by portalClock_, reset_by portalReset_);

   interface PcieEndpointS5 tep7 = ep7;
   interface PcieHost tpciehost = pciehost;

   interface Clock pcieClock = epPcieClock;
   interface Reset pcieReset = epPcieReset;
   interface portalClock = portalClock_;
   interface portalReset = portalReset_;
   interface derivedClock = ep7.epDerivedClock;
   interface derivedReset = ep7.epDerivedReset;

endmodule
`endif

`ifdef BSIM
   module mkPcieHostTop #(Clock pci_sys_clk_p, Clock pci_sys_clk_n, Clock sys_clk_p, Clock sys_clk_n, Reset pci_sys_reset_n)(PcieHostTop);
   PcieHostTop _a <- mkBsimPcieHostTop(pci_sys_clk_p, pci_sys_clk_n, sys_clk_p, sys_clk_n, pci_sys_reset_n); return _a;
   endmodule
`elsif XILINX // XILINX
   //(* synthesize, no_default_clock, no_default_reset *)
   (* no_default_clock, no_default_reset *)
   module mkPcieHostTop #(Clock pci_sys_clk_p, Clock pci_sys_clk_n, Clock sys_clk_p, Clock sys_clk_n, Reset pci_sys_reset_n)(PcieHostTop);
      PcieHostTop _a <- mkXilinxPcieHostTop(pci_sys_clk_p, pci_sys_clk_n, sys_clk_p, sys_clk_n, pci_sys_reset_n); return _a;
   endmodule
`elsif ALTERA_TOP
   //(* synthesize, no_default_clock, no_default_reset *)
   (* no_default_clock, no_default_reset *)
   module mkPcieHostTop #(Clock clk_100MHz, Clock clk_50MHz, Reset perst_n)(PcieHostTop);
      PcieHostTop _a <- mkAlteraPcieHostTop(clk_100MHz, clk_50MHz, perst_n); return _a;
   endmodule
`endif // NOT ALTERA

// Copyright (c) 2014-2015 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 Vector            :: *;
import BuildVector       :: *;
import Clocks            :: *;
import GetPut            :: *;
import FIFO              :: *;
import Connectable       :: *;
import ClientServer      :: *;
import BRAM              :: *;
import DefaultValue      :: *;
import PcieSplitter      :: *;
import PcieTracer        :: *;
import Xilinx            :: *;
import Bscan             :: *;
import Portal            :: *;
import MemToPcie    :: *;
import PcieToMem   :: *;
import PcieCsr           :: *;
import MemTypes          :: *;
`ifndef BSIM
`ifdef XILINX
`ifdef PCIE1
import PCIEWRAPPER       :: *;
import PcieEndpointX7    :: *;
`endif // pcie1
`ifdef PCIE2
import PCIEWRAPPER2       :: *;
import PcieEndpointX7Gen2 :: *;
`endif // pcie2
`ifdef PCIE3
import PCIEWRAPPER3      :: *;
import Pcie3EndpointX7   :: *;
`endif // pcie3
`elsif ALTERA
import PcieEndpointS5    :: *;
`elsif VSIM
import PcieEndpointS5    :: *;
`endif
`endif
import HostInterface     :: *;

// implemented in TlpReplay.cpp
import "BDPI" function Action put_tlp(TLPData#(16) d);
import "BDPI" function ActionValue#(TLPData#(16)) get_tlp();
import "BDPI" function Bool can_put_tlp();
import "BDPI" function Bool can_get_tlp();

(* synthesize *)
module mkMemToPcieSynth#(PciId my_id)(MemToPcie#(DataBusWidth));
   let memSlaveEngine <- mkMemToPcie(my_id);
   return memSlaveEngine;
endmodule

// ==================================================
// PCIE Gen3  PcieHost
//
`ifdef PCIE3
Integer tlpCompleterRequest = 0;
Integer tlpRequesterRequest = 1;

(* synthesize *)
module mkPcieHost#(PciId my_pciId)(PcieHost#(DataBusWidth, NumberOfMasters));
   TLPDispatcher dispatcher <- mkTLPDispatcher;
   TLPArbiter arbiter <- mkTLPArbiter;
   MemToPcie#(DataBusWidth) sEngine <- mkMemToPcieSynth(my_pciId);
`ifdef PCIE3
   MemInterrupt intr <- mkMemInterrupt(my_pciId);
`endif
   Vector#(PortMax, PcieToMem) mvec;
   for (Integer i=0; i < valueOf(PortMax) - 1; i=i+1) begin
      let tlp;
      if (i == portInterrupt)
         tlp = intr.tlp;
      else begin
         mvec[i] <- mkPcieToMem(my_pciId);
         tlp = mvec[i].tlp;
      end
      mkConnection((interface Server;
                       interface response = dispatcher.out[i];
                       interface request = arbiter.in[i];
                    endinterface), tlp);
   end

   PcieTracer traceif <- mkPcieTracer();
   let splitter = (interface Client;
                      interface request = arbiter.outToBus;
                      interface response = dispatcher.inFromBus;
                  endinterface);
`ifdef TRACE_PORTAL
   mkConnection(traceif[tlpCompleterRequest].bus, splitter);
`else
   mkConnection(traceif.bus, sEngine.tlp);
`endif

   PcieControlAndStatusRegs csr <- mkPcieControlAndStatusRegs();
   mkConnection(mvec[portConfig].master, csr.memSlave);

   mkConnection(csr.traceClient, traceif.traceServer);
   interface msixEntry = csr.msixEntry;
   interface master = mvec[portPortal].master;
   interface slave = vec(sEngine.slave);
   interface interruptRequest = intr.interruptRequest;
`ifdef TRACE_PORTAL
   interface pcic = traceif.pci;
   interface pcir = sEngine.tlp;
`else
   interface pcic = splitter;
   interface pcir = traceif.pci;
`endif
endmodule: mkPcieHost
`else //NOT PCIE3
// ======================================================
// PCIE GEN1 and GEN2 PcieHost
//(* synthesize *) commented out so that the guards in MemServer aren't destroyed (mdk)
module  mkPcieHost#(PciId my_pciId)(PcieHost#(DataBusWidth, NumberOfMasters));
   let dispatcher <- mkTLPDispatcher;
   let arbiter    <- mkTLPArbiter;
   Vector#(NumberOfMasters,MemToPcie#(DataBusWidth)) sEngine <- replicateM(mkMemToPcieSynth(my_pciId));
   Vector#(NumberOfMasters,PhysMemSlave#(PciePhysAddrWidth,DataBusWidth)) slavearr;
   MemInterrupt intr <- mkMemInterrupt(my_pciId);
`ifdef PCIE_BSCAN
   BscanTop bscan <- mkBscanTop(3); // Use USER3  (JTAG IDCODE address 0x22)
   BscanLocal lbscan <- mkBscanLocal(bscan, clocked_by bscan.tck, reset_by bscan.rst);
`endif

   Vector#(PortMax, PcieToMem) mvec;
   for (Integer i = 0; i < valueOf(PortMax) - 1 + valueOf(NumberOfMasters); i=i+1) begin
       let tlp;
       if (i == portInterrupt)
           tlp = intr.tlp;
       else if (i >= portAxi) begin
           tlp = sEngine[i - portAxi].tlp;
           slavearr[i - portAxi] = sEngine[i - portAxi].slave;
       end
       else begin
           mvec[i] <- mkPcieToMem(my_pciId);
           tlp = mvec[i].tlp;
       end
       mkConnection((interface Server;
                        interface response = dispatcher.out[i];
                        interface request = arbiter.in[i];
                     endinterface), tlp);
   end

   PcieTracer  traceif <- mkPcieTracer();
   mkConnection(traceif.bus, (interface Client;
                                 interface request = arbiter.outToBus;
                                 interface response = dispatcher.inFromBus;
                              endinterface));

`ifndef BSIM
`ifdef PCIE_BSCAN
   Reg#(Bit#(TAdd#(TlpTraceAddrSize,1))) bscanPcieTraceBramWrAddrReg <- mkReg(0);
   BscanBram#(Bit#(TAdd#(TlpTraceAddrSize,1)), TimestampedTlpData) pcieBscanBram <- mkBscanBram(127, bscanPcieTraceBramWrAddrReg, lbscan.loc[1]);
   mkConnection(pcieBscanBram.bramClient, traceif.tlpdata.bscanBramServer);
   rule tdorule;
      lbscan.loc[1].tdo(pcieBscanBram.data_out());
   endrule
`endif
`endif

   PcieControlAndStatusRegs csr <- mkPcieControlAndStatusRegs;
   mkConnection(mvec[portConfig].master, csr.memSlave);
   mkConnection(csr.traceClient, traceif.traceServer);

   interface msixEntry = csr.msixEntry;
   interface master = mvec[portPortal].master;
   interface slave = slavearr;
   interface interruptRequest = intr.interruptRequest;
   interface pci = traceif.pci;
`ifdef PCIE_BSCAN
   interface BscanTop bscanif = lbscan.loc[0];
`else
`ifdef PCIE_TRACE_PORT
   interface BRAMServer traceBramServer = traceif.tlpdata.bscanBramServer;
`endif
`endif
endmodule: mkPcieHost
`endif //PCIE3

interface PcieTop#(type ipins);
`ifndef BSIM
   (* prefix="PCIE" *)
   interface PciewrapPci_exp#(PcieLanes) pcie;
   (* always_ready *)
   (* prefix="" *)
   interface ipins       pins;
`endif
endinterface

`ifdef BSIM
module mkBsimPcieHostTop #(Clock pci_sys_clk_p, Clock pci_sys_clk_n, Clock sys_clk_p, Clock sys_clk_n, Reset pci_sys_reset_n)(PcieHostTop);
   let dc <- exposeCurrentClock;
   let dr <- exposeCurrentReset;
   PcieHost#(DataBusWidth, NumberOfMasters) pciehost <- mkPcieHost(PciId{ bus:0, dev:0, func:0});
   // connect pciehost.pci to bdip functions here
   rule from_bdpi if (can_get_tlp);
      TLPData#(16) foo <- get_tlp;
      pciehost.pci.response.put(foo);
      //$display("from_bdpi: %h %d", foo, valueOf(SizeOf#(TLPData#(16))));
   endrule
   rule to_bdpi if (can_put_tlp);
      TLPData#(16) foo <- pciehost.pci.request.get;
      put_tlp(foo);
      //$display("to_bdpi");
   endrule
   interface Clock pcieClock = dc;
   interface Reset pcieReset = dr;
   interface PcieHost tpciehost = pciehost;
endmodule
`endif

`ifdef XILINX
(* no_default_clock, no_default_reset *)
module mkXilinxPcieHostTop #(Clock pci_sys_clk_p, Clock pci_sys_clk_n, Clock sys_clk_p, Clock sys_clk_n, Reset pci_sys_reset_n)(PcieHostTop);

// Clock and PcieEndpoint for Xilinx
   Clock sys_clk_200mhz <- mkClockIBUFDS(
`ifdef ClockDefaultParam
       defaultValue,
`endif
       sys_clk_p, sys_clk_n);
   Clock sys_clk_200mhz_buf <- mkClockBUFG(clocked_by sys_clk_200mhz);
   Clock pci_clk_100mhz_buf <- mkClockIBUFDS_GTE2(
`ifdef ClockDefaultParam
       defaultValue,
`endif
       True, pci_sys_clk_p, pci_sys_clk_n);
   // Instantiate the PCIE endpoint
   PcieEndpointX7#(PcieLanes) ep7 <- mkPcieEndpointX7( clocked_by pci_clk_100mhz_buf, reset_by pci_sys_reset_n);

   Clock pcieClock_ = ep7.epPcieClock;
   Reset pcieReset_ = ep7.epPcieReset;
   PcieHost#(DataBusWidth, NumberOfMasters) pciehost <- mkPcieHost(
`ifdef PCIE3
         PciId{bus: 0, dev: 0, func:0},
`else
         PciId{ bus:  ep7.cfg.bus_number(), dev: ep7.cfg.device_number(), func: ep7.cfg.function_number()},
`endif
         clocked_by pcieClock_, reset_by pcieReset_);
`ifdef PCIE3
   mkConnection(ep7.tlpr, pciehost.pcir, clocked_by pcieClock_, reset_by pcieReset_);
   mkConnection(ep7.tlpc, pciehost.pcic, clocked_by pcieClock_, reset_by pcieReset_);
   let ipciehost = (interface PcieHost;
		    interface msixEntry = pciehost.msixEntry;
		    interface master = pciehost.master;
		    interface slave = pciehost.slave;
		    interface pcir = pciehost.pcir;
		    interface pcic = pciehost.pcic;
		    interface trace = pciehost.trace;
		    interface interruptRequest = ep7.interruptRequest;
		    endinterface);
`else
   mkConnection(ep7.tlp, pciehost.pci, clocked_by pcieClock_, reset_by pcieReset_);
   let ipciehost = pciehost;
`endif

   interface Clock tsys_clk_200mhz = sys_clk_200mhz;
   interface Clock tsys_clk_200mhz_buf = sys_clk_200mhz_buf;
   interface Clock tpci_clk_100mhz_buf = pci_clk_100mhz_buf;

   interface PcieEndpointX7 tep7 = ep7;
   interface PcieHost tpciehost = ipciehost;

   interface pcieClock = ep7.epPcieClock;
   interface pcieReset = ep7.epPcieReset;
   interface portalClock = ep7.epPortalClock;
   interface portalReset = ep7.epPortalReset;
   interface derivedClock = ep7.epDerivedClock;
   interface derivedReset = ep7.epDerivedReset;
endmodule
`endif

`ifdef ALTERA
`define ALTERA_TOP
`elsif VSIM
`define ALTERA_TOP
`endif

`ifdef ALTERA_TOP
(* no_default_clock, no_default_reset *)
module mkAlteraPcieHostTop #(Clock clk_100MHz, Clock clk_50MHz, Reset perst_n)(PcieHostTop);

   PcieEndpointS5#(PcieLanes) ep7 <- mkPcieEndpointS5(clk_100MHz, clk_50MHz, perst_n, clocked_by clk_100MHz, reset_by perst_n);

   Clock epPcieClock = ep7.epPcieClock;
   Reset epPcieReset = ep7.epPcieReset;

   Clock portalClock_ = epPcieClock;
   Reset portalReset_ = epPcieReset;

   PcieHost#(DataBusWidth, NumberOfMasters) pciehost <- mkPcieHost(ep7.device, clocked_by portalClock_, reset_by portalReset_);
   mkConnection(ep7.tlp, pciehost.pci, clocked_by portalClock_, reset_by portalReset_);

   interface PcieEndpointS5 tep7 = ep7;
   interface PcieHost tpciehost = pciehost;

   interface Clock pcieClock = epPcieClock;
   interface Reset pcieReset = epPcieReset;
   interface portalClock = portalClock_;
   interface portalReset = portalReset_;
   interface derivedClock = ep7.epDerivedClock;
   interface derivedReset = ep7.epDerivedReset;

endmodule
`endif

`ifdef BSIM
   module mkPcieHostTop #(Clock pci_sys_clk_p, Clock pci_sys_clk_n, Clock sys_clk_p, Clock sys_clk_n, Reset pci_sys_reset_n)(PcieHostTop);
   PcieHostTop _a <- mkBsimPcieHostTop(pci_sys_clk_p, pci_sys_clk_n, sys_clk_p, sys_clk_n, pci_sys_reset_n); return _a;
   endmodule
`elsif XILINX // XILINX
   //(* synthesize, no_default_clock, no_default_reset *)
   (* no_default_clock, no_default_reset *)
   module mkPcieHostTop #(Clock pci_sys_clk_p, Clock pci_sys_clk_n, Clock sys_clk_p, Clock sys_clk_n, Reset pci_sys_reset_n)(PcieHostTop);
      PcieHostTop _a <- mkXilinxPcieHostTop(pci_sys_clk_p, pci_sys_clk_n, sys_clk_p, sys_clk_n, pci_sys_reset_n); return _a;
   endmodule
`elsif ALTERA_TOP
   //(* synthesize, no_default_clock, no_default_reset *)
   (* no_default_clock, no_default_reset *)
   module mkPcieHostTop #(Clock clk_100MHz, Clock clk_50MHz, Reset perst_n)(PcieHostTop);
      PcieHostTop _a <- mkAlteraPcieHostTop(clk_100MHz, clk_50MHz, perst_n); return _a;
   endmodule
`endif // NOT ALTERA