only use byte enables if BYTE_ENABLES is defined

// 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 Vector::*;
import BuildVector::*;
import FIFO::*;
import FIFOF::*;
import BRAMFIFO::*;
import ClientServer::*;
import GetPut::*;
import HostInterface::*;
import MemTypes::*;
import MemWriteEngine::*;
import Pipe::*;
import AddressGenerator::*;

typedef TDiv#(DataBusWidth,32) WordsPerBeat;

interface MemwriteRequest;
   method Action startWrite(Bit#(32) pointer, Bit#(32) numWords, Bit#(32) numReqs, Bit#(32) burstLen, Bit#(8) byteEnable);
endinterface

interface MemwriteIndication;
   method Action writeDone(Bit#(32) v);
   method Action writeProgress(Bit#(32) v);
endinterface

interface Memwrite;
   interface MemwriteRequest request;
   interface Vector#(1, MemWriteClient#(DataBusWidth)) dmaClients;
endinterface

module  mkMemwrite#(MemwriteIndication indication) (Memwrite);
   Reg#(SGLId)   pointer <- mkReg(0);
   Reg#(Bit#(32))        numReqs <- mkReg(0);
   Reg#(Bit#(32))        numDone <- mkReg(0);
   Reg#(Bit#(MemOffsetSize)) reqOffset <- mkReg(0);
   Reg#(Bit#(3))                   tag <- mkReg(0);
   Reg#(Bit#(32))             numWords <- mkReg(0);
   Reg#(Bit#(BurstLenSize)) burstLenBytes <- mkReg(0);
   Reg#(Bit#(32))              srcGens <- mkReg(3);
   Reg#(Bit#(8))            byteEnable <- mkReg('hff);

   AddressGenerator#(32, DataBusWidth) addrGenerator <- mkAddressGenerator();
   FIFO#(MemRequest) reqFifo <- mkSizedFIFO(4);
   FIFO#(PhysMemRequest#(32,DataBusWidth)) preqFifo <- mkSizedFIFO(4);
   FIFO#(MemData#(DataBusWidth))   dataFifo <- mkSizedBRAMFIFO(1024);
   FIFO#(Bit#(MemTagSize)) doneFifo <- mkSizedFIFO(4);

   let verboseProgress = False;

`ifdef BYTE_ENABLES
   Bit#(TDiv#(DataBusWidth,8)) firstbe = maxBound;
   Bit#(TDiv#(DataBusWidth,8)) lastbe = maxBound;
   // just apply the byteEnable to the first and last 32-bit word of a burst
   firstbe[3:0] = byteEnable[3:0];
   lastbe[valueOf(ByteEnableSize)-1:valueOf(ByteEnableSize)-4] = byteEnable[7:4];
`endif

   rule start if (numReqs != 0);
`ifdef BYTE_ENABLES
      $display("Memwrite.start firstbe=%h lastbe=%h", firstbe, lastbe);
`endif
      reqFifo.enq(MemRequest { sglId: pointer, offset: reqOffset, burstLen: burstLenBytes, tag: extend(tag)
`ifdef BYTE_ENABLES
			      , firstbe: firstbe, lastbe: lastbe
`endif
			      });
      preqFifo.enq(PhysMemRequest { addr: 0, burstLen: burstLenBytes, tag: extend(tag)
`ifdef BYTE_ENABLES
				       , firstbe: firstbe, lastbe: lastbe
`endif
				   });
      numReqs <= numReqs - 1;
      reqOffset <= reqOffset + extend(burstLenBytes);
      tag <= tag + 1;
      //$display("start numReqs", numReqs);
   endrule

   rule preq;
      let preq <- toGet(preqFifo).get();
      addrGenerator.request.put(preq);
   endrule

   rule finish;
      let donetag <- toGet(doneFifo).get();
      //$display("finished num todo=%d", numDone);
      if (numDone == 1) begin
         indication.writeDone(0);
      end
      numDone <= numDone - 1;
      if (verboseProgress)
	 indication.writeProgress(extend(donetag));
   endrule

   rule src if (numWords != 0);
      let b <- addrGenerator.addrBeat.get();

      function Bit#(32) plusi(Integer i); return srcGens + fromInteger(i); endfunction
      Vector#(WordsPerBeat, Bit#(32)) v = genWith(plusi);
      dataFifo.enq(MemData { data: pack(v), tag: b.tag, last: b.last});
      srcGens <= srcGens+fromInteger(valueOf(WordsPerBeat));
      numWords <= numWords - fromInteger(valueOf(WordsPerBeat));
   endrule

   MemWriteClient#(DataBusWidth) dmaClient = (interface MemWriteClient;
      interface Get writeReq = toGet(reqFifo);
      interface Get writeData = toGet(dataFifo);
      interface Put writeDone = toPut(doneFifo);
   endinterface );

   interface MemwriteRequest request;
       method Action startWrite(Bit#(32) wp, Bit#(32) nw, Bit#(32) nreq, Bit#(32) bl, Bit#(8) be);
	  $dumpvars();
          $display("startWrite pointer=%d numWords=%d (%d) numReqs=%d burstLen=%d", pointer, nw, nreq*bl, nreq, bl);
          pointer <= wp;
          numWords  <= nw;
          burstLenBytes <= truncate(bl);
	  numReqs <= nreq;
	  numDone <= nreq;

	  reqOffset <= 0;
	  srcGens <= 3;
	  byteEnable <= be;
       endmethod
   endinterface
   interface dmaClients = vec(dmaClient);

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 Vector::*;
import BuildVector::*;
import FIFO::*;
import FIFOF::*;
import BRAMFIFO::*;
import ClientServer::*;
import GetPut::*;
import HostInterface::*;
import MemTypes::*;
import MemWriteEngine::*;
import Pipe::*;
import AddressGenerator::*;

typedef TDiv#(DataBusWidth,32) WordsPerBeat;

interface MemwriteRequest;
   method Action startWrite(Bit#(32) pointer, Bit#(32) numWords, Bit#(32) numReqs, Bit#(32) burstLen, Bit#(8) byteEnable);
endinterface

interface MemwriteIndication;
   method Action writeDone(Bit#(32) v);
   method Action writeProgress(Bit#(32) v);
endinterface

interface Memwrite;
   interface MemwriteRequest request;
   interface Vector#(1, MemWriteClient#(DataBusWidth)) dmaClients;
endinterface

module  mkMemwrite#(MemwriteIndication indication) (Memwrite);
   Reg#(SGLId)   pointer <- mkReg(0);
   Reg#(Bit#(32))        numReqs <- mkReg(0);
   Reg#(Bit#(32))        numDone <- mkReg(0);
   Reg#(Bit#(MemOffsetSize)) reqOffset <- mkReg(0);
   Reg#(Bit#(3))                   tag <- mkReg(0);
   Reg#(Bit#(32))             numWords <- mkReg(0);
   Reg#(Bit#(BurstLenSize)) burstLenBytes <- mkReg(0);
   Reg#(Bit#(32))              srcGens <- mkReg(3);
   Reg#(Bit#(8))            byteEnable <- mkReg('hff);

   AddressGenerator#(32, DataBusWidth) addrGenerator <- mkAddressGenerator();
   FIFO#(MemRequest) reqFifo <- mkSizedFIFO(4);
   FIFO#(PhysMemRequest#(32,DataBusWidth)) preqFifo <- mkSizedFIFO(4);
   FIFO#(MemData#(DataBusWidth))   dataFifo <- mkSizedBRAMFIFO(1024);
   FIFO#(Bit#(MemTagSize)) doneFifo <- mkSizedFIFO(4);

   let verboseProgress = False;

   Bit#(TDiv#(DataBusWidth,8)) firstbe = { 4'hf, byteEnable[3:0] };
   Bit#(TDiv#(DataBusWidth,8)) lastbe = { byteEnable[7:4], 4'hf };

   rule start if (numReqs != 0);
      reqFifo.enq(MemRequest { sglId: pointer, offset: reqOffset, burstLen: burstLenBytes, tag: extend(tag)
`ifdef BYTE_ENABLES
			      , firstbe: firstbe, lastbe: lastbe
`endif
			      });
      preqFifo.enq(PhysMemRequest { addr: 0, burstLen: burstLenBytes, tag: extend(tag)
`ifdef BYTE_ENABLES
				       , firstbe: firstbe, lastbe: lastbe
`endif
				   });
      numReqs <= numReqs - 1;
      reqOffset <= reqOffset + extend(burstLenBytes);
      tag <= tag + 1;
      //$display("start numReqs", numReqs);
   endrule

   rule preq;
      let preq <- toGet(preqFifo).get();
      addrGenerator.request.put(preq);
   endrule

   rule finish;
      let donetag <- toGet(doneFifo).get();
      //$display("finished num todo=%d", numDone);
      if (numDone == 1) begin
         indication.writeDone(0);
      end
      numDone <= numDone - 1;
      if (verboseProgress)
	 indication.writeProgress(extend(donetag));
   endrule

   rule src if (numWords != 0);
      let b <- addrGenerator.addrBeat.get();

      function Bit#(32) plusi(Integer i); return srcGens + fromInteger(i); endfunction
      Vector#(WordsPerBeat, Bit#(32)) v = genWith(plusi);
      dataFifo.enq(MemData { data: pack(v), tag: b.tag, last: b.last});
      srcGens <= srcGens+fromInteger(valueOf(WordsPerBeat));
      numWords <= numWords - fromInteger(valueOf(WordsPerBeat));
   endrule

   MemWriteClient#(DataBusWidth) dmaClient = (interface MemWriteClient;
      interface Get writeReq = toGet(reqFifo);
      interface Get writeData = toGet(dataFifo);
      interface Put writeDone = toPut(doneFifo);
   endinterface );

   interface MemwriteRequest request;
       method Action startWrite(Bit#(32) wp, Bit#(32) nw, Bit#(32) nreq, Bit#(32) bl, Bit#(8) be);
	  $dumpvars();
          $display("startWrite pointer=%d numWords=%d (%d) numReqs=%d burstLen=%d", pointer, nw, nreq*bl, nreq, bl);
          pointer <= wp;
          numWords  <= nw;
          burstLenBytes <= truncate(bl);
	  numReqs <= nreq;
	  numDone <= nreq;

	  reqOffset <= 0;
	  srcGens <= 3;
	  byteEnable <= be;
       endmethod
   endinterface
   interface dmaClients = vec(dmaClient);

endmodule


Added dependencies to Port typeclasses

Added dependencies to Port typeclasses

// Copyright (c) 2017 Massachusetts Institute of Technology

// 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.

/**
 * This package defines "Port" interfaces intended to replace `Get`, `Put`,
 * `Client`, and `Server`. The `InputPort` interface improves upon the `Put`
 * interface by adding a `canEnq` method. The `OutputPort` interface improves
 * upon the `Get` interfaces by separating `get` into `first` and `deq` methods
 * and also including a `canDeq` method.
 *
 * The `ServerPort` and `ClientPort` interfaces are replacements `Server` and
 * `Client` interfaces that use `InputPort` and `OutputPort` instead of `Get`
 * and `Put`.
 *
 * This package contains two ways to convert interfaces to `InputPort` and
 * `OutputPort`. The first way are the functions `toInputPort` and
 * `toOutputPort`. These functions are only defined for interfaces that can
 * be directly converted to `InputPort` or `OutputPort` with minimal logic.
 * The second way are the modules `mkInputPortBuffer`,
 * `mkInputPortBypassBuffer`, `mkOutputPortBuffer`, `mkOutputPortBypassBuffer`.
 * These modules add a buffers to the inputted interface to create `InputPort`
 * or `OutputPort` interfaces. Since these add buffers, they break the
 * atomicity of the action of the inputted interface.
 */

package Port;

import ClientServer::*;
import Connectable::*;
import Ehr::*;
import FIFOG::*;
import GetPut::*;

interface InputPort#(type t);
    method Action enq(t val);
    method Bool canEnq;
endinterface

interface OutputPort#(type t);
    method Bool canDeq;
    method t first;
    method Action deq;
endinterface

/// This is only a function because our documentation system cannot handle
/// top-level variable definitions. This function and other functions like it
/// can be used as if it was defined as if it were just a variable.
function InputPort#(t) nullInputPort;
    return (interface InputPort;
            method Action enq(t val) if (False);
                noAction;
            endmethod
            method canEnq;
                return False;
            endmethod
        endinterface);
endfunction

function OutputPort#(t) nullOutputPort;
    return (interface OutputPort;
            method t first if (False);
                return ?;
            endmethod
            method Action deq if (False);
                noAction;
            endmethod
            method Bool canDeq;
                return False;
            endmethod
        endinterface);
endfunction

interface ServerPort#(type req_t, type resp_t);
    interface InputPort#(req_t) request;
    interface OutputPort#(resp_t) response;
endinterface

interface ClientPort#(type req_t, type resp_t);
    interface OutputPort#(req_t) request;
    interface InputPort#(resp_t) response;
endinterface

function ServerPort#(req_t, resp_t) nullServerPort;
    return (interface ServerPort;
            interface InputPort request = nullInputPort;
            interface OutputPort response = nullOutputPort;
        endinterface);
endfunction

function ClientPort#(req_t, resp_t) nullClientPort;
    return (interface ClientPort;
            interface OutputPort request = nullOutputPort;
            interface InputPort response = nullInputPort;
        endinterface);
endfunction

typeclass ToInputPort#(type in_t, type port_t) dependencies (in_t determines port_t);
    function InputPort#(port_t) toInputPort(in_t x);
endtypeclass

typeclass ToOutputPort#(type in_t, type port_t) dependencies (in_t determines port_t);
    function OutputPort#(port_t) toOutputPort(in_t x);
endtypeclass

typeclass MkInputPortBuffer#(type in_t, type port_t) dependencies (in_t determines port_t);
    module mkInputPortBuffer#(in_t x)(InputPort#(port_t));
    module mkInputPortBypassBuffer#(in_t x)(InputPort#(port_t));
endtypeclass

typeclass MkOutputPortBuffer#(type in_t, type port_t) dependencies (in_t determines port_t);
    module mkOutputPortBuffer#(in_t x)(OutputPort#(port_t));
    module mkOutputPortBypassBuffer#(in_t x)(OutputPort#(port_t));
endtypeclass

// Instances
instance Connectable#(OutputPort#(t), InputPort#(t));
    module mkConnection#(OutputPort#(t) a, InputPort#(t) b)(Empty);
        rule connection;
            a.deq();
            b.enq(a.first);
        endrule
    endmodule
endinstance

instance Connectable#(InputPort#(t), OutputPort#(t));
    module mkConnection#(InputPort#(t) a, OutputPort#(t) b)(Empty);
        rule connection;
            b.deq();
            a.enq(b.first);
        endrule
    endmodule
endinstance

instance Connectable#(ServerPort#(req_t, resp_t), ClientPort#(req_t, resp_t));
    module mkConnection#(ServerPort#(req_t, resp_t) a, ClientPort#(req_t, resp_t) b)(Empty);
        mkConnection(a.request, b.request);
        mkConnection(a.response, b.response);
    endmodule
endinstance

instance Connectable#(ClientPort#(req_t, resp_t), ServerPort#(req_t, resp_t));
    module mkConnection#(ClientPort#(req_t, resp_t) a, ServerPort#(req_t, resp_t) b)(Empty);
        mkConnection(a.request, b.request);
        mkConnection(a.response, b.response);
    endmodule
endinstance

// connecting with Put#(t)
instance Connectable#(OutputPort#(t), Put#(t));
    module mkConnection#(OutputPort#(t) a, Put#(t) b)(Empty);
        rule connection;
            a.deq();
            b.put(a.first);
        endrule
    endmodule
endinstance

instance Connectable#(Put#(t), OutputPort#(t));
    module mkConnection#(Put#(t) a, OutputPort#(t) b)(Empty);
        rule connection;
            b.deq();
            a.put(b.first);
        endrule
    endmodule
endinstance

// connecting with Get#(t)
instance Connectable#(Get#(t), InputPort#(t));
    module mkConnection#(Get#(t) a, InputPort#(t) b)(Empty);
        rule connection;
            let val <- a.get();
            b.enq(val);
        endrule
    endmodule
endinstance

instance Connectable#(InputPort#(t), Get#(t));
    module mkConnection#(InputPort#(t) a, Get#(t) b)(Empty);
        rule connection;
            let val <- b.get();
            a.enq(val);
        endrule
    endmodule
endinstance

// connecting with Client#(req_t,resp_t)
instance Connectable#(ServerPort#(req_t, resp_t), Client#(req_t, resp_t));
    module mkConnection#(ServerPort#(req_t, resp_t) a, Client#(req_t, resp_t) b)(Empty);
        mkConnection(a.request, b.request);
        mkConnection(a.response, b.response);
    endmodule
endinstance

instance Connectable#(Client#(req_t, resp_t), ServerPort#(req_t, resp_t));
    module mkConnection#(Client#(req_t, resp_t) a, ServerPort#(req_t, resp_t) b)(Empty);
        mkConnection(a.request, b.request);
        mkConnection(a.response, b.response);
    endmodule
endinstance

// connecting with Server#(req_t,resp_t)
instance Connectable#(Server#(req_t, resp_t), ClientPort#(req_t, resp_t));
    module mkConnection#(Server#(req_t, resp_t) a, ClientPort#(req_t, resp_t) b)(Empty);
        mkConnection(a.request, b.request);
        mkConnection(a.response, b.response);
    endmodule
endinstance

instance Connectable#(ClientPort#(req_t, resp_t), Server#(req_t, resp_t));
    module mkConnection#(ClientPort#(req_t, resp_t) a, Server#(req_t, resp_t) b)(Empty);
        mkConnection(a.request, b.request);
        mkConnection(a.response, b.response);
    endmodule
endinstance

instance ToInputPort#(FIFOG#(port_t), port_t);
    function InputPort#(port_t) toInputPort(FIFOG#(port_t) x);
        return (interface InputPort;
                method Action enq(port_t val);
                    x.enq(val);
                endmethod
                method Bool canEnq();
                    return x.canEnq();
                endmethod
            endinterface);
    endfunction
endinstance

instance ToOutputPort#(FIFOG#(port_t), port_t);
    function OutputPort#(port_t) toOutputPort(FIFOG#(port_t) x);
        return (interface OutputPort;
                method Bool canDeq();
                    return x.canDeq();
                endmethod
                method port_t first();
                    return x.first();
                endmethod
                method Action deq();
                    x.deq();
                endmethod
            endinterface);
    endfunction
endinstance

// If you can do toInputPort(x), you can do mkInputPortBuffer(x)
instance MkInputPortBuffer#(in_t, port_t) provisos (ToInputPort#(in_t, port_t));
    module mkInputPortBuffer#(in_t x)(InputPort#(port_t));
        return toInputPort(x);
    endmodule
    module mkInputPortBypassBuffer#(in_t x)(InputPort#(port_t));
        return toInputPort(x);
    endmodule
endinstance

// If you can do toOutputPort(x), you can do mkOutputPortBuffer(x)
instance MkOutputPortBuffer#(in_t, port_t) provisos (ToOutputPort#(in_t, port_t));
    module mkOutputPortBuffer#(in_t x)(OutputPort#(port_t));
        return toOutputPort(x);
    endmodule
    module mkOutputPortBypassBuffer#(in_t x)(OutputPort#(port_t));
        return toOutputPort(x);
    endmodule
endinstance

instance MkInputPortBuffer#(Put#(t), t) provisos (Bits#(t, tSz));
    module mkInputPortBuffer#(Put#(t) x)(InputPort#(t));
        Ehr#(2, Maybe#(t)) put_buffer <- mkEhr(tagged Invalid);

        rule doPut(put_buffer[0] matches tagged Valid .val);
            x.put(val);
            put_buffer[0] <= tagged Invalid;
        endrule

        method Action enq(t val) if (!isValid(put_buffer[1]));
            put_buffer[1] <= tagged Valid val;
        endmethod

        method Bool canEnq();
            return !isValid(put_buffer[1]);
        endmethod
    endmodule
    module mkInputPortBypassBuffer#(Put#(t) x)(InputPort#(t));
        Ehr#(2, Maybe#(t)) put_buffer <- mkEhr(tagged Invalid);

        rule doPut(put_buffer[1] matches tagged Valid .val);
            x.put(val);
            put_buffer[1] <= tagged Invalid;
        endrule

        method Action enq(t val) if (!isValid(put_buffer[0]));
            put_buffer[0] <= tagged Valid val;
        endmethod

        method Bool canEnq();
            return !isValid(put_buffer[0]);
        endmethod
    endmodule
endinstance

instance MkOutputPortBuffer#(Get#(t), t) provisos (Bits#(t, tSz));
    module mkOutputPortBuffer#(Get#(t) x)(OutputPort#(t));
        Ehr#(2, Maybe#(t)) get_buffer <- mkEhr(tagged Invalid);

        rule doGet(!isValid(get_buffer[1]));
            let val <- x.get();
            get_buffer[1] <= tagged Valid val;
        endrule

        method Bool canDeq();
            return isValid(get_buffer[0]);
        endmethod
        method t first() if (get_buffer[0] matches tagged Valid .val);
            return val;
        endmethod
        method Action deq() if (isValid(get_buffer[0]));
            get_buffer[0] <= tagged Invalid;
        endmethod
    endmodule
    module mkOutputPortBypassBuffer#(Get#(t) x)(OutputPort#(t));
        Ehr#(2, Maybe#(t)) get_buffer <- mkEhr(tagged Invalid);

        rule doGet(!isValid(get_buffer[0]));
            let val <- x.get();
            get_buffer[0] <= tagged Valid val;
        endrule

        method Bool canDeq();
            return isValid(get_buffer[1]);
        endmethod
        method t first() if (get_buffer[1] matches tagged Valid .val);
            return val;
        endmethod
        method Action deq() if (isValid(get_buffer[1]));
            get_buffer[1] <= tagged Invalid;
        endmethod
    endmodule
endinstance

typeclass ToServerPort#(type req_ifc_t, type resp_ifc_t, type req_t, type resp_t) dependencies ((req_ifc_t, resp_ifc_t) determines (req_t, resp_t));
    function ServerPort#(req_t, resp_t) toServerPort(req_ifc_t req_ifc, resp_ifc_t resp_ifc);
endtypeclass

instance ToServerPort#(InputPort#(req_t), OutputPort#(resp_t), req_t, resp_t);
    function ServerPort#(req_t, resp_t) toServerPort(InputPort#(req_t) req_ifc, OutputPort#(resp_t) resp_ifc);
        return (interface ServerPort;
                    interface InputPort request = req_ifc;
                    interface OutputPort response = resp_ifc;
                endinterface);
    endfunction
endinstance

instance ToServerPort#(req_ifc_t, resp_ifc_t, req_t, resp_t) provisos (ToInputPort#(req_ifc_t, req_t), ToOutputPort#(resp_ifc_t, resp_t));
    function ServerPort#(req_t, resp_t) toServerPort(req_ifc_t req_ifc, resp_ifc_t resp_ifc);
        return (interface ServerPort;
                    interface InputPort request = toInputPort(req_ifc);
                    interface OutputPort response = toOutputPort(resp_ifc);
                endinterface);
    endfunction
endinstance

typeclass ToClientPort#(type req_ifc_t, type resp_ifc_t, type req_t, type resp_t) dependencies ((req_ifc_t, resp_ifc_t) determines (req_t, resp_t));
    function ClientPort#(req_t, resp_t) toClientPort(req_ifc_t req_ifc, resp_ifc_t resp_ifc);
endtypeclass

instance ToClientPort#(OutputPort#(req_t), InputPort#(resp_t), req_t, resp_t);
    function ClientPort#(req_t, resp_t) toClientPort(OutputPort#(req_t) req_ifc, InputPort#(resp_t) resp_ifc);
        return (interface ClientPort;
                    interface OutputPort request = req_ifc;
                    interface InputPort response = resp_ifc;
                endinterface);
    endfunction
endinstance

instance ToClientPort#(req_ifc_t, resp_ifc_t, req_t, resp_t) provisos (ToOutputPort#(req_ifc_t, req_t), ToInputPort#(resp_ifc_t, resp_t));
    function ClientPort#(req_t, resp_t) toClientPort(req_ifc_t req_ifc, resp_ifc_t resp_ifc);
        return (interface ClientPort;
                    interface OutputPort request = toOutputPort(req_ifc);
                    interface InputPort response = toInputPort(resp_ifc);
                endinterface);
    endfunction
endinstance

endpackage

// Copyright (c) 2017 Massachusetts Institute of Technology

// 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.

/**
 * This package defines "Port" interfaces intended to replace `Get`, `Put`,
 * `Client`, and `Server`. The `InputPort` interface improves upon the `Put`
 * interface by adding a `canEnq` method. The `OutputPort` interface improves
 * upon the `Get` interfaces by separating `get` into `first` and `deq` methods
 * and also including a `canDeq` method.
 *
 * The `ServerPort` and `ClientPort` interfaces are replacements `Server` and
 * `Client` interfaces that use `InputPort` and `OutputPort` instead of `Get`
 * and `Put`.
 *
 * This package contains two ways to convert interfaces to `InputPort` and
 * `OutputPort`. The first way are the functions `toInputPort` and
 * `toOutputPort`. These functions are only defined for interfaces that can
 * be directly converted to `InputPort` or `OutputPort` with minimal logic.
 * The second way are the modules `mkInputPortBuffer`,
 * `mkInputPortBypassBuffer`, `mkOutputPortBuffer`, `mkOutputPortBypassBuffer`.
 * These modules add a buffers to the inputted interface to create `InputPort`
 * or `OutputPort` interfaces. Since these add buffers, they break the
 * atomicity of the action of the inputted interface.
 */

package Port;

import ClientServer::*;
import Connectable::*;
import Ehr::*;
import FIFOG::*;
import GetPut::*;

interface InputPort#(type t);
    method Action enq(t val);
    method Bool canEnq;
endinterface

interface OutputPort#(type t);
    method Bool canDeq;
    method t first;
    method Action deq;
endinterface

/// This is only a function because our documentation system cannot handle
/// top-level variable definitions. This function and other functions like it
/// can be used as if it was defined as if it were just a variable.
function InputPort#(t) nullInputPort;
    return (interface InputPort;
            method Action enq(t val) if (False);
                noAction;
            endmethod
            method canEnq;
                return False;
            endmethod
        endinterface);
endfunction

function OutputPort#(t) nullOutputPort;
    return (interface OutputPort;
            method t first if (False);
                return ?;
            endmethod
            method Action deq if (False);
                noAction;
            endmethod
            method Bool canDeq;
                return False;
            endmethod
        endinterface);
endfunction

interface ServerPort#(type req_t, type resp_t);
    interface InputPort#(req_t) request;
    interface OutputPort#(resp_t) response;
endinterface

interface ClientPort#(type req_t, type resp_t);
    interface OutputPort#(req_t) request;
    interface InputPort#(resp_t) response;
endinterface

function ServerPort#(req_t, resp_t) nullServerPort;
    return (interface ServerPort;
            interface InputPort request = nullInputPort;
            interface OutputPort response = nullOutputPort;
        endinterface);
endfunction

function ClientPort#(req_t, resp_t) nullClientPort;
    return (interface ClientPort;
            interface OutputPort request = nullOutputPort;
            interface InputPort response = nullInputPort;
        endinterface);
endfunction

typeclass ToInputPort#(type in_t, type port_t);
    function InputPort#(port_t) toInputPort(in_t x);
endtypeclass

typeclass ToOutputPort#(type in_t, type port_t);
    function OutputPort#(port_t) toOutputPort(in_t x);
endtypeclass

typeclass MkInputPortBuffer#(type in_t, type port_t);
    module mkInputPortBuffer#(in_t x)(InputPort#(port_t));
    module mkInputPortBypassBuffer#(in_t x)(InputPort#(port_t));
endtypeclass

typeclass MkOutputPortBuffer#(type in_t, type port_t);
    module mkOutputPortBuffer#(in_t x)(OutputPort#(port_t));
    module mkOutputPortBypassBuffer#(in_t x)(OutputPort#(port_t));
endtypeclass

// Instances
instance Connectable#(OutputPort#(t), InputPort#(t));
    module mkConnection#(OutputPort#(t) a, InputPort#(t) b)(Empty);
        rule connection;
            a.deq();
            b.enq(a.first);
        endrule
    endmodule
endinstance

instance Connectable#(InputPort#(t), OutputPort#(t));
    module mkConnection#(InputPort#(t) a, OutputPort#(t) b)(Empty);
        rule connection;
            b.deq();
            a.enq(b.first);
        endrule
    endmodule
endinstance

instance Connectable#(ServerPort#(req_t, resp_t), ClientPort#(req_t, resp_t));
    module mkConnection#(ServerPort#(req_t, resp_t) a, ClientPort#(req_t, resp_t) b)(Empty);
        mkConnection(a.request, b.request);
        mkConnection(a.response, b.response);
    endmodule
endinstance

instance Connectable#(ClientPort#(req_t, resp_t), ServerPort#(req_t, resp_t));
    module mkConnection#(ClientPort#(req_t, resp_t) a, ServerPort#(req_t, resp_t) b)(Empty);
        mkConnection(a.request, b.request);
        mkConnection(a.response, b.response);
    endmodule
endinstance

// connecting with Put#(t)
instance Connectable#(OutputPort#(t), Put#(t));
    module mkConnection#(OutputPort#(t) a, Put#(t) b)(Empty);
        rule connection;
            a.deq();
            b.put(a.first);
        endrule
    endmodule
endinstance

instance Connectable#(Put#(t), OutputPort#(t));
    module mkConnection#(Put#(t) a, OutputPort#(t) b)(Empty);
        rule connection;
            b.deq();
            a.put(b.first);
        endrule
    endmodule
endinstance

// connecting with Get#(t)
instance Connectable#(Get#(t), InputPort#(t));
    module mkConnection#(Get#(t) a, InputPort#(t) b)(Empty);
        rule connection;
            let val <- a.get();
            b.enq(val);
        endrule
    endmodule
endinstance

instance Connectable#(InputPort#(t), Get#(t));
    module mkConnection#(InputPort#(t) a, Get#(t) b)(Empty);
        rule connection;
            let val <- b.get();
            a.enq(val);
        endrule
    endmodule
endinstance

// connecting with Client#(req_t,resp_t)
instance Connectable#(ServerPort#(req_t, resp_t), Client#(req_t, resp_t));
    module mkConnection#(ServerPort#(req_t, resp_t) a, Client#(req_t, resp_t) b)(Empty);
        mkConnection(a.request, b.request);
        mkConnection(a.response, b.response);
    endmodule
endinstance

instance Connectable#(Client#(req_t, resp_t), ServerPort#(req_t, resp_t));
    module mkConnection#(Client#(req_t, resp_t) a, ServerPort#(req_t, resp_t) b)(Empty);
        mkConnection(a.request, b.request);
        mkConnection(a.response, b.response);
    endmodule
endinstance

// connecting with Server#(req_t,resp_t)
instance Connectable#(Server#(req_t, resp_t), ClientPort#(req_t, resp_t));
    module mkConnection#(Server#(req_t, resp_t) a, ClientPort#(req_t, resp_t) b)(Empty);
        mkConnection(a.request, b.request);
        mkConnection(a.response, b.response);
    endmodule
endinstance

instance Connectable#(ClientPort#(req_t, resp_t), Server#(req_t, resp_t));
    module mkConnection#(ClientPort#(req_t, resp_t) a, Server#(req_t, resp_t) b)(Empty);
        mkConnection(a.request, b.request);
        mkConnection(a.response, b.response);
    endmodule
endinstance

instance ToInputPort#(FIFOG#(port_t), port_t);
    function InputPort#(port_t) toInputPort(FIFOG#(port_t) x);
        return (interface InputPort;
                method Action enq(port_t val);
                    x.enq(val);
                endmethod
                method Bool canEnq();
                    return x.canEnq();
                endmethod
            endinterface);
    endfunction
endinstance

instance ToOutputPort#(FIFOG#(port_t), port_t);
    function OutputPort#(port_t) toOutputPort(FIFOG#(port_t) x);
        return (interface OutputPort;
                method Bool canDeq();
                    return x.canDeq();
                endmethod
                method port_t first();
                    return x.first();
                endmethod
                method Action deq();
                    x.deq();
                endmethod
            endinterface);
    endfunction
endinstance

// If you can do toInputPort(x), you can do mkInputPortBuffer(x)
instance MkInputPortBuffer#(in_t, port_t) provisos (ToInputPort#(in_t, port_t));
    module mkInputPortBuffer#(in_t x)(InputPort#(port_t));
        return toInputPort(x);
    endmodule
    module mkInputPortBypassBuffer#(in_t x)(InputPort#(port_t));
        return toInputPort(x);
    endmodule
endinstance

// If you can do toOutputPort(x), you can do mkOutputPortBuffer(x)
instance MkOutputPortBuffer#(in_t, port_t) provisos (ToOutputPort#(in_t, port_t));
    module mkOutputPortBuffer#(in_t x)(OutputPort#(port_t));
        return toOutputPort(x);
    endmodule
    module mkOutputPortBypassBuffer#(in_t x)(OutputPort#(port_t));
        return toOutputPort(x);
    endmodule
endinstance

instance MkInputPortBuffer#(Put#(t), t) provisos (Bits#(t, tSz));
    module mkInputPortBuffer#(Put#(t) x)(InputPort#(t));
        Ehr#(2, Maybe#(t)) put_buffer <- mkEhr(tagged Invalid);

        rule doPut(put_buffer[0] matches tagged Valid .val);
            x.put(val);
            put_buffer[0] <= tagged Invalid;
        endrule

        method Action enq(t val) if (!isValid(put_buffer[1]));
            put_buffer[1] <= tagged Valid val;
        endmethod

        method Bool canEnq();
            return !isValid(put_buffer[1]);
        endmethod
    endmodule
    module mkInputPortBypassBuffer#(Put#(t) x)(InputPort#(t));
        Ehr#(2, Maybe#(t)) put_buffer <- mkEhr(tagged Invalid);

        rule doPut(put_buffer[1] matches tagged Valid .val);
            x.put(val);
            put_buffer[1] <= tagged Invalid;
        endrule

        method Action enq(t val) if (!isValid(put_buffer[0]));
            put_buffer[0] <= tagged Valid val;
        endmethod

        method Bool canEnq();
            return !isValid(put_buffer[0]);
        endmethod
    endmodule
endinstance

instance MkOutputPortBuffer#(Get#(t), t) provisos (Bits#(t, tSz));
    module mkOutputPortBuffer#(Get#(t) x)(OutputPort#(t));
        Ehr#(2, Maybe#(t)) get_buffer <- mkEhr(tagged Invalid);

        rule doGet(!isValid(get_buffer[1]));
            let val <- x.get();
            get_buffer[1] <= tagged Valid val;
        endrule

        method Bool canDeq();
            return isValid(get_buffer[0]);
        endmethod
        method t first() if (get_buffer[0] matches tagged Valid .val);
            return val;
        endmethod
        method Action deq() if (isValid(get_buffer[0]));
            get_buffer[0] <= tagged Invalid;
        endmethod
    endmodule
    module mkOutputPortBypassBuffer#(Get#(t) x)(OutputPort#(t));
        Ehr#(2, Maybe#(t)) get_buffer <- mkEhr(tagged Invalid);

        rule doGet(!isValid(get_buffer[0]));
            let val <- x.get();
            get_buffer[0] <= tagged Valid val;
        endrule

        method Bool canDeq();
            return isValid(get_buffer[1]);
        endmethod
        method t first() if (get_buffer[1] matches tagged Valid .val);
            return val;
        endmethod
        method Action deq() if (isValid(get_buffer[1]));
            get_buffer[1] <= tagged Invalid;
        endmethod
    endmodule
endinstance

typeclass ToServerPort#(type req_ifc_t, type resp_ifc_t, type req_t, type resp_t);
    function ServerPort#(req_t, resp_t) toServerPort(req_ifc_t req_ifc, resp_ifc_t resp_ifc);
endtypeclass

instance ToServerPort#(InputPort#(req_t), OutputPort#(resp_t), req_t, resp_t);
    function ServerPort#(req_t, resp_t) toServerPort(InputPort#(req_t) req_ifc, OutputPort#(resp_t) resp_ifc);
        return (interface ServerPort;
                    interface InputPort request = req_ifc;
                    interface OutputPort response = resp_ifc;
                endinterface);
    endfunction
endinstance

instance ToServerPort#(req_ifc_t, resp_ifc_t, req_t, resp_t) provisos (ToInputPort#(req_ifc_t, req_t), ToOutputPort#(resp_ifc_t, resp_t));
    function ServerPort#(req_t, resp_t) toServerPort(req_ifc_t req_ifc, resp_ifc_t resp_ifc);
        return (interface ServerPort;
                    interface InputPort request = toInputPort(req_ifc);
                    interface OutputPort response = toOutputPort(resp_ifc);
                endinterface);
    endfunction
endinstance

typeclass ToClientPort#(type req_ifc_t, type resp_ifc_t, type req_t, type resp_t);
    function ClientPort#(req_t, resp_t) toClientPort(req_ifc_t req_ifc, resp_ifc_t resp_ifc);
endtypeclass

instance ToClientPort#(OutputPort#(req_t), InputPort#(resp_t), req_t, resp_t);
    function ClientPort#(req_t, resp_t) toClientPort(OutputPort#(req_t) req_ifc, InputPort#(resp_t) resp_ifc);
        return (interface ClientPort;
                    interface OutputPort request = req_ifc;
                    interface InputPort response = resp_ifc;
                endinterface);
    endfunction
endinstance

instance ToClientPort#(req_ifc_t, resp_ifc_t, req_t, resp_t) provisos (ToOutputPort#(req_ifc_t, req_t), ToInputPort#(resp_ifc_t, resp_t));
    function ClientPort#(req_t, resp_t) toClientPort(req_ifc_t req_ifc, resp_ifc_t resp_ifc);
        return (interface ClientPort;
                    interface OutputPort request = toOutputPort(req_ifc);
                    interface InputPort response = toInputPort(resp_ifc);
                endinterface);
    endfunction
endinstance

endpackage


added 250mhz clock to pcie endpoint interface

////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2012  Bluespec, Inc.  ALL RIGHTS RESERVED.
////////////////////////////////////////////////////////////////////////////////
//  Filename      : XbsvXilinx7PCIE.bsv
//  Description   :
////////////////////////////////////////////////////////////////////////////////
package PcieEndpointX7;

import Clocks            ::*;
import Vector            ::*;
import Connectable       ::*;
import GetPut            ::*;
import Reserved          ::*;
import TieOff            ::*;
import DefaultValue      ::*;
import DReg              ::*;
import Gearbox           ::*;
import FIFO              ::*;
import FIFOF             ::*;
import SpecialFIFOs      ::*;
import ClientServer      ::*;

import XbsvXilinxCells   ::*;
import XilinxCells       ::*;
import PCIE              ::*;
import PCIEWRAPPER       ::*;
import Bufgctrl           ::*;
import PcieGearbox       :: *;

(* always_ready, always_enabled *)
interface PCIE_X7#(numeric type lanes);
   interface PciewrapPci_exp#(lanes)   pcie;
   interface PciewrapUser#(lanes)      user;
   interface PciewrapFc#(lanes)        fc;
   interface PciewrapTx#(lanes)        tx;
   interface PciewrapS_axis_tx#(lanes) s_axis_tx;
   interface PciewrapM_axis_rx#(lanes) m_axis_rx;
   interface PciewrapRx#(lanes)        rx;
   interface PciewrapCfg#(lanes)       cfg;
   method    Action                    cfg_dsn(Bit#(64) i);
   interface Clock                     pipe_txoutclk_out;
   method    Action                    pipe_mmcm_lock_in(Bit#(1) v);
   method    Bit#(lanes)               pipe_pclk_sel_out();
endinterface

import "BVI" pcie_7x_0 =
module vMkXilinx7PCIExpress#(PCIEParams params, Clock clk_125mhz, Clock pipe_userclk1_in, Clock pclk_in)(PCIE_X7#(lanes))
   provisos( Add#(1, z, lanes));
   let sys_rst_n <- exposeCurrentReset;

   default_clock clk(sys_clk); // 100 MHz refclk
   default_reset rstn(sys_rst_n) = sys_rst_n;
   input_clock clk_125mhz(pipe_dclk_in) = clk_125mhz;
   input_clock clk_oobclk_in(pipe_oobclk_in) = clk_125mhz;
   input_clock pipe_userclk1_in(pipe_userclk1_in) = pipe_userclk1_in;
   input_clock pipe_userclk2_in(pipe_userclk2_in) = pipe_userclk1_in;
   input_clock pclk_in(pipe_pclk_in) = pclk_in;
   input_clock pclk_usrin(pipe_rxusrclk_in) = pclk_in;
   method pipe_mmcm_lock_in(pipe_mmcm_lock_in) enable((*inhigh*)en_pipe_mmcm_lock_in);
   method pipe_pclk_sel_out pipe_pclk_sel_out   clocked_by(pclk_in);

   interface PciewrapPci_exp pcie;
      method                  rxp(pci_exp_rxp) enable((*inhigh*)en0)    reset_by(no_reset);
      method                  rxn(pci_exp_rxn) enable((*inhigh*)en1)    reset_by(no_reset);
      method pci_exp_txp      txp    reset_by(no_reset);
      method pci_exp_txn      txn    reset_by(no_reset);
   endinterface

   interface PciewrapUser     user;
      output_clock            clk_out(user_clk_out);
      output_reset    reset_out(user_reset_out);
      method user_lnk_up      lnk_up   clocked_by(no_clock) reset_by(no_reset); /* semi-static */
      method user_app_rdy     app_rdy   clocked_by(no_clock) reset_by(no_reset);
   endinterface
    interface PciewrapFc     fc;
      method fc_ph            ph   clocked_by(user_clk_out)    reset_by(no_reset);
      method fc_pd            pd   clocked_by(user_clk_out)    reset_by(no_reset);
      method fc_nph           nph   clocked_by(user_clk_out)    reset_by(no_reset);
      method fc_npd           npd   clocked_by(user_clk_out)    reset_by(no_reset);
      method fc_cplh          cplh   clocked_by(user_clk_out)    reset_by(no_reset);
      method fc_cpld          cpld   clocked_by(user_clk_out)    reset_by(no_reset);
      method                  sel(fc_sel)    enable((*inhigh*)en01)   clocked_by(user_clk_out)    reset_by(no_reset);
   endinterface

   interface PciewrapTx     tx;
      method tx_buf_av        buf_av   clocked_by(user_clk_out)    reset_by(no_reset);
      method tx_err_drop      err_drop   clocked_by(user_clk_out)    reset_by(no_reset);
      method tx_cfg_req       cfg_req   clocked_by(user_clk_out)    reset_by(no_reset);
      method                  cfg_gnt(tx_cfg_gnt)    enable((*inhigh*)en07)   clocked_by(user_clk_out)    reset_by(no_reset);
   endinterface

    interface PciewrapS_axis_tx     s_axis_tx;
      method                  tlast(s_axis_tx_tlast)    enable((*inhigh*)en02)   clocked_by(user_clk_out)    reset_by(no_reset);
      method                  tdata(s_axis_tx_tdata)    enable((*inhigh*)en03)   clocked_by(user_clk_out)    reset_by(no_reset);
      method                  tkeep(s_axis_tx_tkeep)    enable((*inhigh*)en04)   clocked_by(user_clk_out)    reset_by(no_reset);
      method                  tvalid(s_axis_tx_tvalid)    enable((*inhigh*)en05)   clocked_by(user_clk_out)    reset_by(no_reset);
      method                  tuser(s_axis_tx_tuser)    enable((*inhigh*)en06)   clocked_by(user_clk_out)    reset_by(no_reset);
      method s_axis_tx_tready tready   clocked_by(user_clk_out)    reset_by(no_reset);
   endinterface

    interface PciewrapM_axis_rx     m_axis_rx;
      method m_axis_rx_tlast  tlast   clocked_by(user_clk_out)    reset_by(no_reset);
      method m_axis_rx_tdata  tdata   clocked_by(user_clk_out)    reset_by(no_reset);
      method m_axis_rx_tkeep  tkeep   clocked_by(user_clk_out)    reset_by(no_reset);
      method m_axis_rx_tuser  tuser   clocked_by(user_clk_out)    reset_by(no_reset);
      method m_axis_rx_tvalid tvalid   clocked_by(user_clk_out)    reset_by(no_reset);
      method                  tready(m_axis_rx_tready)    enable((*inhigh*)en08)   clocked_by(user_clk_out)    reset_by(no_reset);
   endinterface
   interface PciewrapRx     rx;
      method                  np_ok(rx_np_ok)    enable((*inhigh*)en09)   clocked_by(user_clk_out)    reset_by(no_reset);
      method                  np_req(rx_np_req)    enable((*inhigh*)en10)   clocked_by(user_clk_out)    reset_by(no_reset);
   endinterface

   method                    cfg_dsn(cfg_dsn)    enable((*inhigh*)en25)   clocked_by(user_clk_out);

   interface PciewrapCfg     cfg;
      method cfg_bus_number      bus_number   clocked_by(no_clock) reset_by(no_reset);
      method cfg_device_number   device_number   clocked_by(no_clock) reset_by(no_reset);
      method cfg_function_number function_number   clocked_by(no_clock) reset_by(no_reset);
      method cfg_lcommand        lcommand   clocked_by(user_clk_out) reset_by(no_reset);
      method                     interrupt(cfg_interrupt)    enable((*inhigh*)en32)   clocked_by(user_clk_out) reset_by(no_reset);

      method cfg_bridge_serr_en bridge_serr_en();
      method cfg_command command();
      method cfg_dcommand dcommand();
      method cfg_dcommand2 dcommand2();
      method cfg_lstatus lstatus();
      method cfg_pcie_link_state pcie_link_state();
      method pciecap_interrupt_msgnum(cfg_pciecap_interrupt_msgnum) enable((*inhigh*) EN_cfg_pciecap_interrupt_msgnum);
      method cfg_received_func_lvl_rst received_func_lvl_rst();
      method cfg_slot_control_electromech_il_ctl_pulse slot_control_electromech_il_ctl_pulse();
      method cfg_status status();
      method cfg_to_turnoff to_turnoff();
      method trn_pending(cfg_trn_pending) enable((*inhigh*) EN_cfg_trn_pending);
      method turnoff_ok(cfg_turnoff_ok) enable((*inhigh*) EN_cfg_turnoff_ok);
      method cfg_vc_tcvc_map vc_tcvc_map();
   endinterface

   output_clock pipe_txoutclk_out(pipe_txoutclk_out);

   schedule (user_lnk_up, user_app_rdy, fc_ph, fc_pd, fc_nph, fc_npd, fc_cplh, fc_cpld, fc_sel, s_axis_tx_tlast,
	     s_axis_tx_tdata, s_axis_tx_tkeep, s_axis_tx_tvalid, s_axis_tx_tready, s_axis_tx_tuser, tx_buf_av, tx_err_drop,
	     tx_cfg_req, tx_cfg_gnt, m_axis_rx_tlast, m_axis_rx_tdata, m_axis_rx_tkeep, m_axis_rx_tuser, m_axis_rx_tvalid,
	     m_axis_rx_tready, rx_np_ok, rx_np_req,
	     cfg_bus_number, cfg_device_number, cfg_function_number, cfg_lcommand,
cfg_command, cfg_dcommand, cfg_dcommand2, cfg_lstatus, cfg_pcie_link_state, cfg_received_func_lvl_rst, cfg_status, cfg_to_turnoff, cfg_vc_tcvc_map,
cfg_bridge_serr_en, cfg_slot_control_electromech_il_ctl_pulse,
cfg_pciecap_interrupt_msgnum, cfg_trn_pending, cfg_turnoff_ok,
cfg_interrupt, cfg_dsn,
	     pcie_txp, pcie_txn, pcie_rxp, pcie_rxn, pipe_mmcm_lock_in, pipe_pclk_sel_out
	     ) CF
            (user_lnk_up, user_app_rdy, fc_ph, fc_pd, fc_nph, fc_npd, fc_cplh, fc_cpld, fc_sel, s_axis_tx_tlast,
	     s_axis_tx_tdata, s_axis_tx_tkeep, s_axis_tx_tvalid, s_axis_tx_tready, s_axis_tx_tuser, tx_buf_av, tx_err_drop,
	     tx_cfg_req, tx_cfg_gnt, m_axis_rx_tlast, m_axis_rx_tdata, m_axis_rx_tkeep, m_axis_rx_tuser, m_axis_rx_tvalid,
	     m_axis_rx_tready, rx_np_ok, rx_np_req,
	     cfg_bus_number, cfg_device_number, cfg_function_number, cfg_lcommand,
cfg_command, cfg_dcommand, cfg_dcommand2, cfg_lstatus, cfg_pcie_link_state, cfg_received_func_lvl_rst, cfg_status, cfg_to_turnoff, cfg_vc_tcvc_map,
cfg_bridge_serr_en, cfg_slot_control_electromech_il_ctl_pulse,
cfg_pciecap_interrupt_msgnum, cfg_trn_pending, cfg_turnoff_ok,
cfg_interrupt, cfg_dsn,
	     pcie_txp, pcie_txn, pcie_rxp, pcie_rxn, pipe_mmcm_lock_in, pipe_pclk_sel_out
             );

endmodule: vMkXilinx7PCIExpress

////////////////////////////////////////////////////////////////////////////////
/// Interfaces
////////////////////////////////////////////////////////////////////////////////

interface PcieEndpointX7#(numeric type lanes);
   interface PciewrapPci_exp#(lanes)   pcie;
   interface PciewrapUser#(lanes)      user;
   interface PciewrapCfg#(lanes)       cfg;
   interface Server#(TLPData#(16), TLPData#(16)) tlp;
   interface Clock epClock125;
   interface Reset epReset125;
   interface Clock epClock250;
   interface Reset epReset250;
endinterface

typedef struct {
   Bit#(22)      user;
   Bit#(1)       last;
   Bit#(8)       keep;
   Bit#(64)      data;
} AxiRx deriving (Bits, Eq);

typedef struct {
   Bit#(1)       last;
   Bit#(8)       keep;
   Bit#(64)      data;
} AxiTx deriving (Bits, Eq);

`ifdef Artix7
typedef 4 PcieLanes;
typedef 4 NumLeds;
`else
typedef 8 PcieLanes;
typedef 8 NumLeds;
`endif

(* synthesize *)
module mkPcieEndpointX7(PcieEndpointX7#(PcieLanes));

   PCIEParams params = defaultValue;

   ////////////////////////////////////////////////////////////////////////////////
   /// Design Elements
   ////////////////////////////////////////////////////////////////////////////////
   B2C1 b2c <- mkB2C1();
   ClockGenerator7AdvParams   clockParams = defaultValue;
   clockParams.bandwidth          = "OPTIMIZED";
   clockParams.compensation       = "INTERNAL";
   clockParams.clkfbout_mult_f    = 10.000;
   clockParams.clkfbout_phase     = 0.0;
   clockParams.clkin1_period      = 10.000;
   clockParams.clkout0_divide_f   = 8.000;
   clockParams.clkout0_duty_cycle = 0.5;
   clockParams.clkout0_phase      = 0.0000;
   clockParams.clkout1_divide     = 4;
   clockParams.clkout1_duty_cycle = 0.5;
   clockParams.clkout1_phase      = 0.0000;
   clockParams.clkout2_divide     = 4;
   clockParams.clkout2_duty_cycle = 0.5;
   clockParams.clkout2_phase      = 0.0000;
   clockParams.divclk_divide      = 1;
   clockParams.ref_jitter1        = 0.010;
   clockParams.clkin_buffer = False;
   XClockGenerator7   clockGen <- mkClockGenerator7Adv(clockParams, clocked_by b2c.c);
   C2B c2b_fb <- mkC2B(clockGen.clkfbout, clocked_by clockGen.clkfbout);
   rule txoutrule5;
      clockGen.clkfbin(c2b_fb.o());
   endrule

   Reset defaultReset <- exposeCurrentReset();
   Bufgctrl bbufc <- mkBufgctrl(clockGen.clkout0, defaultReset, clockGen.clkout1, defaultReset);
   Reset rsto <- mkAsyncReset(2, defaultReset, bbufc.o);
   Reg#(Bit#(1)) pclk_sel <- mkReg(0, clocked_by bbufc.o, reset_by rsto);
   Reg#(Bit#(PcieLanes)) pclk_sel_reg1 <- mkReg(0, clocked_by bbufc.o, reset_by rsto);
   Reg#(Bit#(PcieLanes)) pclk_sel_reg2 <- mkReg(0, clocked_by bbufc.o, reset_by rsto);

   rule bufcruleinit;
      bbufc.ce0(1);
      bbufc.ce1(1);
      bbufc.ignore0(0);
      bbufc.ignore1(0);
   endrule
   rule bufcrule;
      bbufc.s0(~pclk_sel);
      bbufc.s1(pclk_sel);
   endrule

   PCIE_X7#(PcieLanes) pcie_ep <- vMkXilinx7PCIExpress(params, clockGen.clkout0, clockGen.clkout2, bbufc.o);
   //new PcieWrap#(PcieLanes)  pciew <- mkPcieWrap();

   FIFOF#(AxiTx)             fAxiTx              <- mkBypassFIFOF(clocked_by pcie_ep.user.clk_out, reset_by noReset);
   FIFOF#(AxiRx)             fAxiRx              <- mkBypassFIFOF(clocked_by pcie_ep.user.clk_out, reset_by noReset);

   (* fire_when_enabled, no_implicit_conditions *)
   rule every1;
      pcie_ep.fc.sel(0 /*RECEIVE_BUFFER_AVAILABLE_SPACE*/);
      pcie_ep.cfg_dsn({ 32'h0000_0001, {{ 8'h1 } , 24'h000A35 }});
      pcie_ep.rx.np_ok(1);
      pcie_ep.rx.np_req(1);
      pcie_ep.tx.cfg_gnt(1);
      pcie_ep.s_axis_tx.tuser(4'b0);
      pcie_ep.m_axis_rx.tready(pack(fAxiRx.notFull));
   endrule
   rule every2;
      pcie_ep.pipe_mmcm_lock_in(pack(clockGen.locked));
   endrule
   rule every3;
      pclk_sel_reg1 <= pcie_ep.pipe_pclk_sel_out();
   endrule

   Clock txoutclk_buf <- mkClockBUFG(clocked_by pcie_ep.pipe_txoutclk_out);

   C2B c2b <- mkC2B(txoutclk_buf);
   rule txoutrule;
      b2c.inputclock(c2b.o());
   endrule

   rule update_psel;
       let ps = pclk_sel;
       pclk_sel_reg2 <= pclk_sel_reg1;
       if ((~pclk_sel_reg2) == 0)
           ps = 1;
       else if (pclk_sel_reg2 == 0)
           ps = 0;
       pclk_sel <= ps;
   endrule

   let txready = (pcie_ep.s_axis_tx.tready != 0 && fAxiTx.notEmpty);

   //(* fire_when_enabled, no_implicit_conditions *)
   rule drive_axi_tx if (txready);
      let info = fAxiTx.first; fAxiTx.deq;
      pcie_ep.s_axis_tx.tvalid(1);
      pcie_ep.s_axis_tx.tlast(info.last);
      pcie_ep.s_axis_tx.tdata(info.data);
      pcie_ep.s_axis_tx.tkeep(info.keep);
   endrule

   (* fire_when_enabled, no_implicit_conditions *)
   rule drive_axi_tx2 if (!txready);
      pcie_ep.s_axis_tx.tvalid(0);
      pcie_ep.s_axis_tx.tlast(0);
      pcie_ep.s_axis_tx.tdata(0);
      pcie_ep.s_axis_tx.tkeep(0);
   endrule

   (* fire_when_enabled *)
   rule sink_axi_rx if (pcie_ep.m_axis_rx.tvalid != 0);
      fAxiRx.enq(AxiRx {user: pcie_ep.m_axis_rx.tuser,
                        last: pcie_ep.m_axis_rx.tlast,
                        keep: pcie_ep.m_axis_rx.tkeep,
                        data: pcie_ep.m_axis_rx.tdata });
   endrule

   // The PCIe endpoint exports full (250MHz) and half-speed (125MHz) clocks
   Clock clock250 = pcie_ep.user.clk_out;
   Reset user_reset_n <- mkResetInverter(pcie_ep.user.reset_out, clocked_by clock250);
   Reset reset250 <- mkAsyncReset(4, user_reset_n, clock250);

   ClockGenerator7Params     clkgenParams = defaultValue;
   clkgenParams.clkin1_period    = 4.000;
   clkgenParams.clkin_buffer     = False;
   clkgenParams.clkfbout_mult_f  = 4.000;
   clkgenParams.clkout0_divide_f = 8.000;
   ClockGenerator7           clkgen <- mkClockGenerator7(clkgenParams, clocked_by clock250, reset_by user_reset_n);
   Clock clock125 = clkgen.clkout0; /* half speed user_clk */
   Reset reset125 <- mkAsyncReset(4, user_reset_n, clock125);

   Server#(TLPData#(8), TLPData#(8)) tlp8 = (interface Server;
						interface Put request;
						   method Action put(TLPData#(8) data);
						      fAxiTx.enq(AxiTx {last: pack(data.eof),
									keep: dwordSwap64BE(data.be), data: dwordSwap64(data.data) });
						   endmethod
						endinterface
						interface Get response;
						   method ActionValue#(TLPData#(8)) get();
						      let info <- toGet(fAxiRx).get;
						      TLPData#(8) retval = defaultValue;
						      retval.sof  = (info.user[14] == 1);
						      retval.eof  = info.last != 0;
						      retval.hit  = info.user[8:2];
						      retval.be= dwordSwap64BE(info.keep);
						      retval.data = dwordSwap64(info.data);
						      return retval;
						   endmethod
						endinterface
					     endinterface);

   // The PCIE endpoint is processing TLPData#(8)s at 250MHz.  The
   // AXI bridge is accepting TLPData#(16)s at 125 MHz. The
   // connection between the endpoint and the AXI contains GearBox
   // instances for the TLPData#(8)@250 <--> TLPData#(16)@125
   // conversion.
   PcieGearbox gb <- mkPcieGearbox(clock250, reset250, clock125, reset125);
   mkConnection(tlp8, gb.tlp, clocked_by clock250, reset_by reset250);

   interface tlp = gb.pci;
   interface pcie    = pcie_ep.pcie;
   interface PciewrapUser user = pcie_ep.user;
   interface PciewrapCfg cfg = pcie_ep.cfg;
   interface Clock epClock125 = clock125;
   interface Reset epReset125 = reset125;
   interface Clock epClock250 = clock250;
   interface Reset epReset250 = reset250;
endmodule: mkPcieEndpointX7

endpackage: PcieEndpointX7

////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2012  Bluespec, Inc.  ALL RIGHTS RESERVED.
////////////////////////////////////////////////////////////////////////////////
//  Filename      : XbsvXilinx7PCIE.bsv
//  Description   :
////////////////////////////////////////////////////////////////////////////////
package PcieEndpointX7;

import Clocks            ::*;
import Vector            ::*;
import Connectable       ::*;
import GetPut            ::*;
import Reserved          ::*;
import TieOff            ::*;
import DefaultValue      ::*;
import DReg              ::*;
import Gearbox           ::*;
import FIFO              ::*;
import FIFOF             ::*;
import SpecialFIFOs      ::*;
import ClientServer      ::*;

import XbsvXilinxCells   ::*;
import XilinxCells       ::*;
import PCIE              ::*;
import PCIEWRAPPER       ::*;
import Bufgctrl           ::*;
import PcieGearbox       :: *;

(* always_ready, always_enabled *)
interface PCIE_X7#(numeric type lanes);
   interface PciewrapPci_exp#(lanes)   pcie;
   interface PciewrapUser#(lanes)      user;
   interface PciewrapFc#(lanes)        fc;
   interface PciewrapTx#(lanes)        tx;
   interface PciewrapS_axis_tx#(lanes) s_axis_tx;
   interface PciewrapM_axis_rx#(lanes) m_axis_rx;
   interface PciewrapRx#(lanes)        rx;
   interface PciewrapCfg#(lanes)       cfg;
   method    Action                    cfg_dsn(Bit#(64) i);
   interface Clock                     pipe_txoutclk_out;
   method    Action                    pipe_mmcm_lock_in(Bit#(1) v);
   method    Bit#(lanes)               pipe_pclk_sel_out();
endinterface

import "BVI" pcie_7x_0 =
module vMkXilinx7PCIExpress#(PCIEParams params, Clock clk_125mhz, Clock pipe_userclk1_in, Clock pclk_in)(PCIE_X7#(lanes))
   provisos( Add#(1, z, lanes));
   let sys_rst_n <- exposeCurrentReset;

   default_clock clk(sys_clk); // 100 MHz refclk
   default_reset rstn(sys_rst_n) = sys_rst_n;
   input_clock clk_125mhz(pipe_dclk_in) = clk_125mhz;
   input_clock clk_oobclk_in(pipe_oobclk_in) = clk_125mhz;
   input_clock pipe_userclk1_in(pipe_userclk1_in) = pipe_userclk1_in;
   input_clock pipe_userclk2_in(pipe_userclk2_in) = pipe_userclk1_in;
   input_clock pclk_in(pipe_pclk_in) = pclk_in;
   input_clock pclk_usrin(pipe_rxusrclk_in) = pclk_in;
   method pipe_mmcm_lock_in(pipe_mmcm_lock_in) enable((*inhigh*)en_pipe_mmcm_lock_in);
   method pipe_pclk_sel_out pipe_pclk_sel_out   clocked_by(pclk_in);

   interface PciewrapPci_exp pcie;
      method                  rxp(pci_exp_rxp) enable((*inhigh*)en0)    reset_by(no_reset);
      method                  rxn(pci_exp_rxn) enable((*inhigh*)en1)    reset_by(no_reset);
      method pci_exp_txp      txp    reset_by(no_reset);
      method pci_exp_txn      txn    reset_by(no_reset);
   endinterface

   interface PciewrapUser     user;
      output_clock            clk_out(user_clk_out);
      output_reset    reset_out(user_reset_out);
      method user_lnk_up      lnk_up   clocked_by(no_clock) reset_by(no_reset); /* semi-static */
      method user_app_rdy     app_rdy   clocked_by(no_clock) reset_by(no_reset);
   endinterface
    interface PciewrapFc     fc;
      method fc_ph            ph   clocked_by(user_clk_out)    reset_by(no_reset);
      method fc_pd            pd   clocked_by(user_clk_out)    reset_by(no_reset);
      method fc_nph           nph   clocked_by(user_clk_out)    reset_by(no_reset);
      method fc_npd           npd   clocked_by(user_clk_out)    reset_by(no_reset);
      method fc_cplh          cplh   clocked_by(user_clk_out)    reset_by(no_reset);
      method fc_cpld          cpld   clocked_by(user_clk_out)    reset_by(no_reset);
      method                  sel(fc_sel)    enable((*inhigh*)en01)   clocked_by(user_clk_out)    reset_by(no_reset);
   endinterface

   interface PciewrapTx     tx;
      method tx_buf_av        buf_av   clocked_by(user_clk_out)    reset_by(no_reset);
      method tx_err_drop      err_drop   clocked_by(user_clk_out)    reset_by(no_reset);
      method tx_cfg_req       cfg_req   clocked_by(user_clk_out)    reset_by(no_reset);
      method                  cfg_gnt(tx_cfg_gnt)    enable((*inhigh*)en07)   clocked_by(user_clk_out)    reset_by(no_reset);
   endinterface

    interface PciewrapS_axis_tx     s_axis_tx;
      method                  tlast(s_axis_tx_tlast)    enable((*inhigh*)en02)   clocked_by(user_clk_out)    reset_by(no_reset);
      method                  tdata(s_axis_tx_tdata)    enable((*inhigh*)en03)   clocked_by(user_clk_out)    reset_by(no_reset);
      method                  tkeep(s_axis_tx_tkeep)    enable((*inhigh*)en04)   clocked_by(user_clk_out)    reset_by(no_reset);
      method                  tvalid(s_axis_tx_tvalid)    enable((*inhigh*)en05)   clocked_by(user_clk_out)    reset_by(no_reset);
      method                  tuser(s_axis_tx_tuser)    enable((*inhigh*)en06)   clocked_by(user_clk_out)    reset_by(no_reset);
      method s_axis_tx_tready tready   clocked_by(user_clk_out)    reset_by(no_reset);
   endinterface

    interface PciewrapM_axis_rx     m_axis_rx;
      method m_axis_rx_tlast  tlast   clocked_by(user_clk_out)    reset_by(no_reset);
      method m_axis_rx_tdata  tdata   clocked_by(user_clk_out)    reset_by(no_reset);
      method m_axis_rx_tkeep  tkeep   clocked_by(user_clk_out)    reset_by(no_reset);
      method m_axis_rx_tuser  tuser   clocked_by(user_clk_out)    reset_by(no_reset);
      method m_axis_rx_tvalid tvalid   clocked_by(user_clk_out)    reset_by(no_reset);
      method                  tready(m_axis_rx_tready)    enable((*inhigh*)en08)   clocked_by(user_clk_out)    reset_by(no_reset);
   endinterface
   interface PciewrapRx     rx;
      method                  np_ok(rx_np_ok)    enable((*inhigh*)en09)   clocked_by(user_clk_out)    reset_by(no_reset);
      method                  np_req(rx_np_req)    enable((*inhigh*)en10)   clocked_by(user_clk_out)    reset_by(no_reset);
   endinterface

   method                    cfg_dsn(cfg_dsn)    enable((*inhigh*)en25)   clocked_by(user_clk_out);

   interface PciewrapCfg     cfg;
      method cfg_bus_number      bus_number   clocked_by(no_clock) reset_by(no_reset);
      method cfg_device_number   device_number   clocked_by(no_clock) reset_by(no_reset);
      method cfg_function_number function_number   clocked_by(no_clock) reset_by(no_reset);
      method cfg_lcommand        lcommand   clocked_by(user_clk_out) reset_by(no_reset);
      method                     interrupt(cfg_interrupt)    enable((*inhigh*)en32)   clocked_by(user_clk_out) reset_by(no_reset);

      method cfg_bridge_serr_en bridge_serr_en();
      method cfg_command command();
      method cfg_dcommand dcommand();
      method cfg_dcommand2 dcommand2();
      method cfg_lstatus lstatus();
      method cfg_pcie_link_state pcie_link_state();
      method pciecap_interrupt_msgnum(cfg_pciecap_interrupt_msgnum) enable((*inhigh*) EN_cfg_pciecap_interrupt_msgnum);
      method cfg_received_func_lvl_rst received_func_lvl_rst();
      method cfg_slot_control_electromech_il_ctl_pulse slot_control_electromech_il_ctl_pulse();
      method cfg_status status();
      method cfg_to_turnoff to_turnoff();
      method trn_pending(cfg_trn_pending) enable((*inhigh*) EN_cfg_trn_pending);
      method turnoff_ok(cfg_turnoff_ok) enable((*inhigh*) EN_cfg_turnoff_ok);
      method cfg_vc_tcvc_map vc_tcvc_map();
   endinterface

   output_clock pipe_txoutclk_out(pipe_txoutclk_out);

   schedule (user_lnk_up, user_app_rdy, fc_ph, fc_pd, fc_nph, fc_npd, fc_cplh, fc_cpld, fc_sel, s_axis_tx_tlast,
	     s_axis_tx_tdata, s_axis_tx_tkeep, s_axis_tx_tvalid, s_axis_tx_tready, s_axis_tx_tuser, tx_buf_av, tx_err_drop,
	     tx_cfg_req, tx_cfg_gnt, m_axis_rx_tlast, m_axis_rx_tdata, m_axis_rx_tkeep, m_axis_rx_tuser, m_axis_rx_tvalid,
	     m_axis_rx_tready, rx_np_ok, rx_np_req,
	     cfg_bus_number, cfg_device_number, cfg_function_number, cfg_lcommand,
cfg_command, cfg_dcommand, cfg_dcommand2, cfg_lstatus, cfg_pcie_link_state, cfg_received_func_lvl_rst, cfg_status, cfg_to_turnoff, cfg_vc_tcvc_map,
cfg_bridge_serr_en, cfg_slot_control_electromech_il_ctl_pulse,
cfg_pciecap_interrupt_msgnum, cfg_trn_pending, cfg_turnoff_ok,
cfg_interrupt, cfg_dsn,
	     pcie_txp, pcie_txn, pcie_rxp, pcie_rxn, pipe_mmcm_lock_in, pipe_pclk_sel_out
	     ) CF
            (user_lnk_up, user_app_rdy, fc_ph, fc_pd, fc_nph, fc_npd, fc_cplh, fc_cpld, fc_sel, s_axis_tx_tlast,
	     s_axis_tx_tdata, s_axis_tx_tkeep, s_axis_tx_tvalid, s_axis_tx_tready, s_axis_tx_tuser, tx_buf_av, tx_err_drop,
	     tx_cfg_req, tx_cfg_gnt, m_axis_rx_tlast, m_axis_rx_tdata, m_axis_rx_tkeep, m_axis_rx_tuser, m_axis_rx_tvalid,
	     m_axis_rx_tready, rx_np_ok, rx_np_req,
	     cfg_bus_number, cfg_device_number, cfg_function_number, cfg_lcommand,
cfg_command, cfg_dcommand, cfg_dcommand2, cfg_lstatus, cfg_pcie_link_state, cfg_received_func_lvl_rst, cfg_status, cfg_to_turnoff, cfg_vc_tcvc_map,
cfg_bridge_serr_en, cfg_slot_control_electromech_il_ctl_pulse,
cfg_pciecap_interrupt_msgnum, cfg_trn_pending, cfg_turnoff_ok,
cfg_interrupt, cfg_dsn,
	     pcie_txp, pcie_txn, pcie_rxp, pcie_rxn, pipe_mmcm_lock_in, pipe_pclk_sel_out
             );

endmodule: vMkXilinx7PCIExpress

////////////////////////////////////////////////////////////////////////////////
/// Interfaces
////////////////////////////////////////////////////////////////////////////////

interface PcieEndpointX7#(numeric type lanes);
   interface PciewrapPci_exp#(lanes)   pcie;
   interface PciewrapUser#(lanes)      user;
   interface PciewrapCfg#(lanes)       cfg;
   interface Server#(TLPData#(16), TLPData#(16)) tlp;
   interface Clock epClock125;
   interface Reset epReset125;
endinterface

typedef struct {
   Bit#(22)      user;
   Bit#(1)       last;
   Bit#(8)       keep;
   Bit#(64)      data;
} AxiRx deriving (Bits, Eq);

typedef struct {
   Bit#(1)       last;
   Bit#(8)       keep;
   Bit#(64)      data;
} AxiTx deriving (Bits, Eq);

`ifdef Artix7
typedef 4 PcieLanes;
typedef 4 NumLeds;
`else
typedef 8 PcieLanes;
typedef 8 NumLeds;
`endif

(* synthesize *)
module mkPcieEndpointX7(PcieEndpointX7#(PcieLanes));

   PCIEParams params = defaultValue;

   ////////////////////////////////////////////////////////////////////////////////
   /// Design Elements
   ////////////////////////////////////////////////////////////////////////////////
   B2C1 b2c <- mkB2C1();
   ClockGenerator7AdvParams   clockParams = defaultValue;
   clockParams.bandwidth          = "OPTIMIZED";
   clockParams.compensation       = "INTERNAL";
   clockParams.clkfbout_mult_f    = 10.000;
   clockParams.clkfbout_phase     = 0.0;
   clockParams.clkin1_period      = 10.000;
   clockParams.clkout0_divide_f   = 8.000;
   clockParams.clkout0_duty_cycle = 0.5;
   clockParams.clkout0_phase      = 0.0000;
   clockParams.clkout1_divide     = 4;
   clockParams.clkout1_duty_cycle = 0.5;
   clockParams.clkout1_phase      = 0.0000;
   clockParams.clkout2_divide     = 4;
   clockParams.clkout2_duty_cycle = 0.5;
   clockParams.clkout2_phase      = 0.0000;
   clockParams.divclk_divide      = 1;
   clockParams.ref_jitter1        = 0.010;
   clockParams.clkin_buffer = False;
   XClockGenerator7   clockGen <- mkClockGenerator7Adv(clockParams, clocked_by b2c.c);
   C2B c2b_fb <- mkC2B(clockGen.clkfbout, clocked_by clockGen.clkfbout);
   rule txoutrule5;
      clockGen.clkfbin(c2b_fb.o());
   endrule

   Reset defaultReset <- exposeCurrentReset();
   Bufgctrl bbufc <- mkBufgctrl(clockGen.clkout0, defaultReset, clockGen.clkout1, defaultReset);
   Reset rsto <- mkAsyncReset(2, defaultReset, bbufc.o);
   Reg#(Bit#(1)) pclk_sel <- mkReg(0, clocked_by bbufc.o, reset_by rsto);
   Reg#(Bit#(PcieLanes)) pclk_sel_reg1 <- mkReg(0, clocked_by bbufc.o, reset_by rsto);
   Reg#(Bit#(PcieLanes)) pclk_sel_reg2 <- mkReg(0, clocked_by bbufc.o, reset_by rsto);

   rule bufcruleinit;
      bbufc.ce0(1);
      bbufc.ce1(1);
      bbufc.ignore0(0);
      bbufc.ignore1(0);
   endrule
   rule bufcrule;
      bbufc.s0(~pclk_sel);
      bbufc.s1(pclk_sel);
   endrule

   PCIE_X7#(PcieLanes) pcie_ep <- vMkXilinx7PCIExpress(params, clockGen.clkout0, clockGen.clkout2, bbufc.o);
   //new PcieWrap#(PcieLanes)  pciew <- mkPcieWrap();

   FIFOF#(AxiTx)             fAxiTx              <- mkBypassFIFOF(clocked_by pcie_ep.user.clk_out, reset_by noReset);
   FIFOF#(AxiRx)             fAxiRx              <- mkBypassFIFOF(clocked_by pcie_ep.user.clk_out, reset_by noReset);

   (* fire_when_enabled, no_implicit_conditions *)
   rule every1;
      pcie_ep.fc.sel(0 /*RECEIVE_BUFFER_AVAILABLE_SPACE*/);
      pcie_ep.cfg_dsn({ 32'h0000_0001, {{ 8'h1 } , 24'h000A35 }});
      pcie_ep.rx.np_ok(1);
      pcie_ep.rx.np_req(1);
      pcie_ep.tx.cfg_gnt(1);
      pcie_ep.s_axis_tx.tuser(4'b0);
      pcie_ep.m_axis_rx.tready(pack(fAxiRx.notFull));
   endrule
   rule every2;
      pcie_ep.pipe_mmcm_lock_in(pack(clockGen.locked));
   endrule
   rule every3;
      pclk_sel_reg1 <= pcie_ep.pipe_pclk_sel_out();
   endrule

   Clock txoutclk_buf <- mkClockBUFG(clocked_by pcie_ep.pipe_txoutclk_out);

   C2B c2b <- mkC2B(txoutclk_buf);
   rule txoutrule;
      b2c.inputclock(c2b.o());
   endrule

   rule update_psel;
       let ps = pclk_sel;
       pclk_sel_reg2 <= pclk_sel_reg1;
       if ((~pclk_sel_reg2) == 0)
           ps = 1;
       else if (pclk_sel_reg2 == 0)
           ps = 0;
       pclk_sel <= ps;
   endrule

   let txready = (pcie_ep.s_axis_tx.tready != 0 && fAxiTx.notEmpty);

   //(* fire_when_enabled, no_implicit_conditions *)
   rule drive_axi_tx if (txready);
      let info = fAxiTx.first; fAxiTx.deq;
      pcie_ep.s_axis_tx.tvalid(1);
      pcie_ep.s_axis_tx.tlast(info.last);
      pcie_ep.s_axis_tx.tdata(info.data);
      pcie_ep.s_axis_tx.tkeep(info.keep);
   endrule

   (* fire_when_enabled, no_implicit_conditions *)
   rule drive_axi_tx2 if (!txready);
      pcie_ep.s_axis_tx.tvalid(0);
      pcie_ep.s_axis_tx.tlast(0);
      pcie_ep.s_axis_tx.tdata(0);
      pcie_ep.s_axis_tx.tkeep(0);
   endrule

   (* fire_when_enabled *)
   rule sink_axi_rx if (pcie_ep.m_axis_rx.tvalid != 0);
      fAxiRx.enq(AxiRx {user: pcie_ep.m_axis_rx.tuser,
                        last: pcie_ep.m_axis_rx.tlast,
                        keep: pcie_ep.m_axis_rx.tkeep,
                        data: pcie_ep.m_axis_rx.tdata });
   endrule

   // The PCIe endpoint exports full (250MHz) and half-speed (125MHz) clocks
   Clock clock250 = pcie_ep.user.clk_out;
   Reset user_reset_n <- mkResetInverter(pcie_ep.user.reset_out, clocked_by clock250);
   Reset reset250 <- mkAsyncReset(4, user_reset_n, clock250);

   ClockGenerator7Params     clkgenParams = defaultValue;
   clkgenParams.clkin1_period    = 4.000;
   clkgenParams.clkin_buffer     = False;
   clkgenParams.clkfbout_mult_f  = 4.000;
   clkgenParams.clkout0_divide_f = 8.000;
   ClockGenerator7           clkgen <- mkClockGenerator7(clkgenParams, clocked_by clock250, reset_by user_reset_n);
   Clock clock125 = clkgen.clkout0; /* half speed user_clk */
   Reset reset125 <- mkAsyncReset(4, user_reset_n, clock125);

   Server#(TLPData#(8), TLPData#(8)) tlp8 = (interface Server;
						interface Put request;
						   method Action put(TLPData#(8) data);
						      fAxiTx.enq(AxiTx {last: pack(data.eof),
									keep: dwordSwap64BE(data.be), data: dwordSwap64(data.data) });
						   endmethod
						endinterface
						interface Get response;
						   method ActionValue#(TLPData#(8)) get();
						      let info <- toGet(fAxiRx).get;
						      TLPData#(8) retval = defaultValue;
						      retval.sof  = (info.user[14] == 1);
						      retval.eof  = info.last != 0;
						      retval.hit  = info.user[8:2];
						      retval.be= dwordSwap64BE(info.keep);
						      retval.data = dwordSwap64(info.data);
						      return retval;
						   endmethod
						endinterface
					     endinterface);

   // The PCIE endpoint is processing TLPData#(8)s at 250MHz.  The
   // AXI bridge is accepting TLPData#(16)s at 125 MHz. The
   // connection between the endpoint and the AXI contains GearBox
   // instances for the TLPData#(8)@250 <--> TLPData#(16)@125
   // conversion.
   PcieGearbox gb <- mkPcieGearbox(clock250, reset250, clock125, reset125);
   mkConnection(tlp8, gb.tlp, clocked_by clock250, reset_by reset250);

   interface tlp = gb.pci;
   interface pcie    = pcie_ep.pcie;
   interface PciewrapUser user = pcie_ep.user;
   interface PciewrapCfg cfg = pcie_ep.cfg;
   interface Clock epClock125 = clock125;
   interface Reset epReset125 = reset125;
endmodule: mkPcieEndpointX7

endpackage: PcieEndpointX7


fix spelling of registers

fix spelling of registers

// 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 StmtFSM::*;
import BRAM::*;
import MCSAlgorithm::*;

module mkHirschB#(BRAMServer#(Bit#(strIndexWidth), Bit#(8)) strA, BRAMServer#(Bit#(strIndexWidth), Bit#(8)) strB, BRAMServer#(Bit#(lIndexWidth), Bit#(16)) matL)(MCSAlgorithm)
         provisos(Add#(0, 7, strIndexWidth),
	       Add#(0, 14, lIndexWidth));

    Reg#(Bit#(7)) aLenReg <- mkReg(0);
  Reg#(Bit#(7)) bLenReg <- mkReg(0);
  Reg#(Bit#(14)) rLenReg <- mkReg(0);
  Reg#(Bit#(7)) ii <- mkReg(0);
  Reg#(Bit#(7)) jj <- mkReg(0);
   Reg#(Bit#(8)) aData <- mkReg(0);
   Reg#(Bit#(8)) bData <- mkReg(0);
   Reg#(Bit#(16)) k1jm1 <- mkReg(0);
  Reg#(Bit#(16)) k0j <- mkReg(0);

  Stmt hirschB =
   seq
      /* initialize two rows of temporary storage */
      for (jj <= 0; jj < aLenReg; jj <= jj + 1)
	 seq
	    matL.request.put(BRAMRequest{write: True, responseOnWrite: False, address: {0,jj}, datain: 0});
	    matL.request.put(BRAMRequest{write: True, responseOnWrite: False, address: {1,jj}, datain: 0});
	 endseq
      /* Loop through string a */
      for (ii <= 1; ii <= aLenReg; ii <= ii + 1)
	 seq
	    /* Copy L[1] to L[0].  could pingpong instead, or unroll loop */
	    for (jj <= 0; jj <= bLenReg; jj <= jj + 1)
	       seq
		  matL.request.put(BRAMRequest{write: False, responseOnWrite: False, address: {0,jj}, datain: 0});
		  action
		     let ta <- matL.response.get();
		     matL.request.put(BRAMRequest{write: True, responseOnWrite: False, address: {1,jj}, datain: ta});
		  endaction
	       endseq
	    /* Loop through string B */
	    for (jj <= 0; jj <= bLenReg; jj <= jj + 1)
	       seq
		  /* Read a[i] and b[j] */
		  strA.request.put(BRAMRequest{write: False, responseOnWrite: False, address: ii-1, datain: 0});
		  strB.request.put(BRAMRequest{write: False, responseOnWrite: False, address: jj-1, datain: 0});
		  action
		     let ta <- strA.response.get();
		     let tb <- strB.response.get();
		     aData <= ta;
		     bData <= tb;
		  endaction
		  if (aData == bData)
		     seq
			matL.request.put(BRAMRequest{write: False, responseOnWrite: False, address: {1,jj-1}, datain: 0});
			action
			   let ta <- matL.response.get();
			   matL.request.put(BRAMRequest{write: True, responseOnWrite: False, address: {0,jj}, datain: ta + 1});
			endaction
		     endseq
		  else
		     seq
			/* read K[0][j] and K[1][j-1] */
			matL.request.put(BRAMRequest{write: False, responseOnWrite: False, address: {1,jj}, datain: 0});
			action
			   let ta <- matL.response.get();
			   k0j <= ta;
			endaction
			matL.request.put(BRAMRequest{write: False, responseOnWrite: False, address: {0,jj-1}, datain: 0});
			action
			   let ta <- matL.response.get();
			   k1jm1 <= ta;
			endaction
			matL.request.put(BRAMRequest{write: True, responseOnWrite: False, address: {0,jj}, datain: max(k0j,k1jm1)});
		     endseq
		  endseq
	 endseq
   endseq;

   FSM hB <- mkFSM(hirschB);

   method Action setupA(Bit#(7) strLen);
      aLenReg <= strLen;
   endmethod

   method Action setupB(Bit#(7) strLen);
      bLenReg <= strLen;
   endmethod

   interface FSM fsm = hB;

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 StmtFSM::*;
import BRAM::*;
import MCSAlgorithm::*;

module mkHirschB#(BRAMServer#(Bit#(strIndexWidth), Bit#(8)) strA, BRAMServer#(Bit#(strIndexWidth), Bit#(8)) strB, BRAMServer#(Bit#(lIndexWidth), Bit#(16)) matL)(MCSAlgorithm)
         provisos(Add#(0, 7, strIndexWidth),
	       Add#(0, 14, lIndexWidth));

    Reg#(Bit#(7)) aLenReg <- mkReg(0);
  Reg#(Bit#(7)) bLenReg <- mkReg(0);
  Reg#(Bit#(14)) rLenReg <- mkReg(0);
  Reg#(Bit#(7)) ii <- mkReg(0);
  Reg#(Bit#(7)) jj <- mkReg(0);
   Reg#(Bit#(8)) aData <- mkReg(0);
   Reg#(Bit#(8)) bData <- mkReg(0);
   Reg#(Bit#(16)) k1jm1 <- mkReg(0);
  Reg#(Bit#(16)) k0j <- mkReg(0);

  Stmt hirschB =
   seq
      /* initialize two rows of temporary storage */
      for (jj <= 0; jj < aLenReg; jj <= jj + 1)
	 seq
	    matL.request.put(BRAMRequest{write: True, responseOnWrite: False, address: {0,jj}, datain: 0});
	    matL.request.put(BRAMRequest{write: True, responseOnWrite: False, address: {1,jj}, datain: 0});
	 endseq
      /* Loop through string a */
      for (ii <= 1; ii <= aLenReg; ii <= ii + 1)
	 seq
	    /* Copy L[1] to L[0].  could pingpong instead, or unroll loop */
	    for (jj <= 0; jj <= bLenReg; jj <= jj + 1)
	       seq
		  matL.request.put(BRAMRequest{write: False, responseOnWrite: False, address: {0,jj}, datain: 0});
		  action
		     let ta <- matL.response.get();
		     matL.request.put(BRAMRequest{write: True, responseOnWrite: False, address: {1,jj}, datain: ta});
		  endaction
	       endseq
	    /* Loop through string B */
	    for (jj <= 0; jj <= bLenReg; jj <= jj + 1)
	       seq
		  /* Read a[i] and b[j] */
		  strA.request.put(BRAMRequest{write: False, responseOnWrite: False, address: ii-1, datain: 0});
		  strB.request.put(BRAMRequest{write: False, responseOnWrite: False, address: jj-1, datain: 0});
		  action
		     let ta <- strA.response.get();
		     let tb <- strB.response.get();
		     aData <= ta;
		     bData <= tb;
		  endaction
		  if (aData == bData)
		     seq
			matL.request.put(BRAMRequest{write: False, responseOnWrite: False, address: {1,jj-1}, datain: 0});
			action
			   let ta <- matL.response.get();
			   matL.request.put(BRAMRequest{write: True, responseOnWrite: False, address: {0,jj}, datain: ta + 1});
			endaction
		     endseq
		  else
		     seq
			/* read K[0][j] and K[1][j-1] */
			matL.request.put(BRAMRequest{write: False, responseOnWrite: False, address: {1,jj}, datain: 0});
			action
			   let ta <- matL.response.get();
			   k0j <= ta;
			endaction
			matL.request.put(BRAMRequest{write: False, responseOnWrite: False, address: {0,jj-1}, datain: 0});
			action
			   let ta <- matL.response.get();
			   k1jm1 <= ta;
			endaction
			matL.request.put(BRAMRequest{write: True, responseOnWrite: False, address: {0,jj}, datain: max(k0j,k1jm1)});
		     endseq
		  endseq
	 endseq
   endseq;

   FSM hB <- mkFSM(hirschB);

   method Action setupA(Bit#(7) strLen);
      strLenA <= strLen;
   endmethod

   method Action setupB(Bit#(7) strLen);
      strLenB <= strLen;
   endmethod

   interface FSM fsm = hB;

endmodule