use gated BRAM server mux to reduce compiler warnings

// 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 Vector            :: *;
import Clocks          :: *;
import GetPut            :: *;
import Connectable    :: *;
import FIFO              :: *;
import FIFOF        :: *;
import PCIE               :: *;
import BRAM         :: *;
import BramMux        :: *;

typedef 11 TlpTraceAddrSize;
typedef TAdd#(TlpTraceAddrSize,1) TlpTraceAddrSize1;

typedef struct {
    Bit#(32) timestamp;
    Bit#(7) source;   // 4==frombus 8=tobus
    TLPData#(16) tlp; // 153 bits
} TimestampedTlpData deriving (Bits);
typedef SizeOf#(TimestampedTlpData) TimestampedTlpDataSize;
typedef SizeOf#(TLPData#(16)) TlpData16Size;
typedef SizeOf#(TLPCompletionHeader) TLPCompletionHeaderSize;
interface TlpTrace;
   interface Get#(TimestampedTlpData) tlp;
endinterface

interface TlpTraceServer;
   interface Reg#(Bool)     tlpTracing;
   interface Reg#(Bit#(TlpTraceAddrSize)) tlpTraceLimit;
   interface Reg#(Bit#(TlpTraceAddrSize)) tlpTraceBramWrAddr;
   interface BRAMServer#(Bit#(TAdd#(TlpTraceAddrSize,1)), TimestampedTlpData) bramServer;
`ifdef PCIE_BSCAN
   interface BRAMServer#(Bit#(TAdd#(TlpTraceAddrSize,1)), TimestampedTlpData) bscanBramServer;
`endif
endinterface
interface TlpTraceClient;
   interface Reg#(Bool)     tlpTracing;
   interface Reg#(Bit#(TlpTraceAddrSize)) tlpTraceLimit;
   interface Reg#(Bit#(TlpTraceAddrSize)) tlpTraceBramWrAddr;
   interface BRAMClient#(Bit#(TAdd#(TlpTraceAddrSize,1)), TimestampedTlpData) bramClient;
endinterface

interface PcieTracer;
   interface Client#(TLPData#(16), TLPData#(16)) pci;
   interface Put#(TimestampedTlpData) trace;
   interface Server#(TLPData#(16), TLPData#(16)) bus;
   interface TlpTraceServer traceServer;
endinterface: PcieTracer

// The PCIe-to-AXI bridge puts all of the elements together
(* synthesize *)
module mkPcieTracer(PcieTracer);
   // Trace Support
   Reg#(Bool) tlpTracingReg        <- mkReg(False);
   Reg#(Bit#(TlpTraceAddrSize)) tlpTraceLimitReg <- mkReg(0);
   FIFOF#(Bit#(TlpTraceAddrSize)) tlpTraceBramWrAddrFifo <- mkFIFOF();
   Reg#(Bit#(TlpTraceAddrSize)) tlpTraceBramWrAddrReg <- mkReg(0);
   Integer memorySize = 2**valueOf(TlpTraceAddrSize);

   BRAM_Configure bramCfg = defaultValue;
   bramCfg.memorySize = memorySize;
   bramCfg.latency = 1;
`ifdef PCIE_BSCAN
   BRAM2Port#(Bit#(TlpTraceAddrSize), TimestampedTlpData) fromPcieTraceBram <- mkBRAM2Server(bramCfg);
   BRAM2Port#(Bit#(TlpTraceAddrSize), TimestampedTlpData) toPcieTraceBram <- mkBRAM2Server(bramCfg);
`else
   BRAM1Port#(Bit#(TlpTraceAddrSize), TimestampedTlpData) fromPcieTraceBram <- mkBRAM1Server(bramCfg);
   BRAM1Port#(Bit#(TlpTraceAddrSize), TimestampedTlpData) toPcieTraceBram <- mkBRAM1Server(bramCfg);
`endif
   Vector#(2, BRAMServer#(Bit#(TlpTraceAddrSize), TimestampedTlpData)) bramServers;
   bramServers[0] = fromPcieTraceBram.portA;
   bramServers[1] =   toPcieTraceBram.portA;
   Reg#(Bool) tlpNotTracingReg = (interface Reg;
      method Bool _read(); return !tlpTracingReg; endmethod
      method Action _write(Bool w); endmethod
      endinterface);
   BramServerMux#(TAdd#(TlpTraceAddrSize,1), TimestampedTlpData) bramMuxReg <- mkGatedBramServerMux(tlpNotTracingReg, bramServers);

`ifdef PCIE_BSCAN
   Vector#(2, BRAMServer#(Bit#(TlpTraceAddrSize), TimestampedTlpData)) bscanBramServers;
   bscanBramServers[0] = fromPcieTraceBram.portB;
   bscanBramServers[1] =   toPcieTraceBram.portB;
   BramServerMux#(TAdd#(TlpTraceAddrSize,1), TimestampedTlpData) bscanBramMux <- mkBramServerMux(bscanBramServers);
`endif

   Reg#(Bit#(32)) timestamp <- mkReg(0);
   rule incTimestamp;
       timestamp <= timestamp + 1;
   endrule
//   rule endTrace if (tlpTracingReg && tlpTraceLimitReg != 0 && tlpTraceBramWrAddr > truncate(tlpTraceLimitReg));
//       tlpTracingReg <= False;
//   endrule

   FIFO#(TLPData#(16)) tlpFromBusFifo <- mkFIFO();
   FIFO#(TLPData#(16)) tlpToBusFifo <- mkFIFO();
   FIFO#(TLPData#(16)) tlpBusResponseFifo <- mkFIFO();

   Reg#(Bool) skippingIncomingTlps <- mkReg(False);
   FIFO#(Bool) isRootBroadcastMessage <- mkFIFO();
   PulseWire fromPcie <- mkPulseWire;
   PulseWire   toPcie <- mkPulseWire;
   Wire#(TLPData#(16)) fromPcieTlp <- mkDWire(unpack(0));
   Wire#(TLPData#(16))   toPcieTlp <- mkDWire(unpack(0));

   rule sniffTlpFromBus;
      let tlp <- toGet(tlpFromBusFifo).get();
      tlpBusResponseFifo.enq(tlp);

      TLPMemoryIO3DWHeader hdr_3dw = unpack(tlp.data);
      // skip root_broadcast_messages sent to tlp.hit 0
      isRootBroadcastMessage.enq(tlp.sof && tlp.hit == 0 && hdr_3dw.pkttype != COMPLETION);

   endrule

   rule doTracing if (tlpTracingReg && (fromPcie || toPcie));
      TimestampedTlpData fromttd = fromPcie ? TimestampedTlpData { timestamp: timestamp, source: 7'h04, tlp: fromPcieTlp } : unpack(0);
      let writeAddr = tlpTraceBramWrAddrReg;
      if (tlpTraceBramWrAddrFifo.notEmpty)
	 writeAddr <- toGet(tlpTraceBramWrAddrFifo).get();

      fromPcieTraceBram.portA.request.put(BRAMRequest{ write: True, responseOnWrite: False, address: writeAddr, datain: fromttd });

      TimestampedTlpData   tottd = toPcie ? TimestampedTlpData { timestamp: timestamp, source: 7'h08, tlp: toPcieTlp } : unpack(0);
      toPcieTraceBram.portA.request.put(BRAMRequest{ write: True, responseOnWrite: False, address: writeAddr, datain: tottd });

      tlpTraceBramWrAddrReg <= writeAddr + 1;
   endrule

   interface Server     bus;
      interface Get response;
           method ActionValue#(TLPData#(16)) get();
	      let tlp <- toGet(tlpBusResponseFifo).get();

	      if (tlpTracingReg) begin
		 if (tlp.sof && isRootBroadcastMessage.first) begin
 		    skippingIncomingTlps <= True;
		 end
		 else if (skippingIncomingTlps && !tlp.sof) begin
		    // do nothing
		 end
		 else begin
		    fromPcie.send();
		    fromPcieTlp <= tlp;
		    skippingIncomingTlps <= False;
		 end
	      end

	      isRootBroadcastMessage.deq();
	      return tlp;
	   endmethod
      endinterface

       interface Put request;
           method Action put(TLPData#(16) tlp);
           tlpToBusFifo.enq(tlp);
           if (tlpTracingReg) begin
	      toPcie.send();
	      toPcieTlp <= tlp;
           end
           endmethod
       endinterface
   endinterface

   interface Client    pci;
      interface request = toGet(tlpToBusFifo);
      interface response = toPut(tlpFromBusFifo);
   endinterface
   interface Put trace;
       method Action put(TimestampedTlpData ttd) if (!fromPcie && !toPcie);
	   if (tlpTracingReg) begin
	       ttd.timestamp = timestamp;
	       toPcieTraceBram.portA.request.put(BRAMRequest{ write: True, responseOnWrite: False, address: truncate(tlpTraceBramWrAddrReg), datain: ttd });
	       tlpTraceBramWrAddrReg <= tlpTraceBramWrAddrReg + 1;
	   end
       endmethod
   endinterface: trace
   interface TlpTraceServer traceServer;
      interface Reg tlpTracing    = tlpTracingReg;
      interface Reg tlpTraceLimit = tlpTraceLimitReg;
      interface Reg tlpTraceBramWrAddr;
	 method Bit#(TlpTraceAddrSize) _read(); return tlpTraceBramWrAddrReg; endmethod
	 method Action _write(Bit#(TlpTraceAddrSize) v); tlpTraceBramWrAddrFifo.enq(v); endmethod
      endinterface
      interface Server bramServer = bramMuxReg.bramServer;
`ifdef PCIE_BSCAN
      interface Server bscanBramServer = bscanBramMux.bramServer;
`endif
   endinterface
endmodule: mkPcieTracer

instance Connectable#(TlpTraceClient,TlpTraceServer);
   module mkConnection#(TlpTraceClient client, TlpTraceServer tracer)(Empty);
      mkConnection(client.bramClient, tracer.bramServer);
      Reg#(Bool)                           tlpTracingReg <- mkReg(False);
      Reg#(Bit#(TlpTraceAddrSize))      tlpTraceLimitReg <- mkReg(0);
      Reg#(Bit#(TlpTraceAddrSize)) tlpTraceBramWrAddrReg <- mkReg(0);
      rule tracingRule if (tlpTracingReg != client.tlpTracing);
	 tracer.tlpTracing <= client.tlpTracing;
	 tlpTracingReg <= client.tlpTracing;
      endrule
      rule traceLimitRule if (tlpTraceLimitReg != client.tlpTraceLimit);
	 tracer.tlpTraceLimit <= client.tlpTraceLimit;
	 tlpTraceLimitReg <= client.tlpTraceLimit;
      endrule
      // both client and server update the tlpBramWrAddr
      rule traceBramWrAddrRule if (tlpTraceBramWrAddrReg != client.tlpTraceBramWrAddr);
	 tracer.tlpTraceBramWrAddr <= client.tlpTraceBramWrAddr;
	 tlpTraceBramWrAddrReg <= client.tlpTraceBramWrAddr;
      endrule
   endmodule
endinstance

// 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 Vector            :: *;
import Clocks          :: *;
import GetPut            :: *;
import Connectable    :: *;
import FIFO              :: *;
import FIFOF        :: *;
import PCIE               :: *;
import BRAM         :: *;
import BramMux        :: *;

typedef 11 TlpTraceAddrSize;
typedef TAdd#(TlpTraceAddrSize,1) TlpTraceAddrSize1;

typedef struct {
    Bit#(32) timestamp;
    Bit#(7) source;   // 4==frombus 8=tobus
    TLPData#(16) tlp; // 153 bits
} TimestampedTlpData deriving (Bits);
typedef SizeOf#(TimestampedTlpData) TimestampedTlpDataSize;
typedef SizeOf#(TLPData#(16)) TlpData16Size;
typedef SizeOf#(TLPCompletionHeader) TLPCompletionHeaderSize;
interface TlpTrace;
   interface Get#(TimestampedTlpData) tlp;
endinterface

interface TlpTraceServer;
   interface Reg#(Bool)     tlpTracing;
   interface Reg#(Bit#(TlpTraceAddrSize)) tlpTraceLimit;
   interface Reg#(Bit#(TlpTraceAddrSize)) tlpTraceBramWrAddr;
   interface BRAMServer#(Bit#(TAdd#(TlpTraceAddrSize,1)), TimestampedTlpData) bramServer;
`ifdef PCIE_BSCAN
   interface BRAMServer#(Bit#(TAdd#(TlpTraceAddrSize,1)), TimestampedTlpData) bscanBramServer;
`endif
endinterface
interface TlpTraceClient;
   interface Reg#(Bool)     tlpTracing;
   interface Reg#(Bit#(TlpTraceAddrSize)) tlpTraceLimit;
   interface Reg#(Bit#(TlpTraceAddrSize)) tlpTraceBramWrAddr;
   interface BRAMClient#(Bit#(TAdd#(TlpTraceAddrSize,1)), TimestampedTlpData) bramClient;
endinterface

interface PcieTracer;
   interface Client#(TLPData#(16), TLPData#(16)) pci;
   interface Put#(TimestampedTlpData) trace;
   interface Server#(TLPData#(16), TLPData#(16)) bus;
   interface TlpTraceServer traceServer;
endinterface: PcieTracer

// The PCIe-to-AXI bridge puts all of the elements together
(* synthesize *)
module mkPcieTracer(PcieTracer);
   // Trace Support
   Reg#(Bool) tlpTracingReg        <- mkReg(False);
   Reg#(Bit#(TlpTraceAddrSize)) tlpTraceLimitReg <- mkReg(0);
   FIFOF#(Bit#(TlpTraceAddrSize)) tlpTraceBramWrAddrFifo <- mkFIFOF();
   Reg#(Bit#(TlpTraceAddrSize)) tlpTraceBramWrAddrReg <- mkReg(0);
   Integer memorySize = 2**valueOf(TlpTraceAddrSize);

   BRAM_Configure bramCfg = defaultValue;
   bramCfg.memorySize = memorySize;
   bramCfg.latency = 1;
`ifdef PCIE_BSCAN
   BRAM2Port#(Bit#(TlpTraceAddrSize), TimestampedTlpData) fromPcieTraceBram <- mkBRAM2Server(bramCfg);
   BRAM2Port#(Bit#(TlpTraceAddrSize), TimestampedTlpData) toPcieTraceBram <- mkBRAM2Server(bramCfg);
`else
   BRAM1Port#(Bit#(TlpTraceAddrSize), TimestampedTlpData) fromPcieTraceBram <- mkBRAM1Server(bramCfg);
   BRAM1Port#(Bit#(TlpTraceAddrSize), TimestampedTlpData) toPcieTraceBram <- mkBRAM1Server(bramCfg);
`endif
   Vector#(2, BRAMServer#(Bit#(TlpTraceAddrSize), TimestampedTlpData)) bramServers;
   bramServers[0] = fromPcieTraceBram.portA;
   bramServers[1] =   toPcieTraceBram.portA;
   BramServerMux#(TAdd#(TlpTraceAddrSize,1), TimestampedTlpData) bramMuxReg <- mkBramServerMux(bramServers);

`ifdef PCIE_BSCAN
   Vector#(2, BRAMServer#(Bit#(TlpTraceAddrSize), TimestampedTlpData)) bscanBramServers;
   bscanBramServers[0] = fromPcieTraceBram.portB;
   bscanBramServers[1] =   toPcieTraceBram.portB;
   BramServerMux#(TAdd#(TlpTraceAddrSize,1), TimestampedTlpData) bscanBramMux <- mkBramServerMux(bscanBramServers);
`endif

   Reg#(Bit#(32)) timestamp <- mkReg(0);
   rule incTimestamp;
       timestamp <= timestamp + 1;
   endrule
//   rule endTrace if (tlpTracingReg && tlpTraceLimitReg != 0 && tlpTraceBramWrAddr > truncate(tlpTraceLimitReg));
//       tlpTracingReg <= False;
//   endrule

   FIFO#(TLPData#(16)) tlpFromBusFifo <- mkFIFO();
   FIFO#(TLPData#(16)) tlpToBusFifo <- mkFIFO();
   FIFO#(TLPData#(16)) tlpBusResponseFifo <- mkFIFO();

   Reg#(Bool) skippingIncomingTlps <- mkReg(False);
   FIFO#(Bool) isRootBroadcastMessage <- mkFIFO();
   PulseWire fromPcie <- mkPulseWire;
   PulseWire   toPcie <- mkPulseWire;
   Wire#(TLPData#(16)) fromPcieTlp <- mkDWire(unpack(0));
   Wire#(TLPData#(16))   toPcieTlp <- mkDWire(unpack(0));

   rule sniffTlpFromBus;
      let tlp <- toGet(tlpFromBusFifo).get();
      tlpBusResponseFifo.enq(tlp);

      TLPMemoryIO3DWHeader hdr_3dw = unpack(tlp.data);
      // skip root_broadcast_messages sent to tlp.hit 0
      isRootBroadcastMessage.enq(tlp.sof && tlp.hit == 0 && hdr_3dw.pkttype != COMPLETION);

   endrule

   rule doTracing if (fromPcie || toPcie);
      TimestampedTlpData fromttd = fromPcie ? TimestampedTlpData { timestamp: timestamp, source: 7'h04, tlp: fromPcieTlp } : unpack(0);
      let writeAddr = tlpTraceBramWrAddrReg;
      if (tlpTraceBramWrAddrFifo.notEmpty)
	 writeAddr <- toGet(tlpTraceBramWrAddrFifo).get();

      fromPcieTraceBram.portA.request.put(BRAMRequest{ write: True, responseOnWrite: False, address: writeAddr, datain: fromttd });

      TimestampedTlpData   tottd = toPcie ? TimestampedTlpData { timestamp: timestamp, source: 7'h08, tlp: toPcieTlp } : unpack(0);
      toPcieTraceBram.portA.request.put(BRAMRequest{ write: True, responseOnWrite: False, address: writeAddr, datain: tottd });

      tlpTraceBramWrAddrReg <= writeAddr + 1;
   endrule

   interface Server     bus;
      interface Get response;
           method ActionValue#(TLPData#(16)) get();
	      let tlp <- toGet(tlpBusResponseFifo).get();

	      if (tlpTracingReg) begin
		 if (tlp.sof && isRootBroadcastMessage.first) begin
 		    skippingIncomingTlps <= True;
		 end
		 else if (skippingIncomingTlps && !tlp.sof) begin
		    // do nothing
		 end
		 else begin
		    fromPcie.send();
		    fromPcieTlp <= tlp;
		    skippingIncomingTlps <= False;
		 end
	      end

	      isRootBroadcastMessage.deq();
	      return tlp;
	   endmethod
      endinterface

       interface Put request;
           method Action put(TLPData#(16) tlp);
           tlpToBusFifo.enq(tlp);
           if (tlpTracingReg) begin
	      toPcie.send();
	      toPcieTlp <= tlp;
           end
           endmethod
       endinterface
   endinterface

   interface Client    pci;
      interface request = toGet(tlpToBusFifo);
      interface response = toPut(tlpFromBusFifo);
   endinterface
   interface Put trace;
       method Action put(TimestampedTlpData ttd) if (!fromPcie && !toPcie);
	   if (tlpTracingReg) begin
	       ttd.timestamp = timestamp;
	       toPcieTraceBram.portA.request.put(BRAMRequest{ write: True, responseOnWrite: False, address: truncate(tlpTraceBramWrAddrReg), datain: ttd });
	       tlpTraceBramWrAddrReg <= tlpTraceBramWrAddrReg + 1;
	   end
       endmethod
   endinterface: trace
   interface TlpTraceServer traceServer;
      interface Reg tlpTracing    = tlpTracingReg;
      interface Reg tlpTraceLimit = tlpTraceLimitReg;
      interface Reg tlpTraceBramWrAddr;
	 method Bit#(TlpTraceAddrSize) _read(); return tlpTraceBramWrAddrReg; endmethod
	 method Action _write(Bit#(TlpTraceAddrSize) v); tlpTraceBramWrAddrFifo.enq(v); endmethod
      endinterface
      interface Server bramServer = bramMuxReg.bramServer;
`ifdef PCIE_BSCAN
      interface Server bscanBramServer = bscanBramMux.bramServer;
`endif
   endinterface
endmodule: mkPcieTracer

instance Connectable#(TlpTraceClient,TlpTraceServer);
   module mkConnection#(TlpTraceClient client, TlpTraceServer tracer)(Empty);
      mkConnection(client.bramClient, tracer.bramServer);
      Reg#(Bool)                           tlpTracingReg <- mkReg(False);
      Reg#(Bit#(TlpTraceAddrSize))      tlpTraceLimitReg <- mkReg(0);
      Reg#(Bit#(TlpTraceAddrSize)) tlpTraceBramWrAddrReg <- mkReg(0);
      rule tracingRule if (tlpTracingReg != client.tlpTracing);
	 tracer.tlpTracing <= client.tlpTracing;
	 tlpTracingReg <= client.tlpTracing;
      endrule
      rule traceLimitRule if (tlpTraceLimitReg != client.tlpTraceLimit);
	 tracer.tlpTraceLimit <= client.tlpTraceLimit;
	 tlpTraceLimitReg <= client.tlpTraceLimit;
      endrule
      // both client and server update the tlpBramWrAddr
      rule traceBramWrAddrRule if (tlpTraceBramWrAddrReg != client.tlpTraceBramWrAddr);
	 tracer.tlpTraceBramWrAddr <= client.tlpTraceBramWrAddr;
	 tlpTraceBramWrAddrReg <= client.tlpTraceBramWrAddr;
      endrule
   endmodule
endinstance


updated copyright

updated copyright

// Copyright (c) 2015 Cornell University.

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

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

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

import FIFO::*;
import FIFOF::*;
import Vector::*;
import Pipe::*;
import GetPut::*;

typedef struct {
   Bit#(8) port_no;
   Bit#(64) data;
} BufData deriving (Bits, Eq);

interface DtpIfc;
   interface PipeIn#(Bit#(128)) timestamp; // streaming time counter from NetTop.
   interface Vector#(4, PipeOut#(Bit#(53))) fromHost;
   interface Vector#(4, PipeIn#(Bit#(53)))  toHost;
endinterface

interface SonicUserRequest;
   method Action read_timestamp_req(Bit#(8) cmd);
   method Action write_delay(Bit#(64) host_cnt);
   method Action log_write(Bit#(8) port_no, Bit#(64) local_cnt);
   method Action log_read_req(Bit#(8) port_no);
endinterface

interface SonicUserIndication;
   method Action read_timestamp_resp(Bit#(64) val);
   method Action log_read_resp(Bit#(8) port_no, Bit#(64) local_cnt, Bit#(64) global_cnt);
endinterface

interface SonicUser;
   interface SonicUserRequest request;
   interface DtpIfc           dtp;
endinterface

module mkSonicUser#(SonicUserIndication indication)(SonicUser);
   let verbose = False;
   Reg#(Bit#(64))  cycle_count <- mkReg(0);
   Reg#(Bit#(64))  last_count  <- mkReg(0);

   FIFOF#(Bit#(128)) rxFifo    <- mkFIFOF();
   Reg#(Bit#(128)) timestamp_reg <- mkReg(0);

   Vector#(4, FIFOF#(Bit#(53))) fromHostFifo <- replicateM(mkSizedFIFOF(4));
   Vector#(4, FIFOF#(Bit#(53))) toHostFifo <- replicateM(mkSizedFIFOF(4));
   FIFOF#(BufData) toHostBuffered <- mkSizedFIFOF(16);

   Reg#(Bit#(8))  lwrite_port <- mkReg(0);
   Reg#(Bit#(53)) lwrite_timestamp <- mkReg(0);
   FIFOF#(void)    lwrite_cf <- mkSizedFIFOF(8);

   Reg#(Bit#(8))  lread_port <- mkReg(0);
   FIFOF#(void)   lread_cf <- mkSizedFIFOF(8);

   rule count;
      cycle_count <= cycle_count + 1;
   endrule

   rule snapshot_dtp_timestamp;
      let v <- toGet(rxFifo).get;
      timestamp_reg <= v;
   endrule

   rule log_from_host (lwrite_cf.notEmpty && fromHostFifo[lwrite_port].notFull);
      fromHostFifo[lwrite_port].enq(lwrite_timestamp);
      lwrite_cf.deq;
   endrule

   Reg#(Bit#(8))  debug_port_no <- mkReg(0);
   Reg#(Bit#(53)) debug_host_timestamp <- mkReg(0);
   rule cannot_log_from_host(!fromHostFifo[lwrite_port].notFull);
      debug_port_no <= lwrite_port;
      debug_host_timestamp <= lwrite_timestamp;
   endrule

   Reg#(Bit#(TLog#(4))) arb <- mkReg(0);
   rule arbit;
      arb <= arb + 1;
   endrule
   rule save_port0_to_host_data (arb == 0 && toHostFifo[0].notEmpty);
      let v = toHostFifo[0].first;
      toHostBuffered.enq(BufData{port_no:0, data:zeroExtend(v)});
      toHostFifo[0].deq;
   endrule

   rule save_port1_to_host_data (arb == 1 && toHostFifo[1].notEmpty);
      let v = toHostFifo[1].first;
      toHostBuffered.enq(BufData{port_no:1, data:zeroExtend(v)});
      toHostFifo[1].deq;
   endrule

   rule save_port2_to_host_data (arb == 2 && toHostFifo[2].notEmpty);
      let v = toHostFifo[2].first;
      toHostBuffered.enq(BufData{port_no:2, data:zeroExtend(v)});
      toHostFifo[2].deq;
   endrule

   rule save_port3_to_host_data (arb == 3 && toHostFifo[3].notEmpty);
      let v = toHostFifo[3].first;
      toHostBuffered.enq(BufData{port_no:3, data:zeroExtend(v)});
      toHostFifo[3].deq;
   endrule

   Reg#(Bit#(64)) debug_host_buffer <-mkReg(0);
   rule log_to_host(toHostBuffered.notEmpty);
      let v = toHostBuffered.first;
      indication.log_read_resp(v.port_no, truncate(timestamp_reg), v.data);
      debug_host_buffer <= 64'hAAAA;
      toHostBuffered.deq;
   endrule

   rule cannot_log_to_host(!toHostBuffered.notEmpty);
      debug_host_buffer <= cycle_count;
   endrule

   interface dtp = (interface DtpIfc;
      interface timestamp = toPipeIn(rxFifo);
      interface toHost = map(toPipeIn, toHostFifo);
      interface fromHost = map(toPipeOut, fromHostFifo);
   endinterface);

   interface SonicUserRequest request;
   method Action read_timestamp_req(Bit#(8) cmd);
      indication.read_timestamp_resp(truncate(timestamp_reg));
   endmethod
   method Action write_delay(Bit#(64) host_cnt);
      Bit#(64) delay = (host_cnt - cycle_count) >> 1;
   endmethod
   method Action log_write(Bit#(8) port_no, Bit#(64) host_timestamp);
      // Check valid port No.
      if (port_no < 4) begin
         lwrite_port <= port_no;
         lwrite_timestamp <= truncate(host_timestamp);
         lwrite_cf.enq(?);
      end
   endmethod
   method Action log_read_req(Bit#(8) port_no);
      if (port_no < 4) begin
         lread_port <= port_no;
      end
   endmethod
   endinterface
endmodule

// Copyright (c) 2013 Nokia, Inc.

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

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

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

import FIFO::*;
import FIFOF::*;
import Vector::*;
import Pipe::*;
import GetPut::*;

typedef struct {
   Bit#(8) port_no;
   Bit#(64) data;
} BufData deriving (Bits, Eq);

interface DtpIfc;
   interface PipeIn#(Bit#(128)) timestamp; // streaming time counter from NetTop.
   interface Vector#(4, PipeOut#(Bit#(53))) fromHost;
   interface Vector#(4, PipeIn#(Bit#(53)))  toHost;
endinterface

interface SonicUserRequest;
   method Action read_timestamp_req(Bit#(8) cmd);
   method Action write_delay(Bit#(64) host_cnt);
   method Action log_write(Bit#(8) port_no, Bit#(64) local_cnt);
   method Action log_read_req(Bit#(8) port_no);
endinterface

interface SonicUserIndication;
   method Action read_timestamp_resp(Bit#(64) val);
   method Action log_read_resp(Bit#(8) port_no, Bit#(64) local_cnt, Bit#(64) global_cnt);
endinterface

interface SonicUser;
   interface SonicUserRequest request;
   interface DtpIfc           dtp;
endinterface

module mkSonicUser#(SonicUserIndication indication)(SonicUser);
   let verbose = False;
   Reg#(Bit#(64))  cycle_count <- mkReg(0);
   Reg#(Bit#(64))  last_count  <- mkReg(0);

   FIFOF#(Bit#(128)) rxFifo    <- mkFIFOF();
   Reg#(Bit#(128)) timestamp_reg <- mkReg(0);

   Vector#(4, FIFOF#(Bit#(53))) fromHostFifo <- replicateM(mkSizedFIFOF(4));
   Vector#(4, FIFOF#(Bit#(53))) toHostFifo <- replicateM(mkSizedFIFOF(4));
   FIFOF#(BufData) toHostBuffered <- mkSizedFIFOF(16);

   Reg#(Bit#(8))  lwrite_port <- mkReg(0);
   Reg#(Bit#(53)) lwrite_timestamp <- mkReg(0);
   FIFOF#(void)    lwrite_cf <- mkSizedFIFOF(8);

   Reg#(Bit#(8))  lread_port <- mkReg(0);
   FIFOF#(void)   lread_cf <- mkSizedFIFOF(8);

   rule count;
      cycle_count <= cycle_count + 1;
   endrule

   rule snapshot_dtp_timestamp;
      let v <- toGet(rxFifo).get;
      timestamp_reg <= v;
   endrule

   rule log_from_host (lwrite_cf.notEmpty && fromHostFifo[lwrite_port].notFull);
      fromHostFifo[lwrite_port].enq(lwrite_timestamp);
      lwrite_cf.deq;
   endrule

   Reg#(Bit#(8))  debug_port_no <- mkReg(0);
   Reg#(Bit#(53)) debug_host_timestamp <- mkReg(0);
   rule cannot_log_from_host(!fromHostFifo[lwrite_port].notFull);
      debug_port_no <= lwrite_port;
      debug_host_timestamp <= lwrite_timestamp;
   endrule

   Reg#(Bit#(TLog#(4))) arb <- mkReg(0);
   rule arbit;
      arb <= arb + 1;
   endrule
   rule save_port0_to_host_data (arb == 0 && toHostFifo[0].notEmpty);
      let v = toHostFifo[0].first;
      toHostBuffered.enq(BufData{port_no:0, data:zeroExtend(v)});
      toHostFifo[0].deq;
   endrule

   rule save_port1_to_host_data (arb == 1 && toHostFifo[1].notEmpty);
      let v = toHostFifo[1].first;
      toHostBuffered.enq(BufData{port_no:1, data:zeroExtend(v)});
      toHostFifo[1].deq;
   endrule

   rule save_port2_to_host_data (arb == 2 && toHostFifo[2].notEmpty);
      let v = toHostFifo[2].first;
      toHostBuffered.enq(BufData{port_no:2, data:zeroExtend(v)});
      toHostFifo[2].deq;
   endrule

   rule save_port3_to_host_data (arb == 3 && toHostFifo[3].notEmpty);
      let v = toHostFifo[3].first;
      toHostBuffered.enq(BufData{port_no:3, data:zeroExtend(v)});
      toHostFifo[3].deq;
   endrule

   Reg#(Bit#(64)) debug_host_buffer <-mkReg(0);
   rule log_to_host(toHostBuffered.notEmpty);
      let v = toHostBuffered.first;
      indication.log_read_resp(v.port_no, truncate(timestamp_reg), v.data);
      debug_host_buffer <= 64'hAAAA;
      toHostBuffered.deq;
   endrule

   rule cannot_log_to_host(!toHostBuffered.notEmpty);
      debug_host_buffer <= cycle_count;
   endrule

   interface dtp = (interface DtpIfc;
      interface timestamp = toPipeIn(rxFifo);
      interface toHost = map(toPipeIn, toHostFifo);
      interface fromHost = map(toPipeOut, fromHostFifo);
   endinterface);

   interface SonicUserRequest request;
   method Action read_timestamp_req(Bit#(8) cmd);
      indication.read_timestamp_resp(truncate(timestamp_reg));
   endmethod
   method Action write_delay(Bit#(64) host_cnt);
      Bit#(64) delay = (host_cnt - cycle_count) >> 1;
   endmethod
   method Action log_write(Bit#(8) port_no, Bit#(64) host_timestamp);
      // Check valid port No.
      if (port_no < 4) begin
         lwrite_port <= port_no;
         lwrite_timestamp <= truncate(host_timestamp);
         lwrite_cf.enq(?);
      end
   endmethod
   method Action log_read_req(Bit#(8) port_no);
      if (port_no < 4) begin
         lread_port <= port_no;
      end
   endmethod
   endinterface
endmodule


add setupL

add setupL

// 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::*;

interface MCSAlgorithm;
   method Action setupA (Bit#(7) start, Bit#(7) length);
   method Action setupB (Bit#(7) start, Bit#(7) length);
   method Action setupL (Bit#(14) start);
   interface FSM fsm;
endinterface

// 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::*;

interface MCSAlgorithm;
   method Action setupA (Bit#(7) start, Bit#(7) length);
   method Action setupB (Bit#(7) start, Bit#(7) length);
   interface FSM fsm;
endinterface


clean up

clean up

// Copyright (c) 2016 Cornell University.

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

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

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

package NullTest;

import FIFO::*;
import FIFOF::*;
import DefaultValue::*;
import Vector::*;
import BuildVector::*;
import GetPut::*;
import ClientServer::*;
import Connectable::*;
import Clocks::*;
import Gearbox::*;
import Pipe::*;

import MemTypes::*;
import Ethernet::*;
import NullAPI::*;
import PacketBuffer::*;
import AlteraMacWrap::*;
import EthMac::*;
import AlteraEthPhy::*;
import DE5Pins::*;

interface NullTest;
   interface NullTestRequest request;
   interface `PinType pins;
endinterface

module mkNullTest#(NullTestIndication indication)(NullTest);
   Clock defaultClock <- exposeCurrentClock();
   Reset defaultReset <- exposeCurrentReset();

   Wire#(Bit#(1)) clk_644_wire <- mkDWire(0);
   Wire#(Bit#(1)) clk_50_wire <- mkDWire(0);
   De5Clocks clocks <- mkDe5Clocks(clk_50_wire, clk_644_wire);

   Clock txClock = clocks.clock_156_25;
   Clock phyClock = clocks.clock_644_53;
   Clock mgmtClock = clocks.clock_50;
   Reset txReset <- mkSyncReset(2, defaultReset, txClock);
   Reset phyReset <- mkSyncReset(2, defaultReset, phyClock);
   Reset mgmtReset <- mkSyncReset(2, defaultReset, mgmtClock);

   // DE5 Pins
   De5Leds leds <- mkDe5Leds(defaultClock, txClock, mgmtClock, phyClock);
   De5SfpCtrl#(4) sfpctrl <- mkDe5SfpCtrl();
   De5Buttons#(4) buttons <- mkDe5Buttons(clocked_by mgmtClock, reset_by mgmtReset);

   // Mac + Phy
   EthPhyIfc phys <- mkAlteraEthPhy(defaultClock, phyClock, txClock, defaultReset);

   Clock rxClock = phys.rx_clkout;
   Reset rxReset <- mkSyncReset(2, defaultReset, rxClock);
   Vector#(4, EthMacIfc) mac <- replicateM(mkEthMac(defaultClock, txClock, rxClock, txReset));

   function Get#(Bit#(72)) getTx(EthMacIfc _mac); return _mac.tx; endfunction
   function Put#(Bit#(72)) getRx(EthMacIfc _mac); return _mac.rx; endfunction
   mapM(uncurry(mkConnection), zip(map(getTx, mac), phys.tx));
   mapM(uncurry(mkConnection), zip(phys.rx, map(getRx, mac)));

   NullAPI api <- mkNullAPI(indication);

   interface request = api.request;
`ifdef SYNTHESIS
   interface `PinType pins;
      method Action osc_50(Bit#(1) b3d, Bit#(1) b4a, Bit#(1) b4d, Bit#(1) b7a, Bit#(1) b7d, Bit#(1) b8a, Bit#(1) b8d);
         clk_50_wire <= b4a;
      endmethod
      method serial_tx_data = phys.serial_tx;
      method serial_rx = phys.serial_rx;
      method Action sfp(Bit#(1) refclk);
         clk_644_wire <= refclk;
      endmethod
      interface i2c = clocks.i2c;
      interface led = leds.led_out;
      interface led_bracket = leds.led_out;
      interface sfpctrl = sfpctrl;
      interface buttons = buttons.pins;
      interface deleteme_unused_clock = defaultClock;
      interface deleteme_unused_clock2 = clocks.clock_50;
      interface deleteme_unused_clock3 = defaultClock;
      interface deleteme_unused_reset = defaultReset;
   endinterface
`endif
endmodule
endpackage

// Copyright (c) 2016 Cornell University.

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

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

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

package NullTest;

import FIFO::*;
import FIFOF::*;
import DefaultValue::*;
import Vector::*;
import BuildVector::*;
import GetPut::*;
import ClientServer::*;
import Connectable::*;
import Clocks::*;
import Gearbox::*;
import Pipe::*;

import MemTypes::*;
import Ethernet::*;
import NullAPI::*;
import PacketBuffer::*;
import AlteraMacWrap::*;
import EthMac::*;
import AlteraEthPhy::*;
import DE5Pins::*;

interface NullTest;
   interface NullTestRequest request;
   interface `PinType pins;
endinterface

module mkNullTest#(NullTestIndication indication)(NullTest);
   Clock defaultClock <- exposeCurrentClock();
   Reset defaultReset <- exposeCurrentReset();

   Wire#(Bit#(1)) clk_644_wire <- mkDWire(0);
   Wire#(Bit#(1)) clk_50_wire <- mkDWire(0);
   De5Clocks clocks <- mkDe5Clocks(clk_50_wire, clk_644_wire);

   Clock txClock = clocks.clock_156_25;
   Clock phyClock = clocks.clock_644_53;
   Clock mgmtClock = clocks.clock_50;
   Reset txReset <- mkSyncReset(2, defaultReset, txClock);
   Reset phyReset <- mkSyncReset(2, defaultReset, phyClock);
   Reset mgmtReset <- mkSyncReset(2, defaultReset, mgmtClock);

   // DE5 Pins
   De5Leds leds <- mkDe5Leds(defaultClock, txClock, mgmtClock, phyClock);
   De5SfpCtrl#(4) sfpctrl <- mkDe5SfpCtrl();
   De5Buttons#(4) buttons <- mkDe5Buttons(clocked_by mgmtClock, reset_by mgmtReset);

   // Mac + Phy
   EthPhyIfc phys <- mkAlteraEthPhy(defaultClock, phyClock, txClock, defaultReset);

   Clock rxClock = phys.rx_clkout;
   Reset rxReset <- mkSyncReset(2, defaultReset, rxClock);
   Vector#(4, EthMacIfc) mac <- replicateM(mkEthMac(defaultClock, txClock, rxClock, txReset));

   function Get#(Bit#(72)) getTx(EthMacIfc _mac); return _mac.tx; endfunction
   function Put#(Bit#(72)) getRx(EthMacIfc _mac); return _mac.rx; endfunction
   mapM(uncurry(mkConnection), zip(map(getTx, mac), phys.tx));
   mapM(uncurry(mkConnection), zip(phys.rx, map(getRx, mac)));

   NullAPI api <- mkNullAPI(indication);

   interface request = api.request;
   interface `PinType pins;
      method Action osc_50(Bit#(1) b3d, Bit#(1) b4a, Bit#(1) b4d, Bit#(1) b7a, Bit#(1) b7d, Bit#(1) b8a, Bit#(1) b8d);
         clk_50_wire <= b4a;
      endmethod
      method serial_tx_data = phys.serial_tx;
      method serial_rx = phys.serial_rx;
      method Action sfp(Bit#(1) refclk);
         clk_644_wire <= refclk;
      endmethod
      interface i2c = clocks.i2c;
      interface led = leds.led_out;
      interface led_bracket = leds.led_out;
      interface sfpctrl = sfpctrl;
      interface buttons = buttons.pins;
      interface deleteme_unused_clock = defaultClock;
      interface deleteme_unused_clock2 = clocks.clock_50;
      interface deleteme_unused_clock3 = defaultClock;
      interface deleteme_unused_reset = defaultReset;
   endinterface
endmodule
endpackage


changed num of servers to 3

changed num of servers to 3

import DefaultValue::*;

 typedef 32 IP_ADDR_LEN;
 typedef 48 MAC_ADDR_LEN;
 typedef 3 NUM_OF_SERVERS;
 typedef 4 NUM_OF_PORTS;

 typedef 8 DEFAULT_FIFO_LEN;

 typedef Bit#(IP_ADDR_LEN) IP;
 typedef Bit#(MAC_ADDR_LEN) MAC;
 typedef Bit#(4) ServerIndex; /* bits to represent num of servers */
 typedef Bit#(3) PortIndex; /* bits to represent num of ports */
 typedef Bit#(32) Address;

 typedef 16 RING_BUFFER_SIZE; /* make sure it is a power of 2 */

 typedef enum {CONFIG, RUN} State deriving(Bits, Eq);

 typedef struct {
      IP server_ip;
      MAC server_mac;
 } TableData deriving(Bits, Eq); /* Each entry in the table */

 instance DefaultValue#(TableData);
      defaultValue = TableData {
                         server_ip : 0,
                         server_mac : 0
                      };
 endinstance

import DefaultValue::*;

 typedef 32 IP_ADDR_LEN;
 typedef 48 MAC_ADDR_LEN;
 typedef 2 NUM_OF_SERVERS;
 typedef 4 NUM_OF_PORTS;

 typedef 8 DEFAULT_FIFO_LEN;

 typedef Bit#(IP_ADDR_LEN) IP;
 typedef Bit#(MAC_ADDR_LEN) MAC;
 typedef Bit#(4) ServerIndex; /* bits to represent num of servers */
 typedef Bit#(3) PortIndex; /* bits to represent num of ports */
 typedef Bit#(32) Address;

 typedef 16 RING_BUFFER_SIZE; /* make sure it is a power of 2 */

 typedef enum {CONFIG, RUN} State deriving(Bits, Eq);

 typedef struct {
      IP server_ip;
      MAC server_mac;
 } TableData deriving(Bits, Eq); /* Each entry in the table */

 instance DefaultValue#(TableData);
      defaultValue = TableData {
                         server_ip : 0,
                         server_mac : 0
                      };
 endinstance


typedef DataBusWidth and NumberOfMasters for all host interfaces

Change-Id: I396ce5d2918d8a8b186cd9cb98df77f8c90fd0b4

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

////////////////////////////// common /////////////////////////////////

`ifndef DataBusWidth
`define DataBusWidth 64
`endif

typedef `DataBusWidth DataBusWidth;
typedef `NumberOfMasters NumberOfMasters;

////////////////////////////// Bsim /////////////////////////////////
`ifdef BsimHostTypeIF

import Vector            :: *;
import AxiMasterSlave    :: *;
import MemTypes          :: *;

// this interface should allow for different master and slave bus paraters;
interface BsimHost#(numeric type clientAddrWidth, numeric type clientBusWidth, numeric type clientIdWidth,
		    numeric type serverAddrWidth, numeric type serverBusWidth, numeric type serverIdWidth,
		    numeric type nSlaves);
   interface MemMaster#(clientAddrWidth, clientBusWidth)  mem_client;
   interface Vector#(nSlaves,Axi3Slave#(serverAddrWidth,  serverBusWidth, serverIdWidth))  axi_servers;
   interface Clock doubleClock;
   interface Reset doubleReset;
endinterface

typedef BsimHost#(32,32,12,40,DataBusWidth,6,NumberOfMasters) HostType;
`endif

////////////////////////////// PciE /////////////////////////////////
`ifdef PcieHostTypeIF

import Vector            :: *;
import GetPut            :: *;
import ClientServer      :: *;
import PCIE               :: *;
import PCIEWRAPPER       :: *;
import PcieCsr           :: *;
import MemTypes          :: *;
import Bscan             :: *;
`ifndef BSIM
import PcieEndpointX7    :: *;
`endif

interface PcieHost#(numeric type dsz, numeric type nSlaves);
   interface Vector#(16,ReadOnly_MSIX_Entry)     msixEntry;
   interface MemMaster#(32,32)                   master;
   interface Vector#(nSlaves,MemSlave#(40,dsz))  slave;
   interface Put#(Tuple2#(Bit#(64),Bit#(32)))    interruptRequest;
   interface Client#(TLPData#(16), TLPData#(16)) pci;
   interface BscanTop bscanif;
endinterface

interface PcieHostTop;
   interface Clock tepClock125;
   interface Reset tepReset125;
   interface PcieHost#(DataBusWidth, NumberOfMasters) tpciehost;
`ifndef BSIM
   interface Clock tsys_clk_200mhz;
   interface Clock tsys_clk_200mhz_buf;
   interface Clock tpci_clk_100mhz_buf;
   interface PcieEndpointX7#(PcieLanes) tep7;
`endif
   interface Clock portalClock;
   interface Reset portalReset;
   interface Clock doubleClock;
   interface Reset doubleReset;
endinterface

typedef PcieHostTop HostType;
`endif

////////////////////////////// Zynq /////////////////////////////////
`ifdef ZynqHostTypeIF
import PS7LIB::*;

typedef PS7 HostType;

export PS7LIB::*;
export HostType;
`endif

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

////////////////////////////// Bsim /////////////////////////////////
`ifdef BsimHostTypeIF

import Vector            :: *;
import AxiMasterSlave    :: *;
import MemTypes          :: *;

`ifndef DataBusWidth
`define DataBusWidth 64
`endif

typedef `NumberOfMasters NumberOfMasters;
typedef `DataBusWidth DataBusWidth;

// this interface should allow for different master and slave bus paraters;
interface BsimHost#(numeric type clientAddrWidth, numeric type clientBusWidth, numeric type clientIdWidth,
		    numeric type serverAddrWidth, numeric type serverBusWidth, numeric type serverIdWidth,
		    numeric type nSlaves);
   interface MemMaster#(clientAddrWidth, clientBusWidth)  mem_client;
   interface Vector#(nSlaves,Axi3Slave#(serverAddrWidth,  serverBusWidth, serverIdWidth))  axi_servers;
   interface Clock doubleClock;
   interface Reset doubleReset;
endinterface

typedef BsimHost#(32,32,12,40,DataBusWidth,6,NumberOfMasters) HostType;
`endif

////////////////////////////// PciE /////////////////////////////////
`ifdef PcieHostTypeIF

import Vector            :: *;
import GetPut            :: *;
import ClientServer      :: *;
import PCIE               :: *;
import PCIEWRAPPER       :: *;
import PcieCsr           :: *;
import MemTypes          :: *;
import Bscan             :: *;
`ifndef BSIM
import PcieEndpointX7    :: *;
`endif

`ifndef DataBusWidth
`define DataBusWidth 64
`endif

typedef `DataBusWidth DataBusWidth;
typedef `NumberOfMasters NumberOfMasters;

interface PcieHost#(numeric type dsz, numeric type nSlaves);
   interface Vector#(16,ReadOnly_MSIX_Entry)     msixEntry;
   interface MemMaster#(32,32)                   master;
   interface Vector#(nSlaves,MemSlave#(40,dsz))  slave;
   interface Put#(Tuple2#(Bit#(64),Bit#(32)))    interruptRequest;
   interface Client#(TLPData#(16), TLPData#(16)) pci;
   interface BscanTop bscanif;
endinterface

interface PcieHostTop;
   interface Clock tepClock125;
   interface Reset tepReset125;
   interface PcieHost#(DataBusWidth, NumberOfMasters) tpciehost;
`ifndef BSIM
   interface Clock tsys_clk_200mhz;
   interface Clock tsys_clk_200mhz_buf;
   interface Clock tpci_clk_100mhz_buf;
   interface PcieEndpointX7#(PcieLanes) tep7;
`endif
   interface Clock portalClock;
   interface Reset portalReset;
   interface Clock doubleClock;
   interface Reset doubleReset;
endinterface

typedef PcieHostTop HostType;
`endif

////////////////////////////// Zynq /////////////////////////////////
`ifdef ZynqHostTypeIF
import PS7LIB::*;

typedef PS7 HostType;

export PS7LIB::*;
export HostType;
`endif


give mkSerialPortalMux a cycle for ready channel arbitration

// 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 BuildVector::*;
import ClientServer::*;
import Connectable::*;
import DefaultValue::*;
import FIFOF::*;
import Gearbox::*;
import GetPut::*;
import MIMO::*;
import Probe::*;
import Vector::*;

import Pipe::*;
import Portal::*;
import MemTypes::*;
import ConnectalMemory::*;
import SharedMemoryFifo::*;

module mkSharedMemoryRequestPortal#(PipePortal#(numRequests, numIndications, 32) portal,
   function Bit#(16) messageSize(Bit#(16) methodNumber),
   Vector#(2, MemReadEngineServer#(64)) readEngine, Vector#(2, MemWriteEngineServer#(64)) writeEngine)(SharedMemoryPortal#(64));
   SharedMemoryPipeOut#(64,numRequests) pipeOut <- mkSharedMemoryPipeOut(readEngine, writeEngine);
   SerialPortalDemux#(numRequests) demux <- mkSerialPortalDemux(Method);
   mkConnection(pipeOut.data, demux.inputPipe);
   mapM_(uncurry(mkConnection), zip(demux.data, portal.requests));

   interface SharedMemoryPortalConfig cfg = pipeOut.cfg;
endmodule

// adds a header word to each message out of an indication pipe
module mkFramedMessagePipe#(Integer portalNumber,
			    PipePortal#(numRequests,numIndications,32) pipePortal,
			    function Bit#(16) messageSize(Bit#(16) methodNumber),
			    Integer i)(PipeOut#(Bit#(32)));

   let pipeOut = pipePortal.indications[i];
   Bit#(16) messageBits = messageSize(fromInteger(i));
   Bit#(16) roundup = messageBits[4:0] == 0 ? 0 : 1;
   Bit#(16) numWords = (messageBits >> 5) + roundup;
   Bit#(16) totalWords = numWords + 1;
   Bit#(32) hdr = (fromInteger(portalNumber) << 24) | (fromInteger(i) << 16) | extend(numWords + 1);
   let sendHeader <- mkReg(True);
   Reg#(Bit#(16)) burstLenReg <- mkReg(0);
   PipeOut#(Bit#(32)) framedPipe = (interface PipeOut;
	      method Bit#(32) first() if (pipeOut.notEmpty());
	         if (sendHeader)
		    return hdr;
		 else
		    return pipeOut.first();
	      endmethod
	      method Action deq() if (pipeOut.notEmpty());
	         if (sendHeader) begin
		    sendHeader <= False;
		    burstLenReg <= numWords;
		 end
		 else begin
		    pipeOut.deq();
		    burstLenReg <= burstLenReg - 1;
		    if (burstLenReg == 1)
		       sendHeader <= True;
		 end
	      endmethod
	      method Bool notEmpty(); return pipeOut.notEmpty(); endmethod
	   endinterface);
   if (False) begin // optional pipeline stage
      FIFOF#(Bit#(32)) framedFifo <- mkFIFOF();
      mkConnection(framedPipe, toPipeIn(framedFifo));
      return toPipeOut(framedFifo);
   end
   else begin
      return framedPipe;
   end
endmodule

module mkSharedMemoryIndicationPortal#(PipePortal#(numRequests,numIndications,32) pipePortal,
				       function Bit#(16) messageSize(Bit#(16) methodNumber),
				       Vector#(2, MemReadEngineServer#(64)) readEngines, Vector#(2, MemWriteEngineServer#(64)) writeEngines)
   (SharedMemoryPortal#(64));

   Vector#(numIndications, PipeOut#(Bit#(32))) indicationPipes <- genWithM(mkFramedMessagePipe(0,pipePortal,messageSize));

   SerialPortalMux#(numIndications) serialPortalMux <- mkSerialPortalMux();
   mkConnection(indicationPipes, serialPortalMux.data);
   SharedMemoryPipeIn#(64) pipeIn <- mkSharedMemoryPipeIn(serialPortalMux.outputPipe, readEngines, writeEngines);
   interface SharedMemoryPortalConfig cfg = pipeIn.cfg;
endmodule

interface SerialPortalDemux#(numeric type pipeCount);
   interface Vector#(pipeCount, PipeOut#(Bit#(32))) data;
   interface PipeIn#(Bit#(32))                      inputPipe;
endinterface
interface SerialPortalMux#(numeric type pipeCount);
   interface Vector#(pipeCount, PipeIn#(Bit#(32))) data;
   interface PipeOut#(Bit#(32))                    outputPipe;
endinterface

typedef enum {
   Idle,
   MessageHeader,
   MessageBody,
   Stop
   } SerialPortalState deriving (Bits,Eq);

typedef enum {
   Portal,
   Method
   } SerialPortalDemuxLevel deriving (Bits,Eq);

module mkSerialPortalDemux#(SerialPortalDemuxLevel portalDemux)(SerialPortalDemux#(pipeCount));
   let clock <- exposeCurrentClock();
   let reset <- exposeCurrentReset();
   Reg#(Bit#(16)) messageWordsReg <- mkReg(0);
   Reg#(Bit#(8))  selectorReg <- mkReg(0);
   Reg#(SerialPortalState) state <- mkReg(Idle);
   FIFOF#(Bit#(32)) inputFifo <- mkFIFOF();
   Vector#(pipeCount, FIFOF#(Bit#(32))) dataFifo <- replicateM(mkFIFOF);

   let verbose = False;

   rule idle if (state == Idle);
      state <= MessageHeader;
   endrule

   rule receiveMessageHeader if (state == MessageHeader);
      let hdr <- toGet(inputFifo).get();
      let selector = (portalDemux == Portal) ? hdr[31:24] : hdr[23:16];
      let messageWords = hdr[15:0];
      selectorReg <= selector;
      if (verbose)
         $display("receiveMessageHeader hdr=%x selector=%x messageWords=%d", hdr, selector, messageWords);
      if (portalDemux == Portal) // methodDemux need the header
         dataFifo[selector].enq(hdr);
      messageWordsReg <= messageWords - 1;
      if (messageWords == 1)
         state <= MessageHeader;
      else
         state <= MessageBody;
   endrule

   rule receiveMessage if (state == MessageBody);
      let data <- toGet(inputFifo).get();
      if (verbose)
         $display("receiveMessage data=%x messageWords=%d", data, messageWordsReg);
      if (selectorReg != 8'hFF)
         dataFifo[selectorReg].enq(data);
      messageWordsReg <= messageWordsReg - 1;
      if (messageWordsReg == 1)
         state <= MessageHeader;
   endrule

   interface data      = map(toPipeOut, dataFifo);
   interface inputPipe = toPipeIn(inputFifo);
endmodule

module mkSerialPortalMux(SerialPortalMux#(pipeCount));
   let clock <- exposeCurrentClock;
   let reset <- exposeCurrentReset;
   Reg#(Bit#(16)) messageWordsReg <- mkReg(0);
   Reg#(Bit#(16)) readyChannelReg <- mkReg(0);
   Reg#(Bool)     interruptStatusReg <- mkReg(False);
   Reg#(Bool) paddingReg <- mkReg(False);
   Reg#(SerialPortalState) state <- mkReg(Idle);
   Reg#(Bit#(32)) sglIdReg <- mkReg(0);

   function Bool fifoNotEmpty(FIFOF#(a) fifo); return fifo.notEmpty(); endfunction

   Vector#(pipeCount, FIFOF#(Bit#(32)))   inputFifos <- replicateM(mkFIFOF());
   Vector#(pipeCount, PipeOut#(Bit#(32))) pipes      = map(toPipeOut, inputFifos);
   Vector#(pipeCount, Bool)               readyBits  = map(fifoNotEmpty, inputFifos);
   Bool      interruptStatus = False;
   Bit#(16)  readyChannel = -1;
   FIFOF#(Bit#(32)) outputFifo <- mkFIFOF();

   let verbose = True;
   let stateProbe <- mkProbe();
   let messageWordsProbe <- mkProbe();
   let messageDataProbe <- mkProbe();

   for (Integer i = valueOf(pipeCount) - 1; i >= 0; i = i - 1) begin
      if (readyBits[i]) begin
         interruptStatus = True;
         readyChannel = fromInteger(i);
      end
   end

   rule idle if (state == Idle);
      readyChannelReg <= readyChannel;
      interruptStatusReg <= interruptStatus;
      SerialPortalState nextState = Idle;
      if (interruptStatus)
	 nextState = MessageHeader;

      state <= nextState;
      stateProbe <= nextState;
   endrule

   rule sendHeader if (state == MessageHeader && interruptStatusReg);
      Bit#(32) hdr <- toGet(inputFifos[readyChannelReg]).get();
      Bit#(16) totalWords = hdr[15:0];
      let messageWords = totalWords-1;
      messageWordsProbe <= messageWords;

      messageWordsReg <= messageWords;
      outputFifo.enq(hdr);
      state <= MessageBody;
      stateProbe <= MessageBody;
      messageDataProbe <= hdr;
   endrule

   rule sendMessage if (state == MessageBody);
      messageWordsReg <= messageWordsReg - 1;
      let v <- toGet(inputFifos[readyChannelReg]).get();
      outputFifo.enq(v);
      $display("sendMessage v=%h messageWords=%d paddingReg=%d", v, messageWordsReg, paddingReg);
      if (messageWordsReg == 1) begin
         state <= Idle;
	 stateProbe <= Idle;
      end
      messageDataProbe <= v;
   endrule

   interface data       = map(toPipeIn, inputFifos);
   interface outputPipe = toPipeOut(outputFifo);
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 BuildVector::*;
import ClientServer::*;
import Connectable::*;
import DefaultValue::*;
import FIFOF::*;
import Gearbox::*;
import GetPut::*;
import MIMO::*;
import Probe::*;
import Vector::*;

import Pipe::*;
import Portal::*;
import MemTypes::*;
import ConnectalMemory::*;
import SharedMemoryFifo::*;

module mkSharedMemoryRequestPortal#(PipePortal#(numRequests, numIndications, 32) portal,
   function Bit#(16) messageSize(Bit#(16) methodNumber),
   Vector#(2, MemReadEngineServer#(64)) readEngine, Vector#(2, MemWriteEngineServer#(64)) writeEngine)(SharedMemoryPortal#(64));
   SharedMemoryPipeOut#(64,numRequests) pipeOut <- mkSharedMemoryPipeOut(readEngine, writeEngine);
   SerialPortalDemux#(numRequests) demux <- mkSerialPortalDemux(Method);
   mkConnection(pipeOut.data, demux.inputPipe);
   mapM_(uncurry(mkConnection), zip(demux.data, portal.requests));

   interface SharedMemoryPortalConfig cfg = pipeOut.cfg;
endmodule

// adds a header word to each message out of an indication pipe
module mkFramedMessagePipe#(Integer portalNumber,
			    PipePortal#(numRequests,numIndications,32) pipePortal,
			    function Bit#(16) messageSize(Bit#(16) methodNumber),
			    Integer i)(PipeOut#(Bit#(32)));

   let pipeOut = pipePortal.indications[i];
   Bit#(16) messageBits = messageSize(fromInteger(i));
   Bit#(16) roundup = messageBits[4:0] == 0 ? 0 : 1;
   Bit#(16) numWords = (messageBits >> 5) + roundup;
   Bit#(16) totalWords = numWords + 1;
   Bit#(32) hdr = (fromInteger(portalNumber) << 24) | (fromInteger(i) << 16) | extend(numWords + 1);
   let sendHeader <- mkReg(True);
   Reg#(Bit#(16)) burstLenReg <- mkReg(0);
   PipeOut#(Bit#(32)) framedPipe = (interface PipeOut;
	      method Bit#(32) first() if (pipeOut.notEmpty());
	         if (sendHeader)
		    return hdr;
		 else
		    return pipeOut.first();
	      endmethod
	      method Action deq() if (pipeOut.notEmpty());
	         if (sendHeader) begin
		    sendHeader <= False;
		    burstLenReg <= numWords;
		 end
		 else begin
		    pipeOut.deq();
		    burstLenReg <= burstLenReg - 1;
		    if (burstLenReg == 1)
		       sendHeader <= True;
		 end
	      endmethod
	      method Bool notEmpty(); return pipeOut.notEmpty(); endmethod
	   endinterface);
   if (False) begin // optional pipeline stage
      FIFOF#(Bit#(32)) framedFifo <- mkFIFOF();
      mkConnection(framedPipe, toPipeIn(framedFifo));
      return toPipeOut(framedFifo);
   end
   else begin
      return framedPipe;
   end
endmodule

module mkSharedMemoryIndicationPortal#(PipePortal#(numRequests,numIndications,32) pipePortal,
				       function Bit#(16) messageSize(Bit#(16) methodNumber),
				       Vector#(2, MemReadEngineServer#(64)) readEngines, Vector#(2, MemWriteEngineServer#(64)) writeEngines)
   (SharedMemoryPortal#(64));

   Vector#(numIndications, PipeOut#(Bit#(32))) indicationPipes <- genWithM(mkFramedMessagePipe(0,pipePortal,messageSize));

   SerialPortalMux#(numIndications) serialPortalMux <- mkSerialPortalMux();
   mkConnection(indicationPipes, serialPortalMux.data);
   SharedMemoryPipeIn#(64) pipeIn <- mkSharedMemoryPipeIn(serialPortalMux.outputPipe, readEngines, writeEngines);
   interface SharedMemoryPortalConfig cfg = pipeIn.cfg;
endmodule

interface SerialPortalDemux#(numeric type pipeCount);
   interface Vector#(pipeCount, PipeOut#(Bit#(32))) data;
   interface PipeIn#(Bit#(32))                      inputPipe;
endinterface
interface SerialPortalMux#(numeric type pipeCount);
   interface Vector#(pipeCount, PipeIn#(Bit#(32))) data;
   interface PipeOut#(Bit#(32))                    outputPipe;
endinterface

typedef enum {
   Idle,
   MessageHeader,
   MessageBody,
   Stop
   } SerialPortalState deriving (Bits,Eq);

typedef enum {
   Portal,
   Method
   } SerialPortalDemuxLevel deriving (Bits,Eq);

module mkSerialPortalDemux#(SerialPortalDemuxLevel portalDemux)(SerialPortalDemux#(pipeCount));
   let clock <- exposeCurrentClock();
   let reset <- exposeCurrentReset();
   Reg#(Bit#(16)) messageWordsReg <- mkReg(0);
   Reg#(Bit#(8))  selectorReg <- mkReg(0);
   Reg#(SerialPortalState) state <- mkReg(Idle);
   FIFOF#(Bit#(32)) inputFifo <- mkFIFOF();
   Vector#(pipeCount, FIFOF#(Bit#(32))) dataFifo <- replicateM(mkFIFOF);

   let verbose = False;

   rule idle if (state == Idle);
      state <= MessageHeader;
   endrule

   rule receiveMessageHeader if (state == MessageHeader);
      let hdr <- toGet(inputFifo).get();
      let selector = (portalDemux == Portal) ? hdr[31:24] : hdr[23:16];
      let messageWords = hdr[15:0];
      selectorReg <= selector;
      if (verbose)
         $display("receiveMessageHeader hdr=%x selector=%x messageWords=%d", hdr, selector, messageWords);
      if (portalDemux == Portal) // methodDemux need the header
         dataFifo[selector].enq(hdr);
      messageWordsReg <= messageWords - 1;
      if (messageWords == 1)
         state <= MessageHeader;
      else
         state <= MessageBody;
   endrule

   rule receiveMessage if (state == MessageBody);
      let data <- toGet(inputFifo).get();
      if (verbose)
         $display("receiveMessage data=%x messageWords=%d", data, messageWordsReg);
      if (selectorReg != 8'hFF)
         dataFifo[selectorReg].enq(data);
      messageWordsReg <= messageWordsReg - 1;
      if (messageWordsReg == 1)
         state <= MessageHeader;
   endrule

   interface data      = map(toPipeOut, dataFifo);
   interface inputPipe = toPipeIn(inputFifo);
endmodule

module mkSerialPortalMux(SerialPortalMux#(pipeCount));
   let clock <- exposeCurrentClock;
   let reset <- exposeCurrentReset;
   Reg#(Bit#(16)) messageWordsReg <- mkReg(0);
   Reg#(Bit#(16)) methodIdReg <- mkReg(0);
   Reg#(Bool) paddingReg <- mkReg(False);
   Reg#(SerialPortalState) state <- mkReg(Idle);
   Reg#(Bit#(32)) sglIdReg <- mkReg(0);

   function Bool fifoNotEmpty(FIFOF#(a) fifo); return fifo.notEmpty(); endfunction

   Vector#(pipeCount, FIFOF#(Bit#(32)))   inputFifos <- replicateM(mkFIFOF());
   Vector#(pipeCount, PipeOut#(Bit#(32))) pipes      = map(toPipeOut, inputFifos);
   Vector#(pipeCount, Bool)               readyBits  = map(fifoNotEmpty, inputFifos);
   Bool      interruptStatus = False;
   Bit#(16)  readyChannel = -1;
   FIFOF#(Bit#(32)) outputFifo <- mkFIFOF();

   let verbose = True;
   let stateProbe <- mkProbe();
   let messageWordsProbe <- mkProbe();
   let messageDataProbe <- mkProbe();

   for (Integer i = valueOf(pipeCount) - 1; i >= 0; i = i - 1) begin
      if (readyBits[i]) begin
         interruptStatus = True;
         readyChannel = fromInteger(i);
      end
   end

   rule idle if (state == Idle);
      state <= MessageHeader;
      stateProbe <= MessageHeader;
   endrule

   rule sendHeader if (state == MessageHeader && interruptStatus);
      Bit#(32) hdr <- toGet(inputFifos[readyChannel]).get();
      Bit#(16) totalWords = hdr[15:0];
      let messageWords = totalWords-1;
      messageWordsProbe <= messageWords;

      messageWordsReg <= messageWords;
      methodIdReg <= readyChannel;
      outputFifo.enq(hdr);
      state <= MessageBody;
      stateProbe <= MessageBody;
      messageDataProbe <= hdr;
   endrule

   rule sendMessage if (state == MessageBody);
      messageWordsReg <= messageWordsReg - 1;
      let v <- toGet(inputFifos[methodIdReg]).get();
      outputFifo.enq(v);
      $display("sendMessage v=%h messageWords=%d paddingReg=%d", v, messageWordsReg, paddingReg);
      if (messageWordsReg == 1) begin
         state <= MessageHeader;
	 stateProbe <= MessageHeader;
      end
      messageDataProbe <= v;
   endrule

   interface data       = map(toPipeIn, inputFifos);
   interface outputPipe = toPipeOut(outputFifo);
endmodule


updated PcieTracer usage of Bscan

updated PcieTracer usage of Bscan

// 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 Vector            :: *;
import Clocks          :: *;
import GetPut            :: *;
import Connectable    :: *;
import FIFO              :: *;
import FIFOF        :: *;
import PCIE               :: *;
import BRAM         :: *;
import Bscan          :: *;
import BramMux        :: *;

typedef 11 TlpTraceAddrSize;
typedef TAdd#(TlpTraceAddrSize,1) TlpTraceAddrSize1;

typedef struct {
    Bit#(32) timestamp;
    Bit#(7) source;   // 4==frombus 8=tobus
    TLPData#(16) tlp; // 153 bits
} TimestampedTlpData deriving (Bits);
typedef SizeOf#(TimestampedTlpData) TimestampedTlpDataSize;
typedef SizeOf#(TLPData#(16)) TlpData16Size;
typedef SizeOf#(TLPCompletionHeader) TLPCompletionHeaderSize;
interface TlpTrace;
   interface Get#(TimestampedTlpData) tlp;
endinterface

interface TlpTraceData;
   interface Reg#(Bool)     tlpTracing;
   interface Reg#(Bit#(TlpTraceAddrSize)) tlpTraceLimit;
   interface Reg#(Bit#(TlpTraceAddrSize)) fromPcieTraceBramWrAddr;
   interface Reg#(Bit#(TlpTraceAddrSize))   toPcieTraceBramWrAddr;
   interface BRAMServer#(Bit#(TAdd#(TlpTraceAddrSize,1)), TimestampedTlpData) bramServer;
endinterface
interface PcieTracer;
   interface Client#(TLPData#(16), TLPData#(16)) pci;
   interface Put#(TimestampedTlpData) trace;
   interface Server#(TLPData#(16), TLPData#(16)) bus;
   interface TlpTraceData tlpdata;
endinterface: PcieTracer

// The PCIe-to-AXI bridge puts all of the elements together
(* synthesize *)
module mkPcieTracer(PcieTracer);
   // Trace Support
   Reg#(Bool) tlpTracingReg        <- mkReg(False);
   Reg#(Bit#(TlpTraceAddrSize)) tlpTraceLimitReg <- mkReg(0);
   Reg#(Bit#(TlpTraceAddrSize)) fromPcieTraceBramWrAddrReg <- mkReg(0);
   Reg#(Bit#(TlpTraceAddrSize))   toPcieTraceBramWrAddrReg <- mkReg(0);
   Integer memorySize = 2**valueOf(TlpTraceAddrSize);
   // TODO: lift BscanBram to *Top.bsv
`ifndef BSIM
   Reg#(Bit#(TAdd#(TlpTraceAddrSize,1))) bscanPcieTraceBramWrAddrReg <- mkReg(0);
   BscanTop bscan <- mkBscanTop(1);
   BscanBram#(Bit#(TAdd#(TlpTraceAddrSize,1)), TimestampedTlpData) pcieBscanBram <- mkBscanBram(123, bscanPcieTraceBramWrAddrReg, bscan);
`endif

   BRAM_Configure bramCfg = defaultValue;
   bramCfg.memorySize = memorySize;
   bramCfg.latency = 1;
   BRAM2Port#(Bit#(TlpTraceAddrSize), TimestampedTlpData) fromPcieTraceBram <- mkBRAM2Server(bramCfg);
   BRAM2Port#(Bit#(TlpTraceAddrSize), TimestampedTlpData) toPcieTraceBram <- mkBRAM2Server(bramCfg);
   Vector#(2, BRAMServer#(Bit#(TlpTraceAddrSize), TimestampedTlpData)) bramServers;
   bramServers[0] = fromPcieTraceBram.portA;
   bramServers[1] =   toPcieTraceBram.portA;
   BramServerMux#(TAdd#(TlpTraceAddrSize,1), TimestampedTlpData) bramMuxReg <- mkBramServerMux(bramServers);

`ifndef BSIM
   Vector#(2, BRAMServer#(Bit#(TlpTraceAddrSize), TimestampedTlpData)) bscanBramServers;
   bscanBramServers[0] = fromPcieTraceBram.portB;
   bscanBramServers[1] =   toPcieTraceBram.portB;
   BramServerMux#(TAdd#(TlpTraceAddrSize,1), TimestampedTlpData) bscanBramMux <- mkBramServerMux(bscanBramServers);
   mkConnection(pcieBscanBram.bramClient, bscanBramMux.bramServer);
`endif

   Reg#(Bit#(32)) timestamp <- mkReg(0);
   rule incTimestamp;
       timestamp <= timestamp + 1;
   endrule
//   rule endTrace if (tlpTracingReg && tlpTraceLimitReg != 0 && tlpTraceBramWrAddr > truncate(tlpTraceLimitReg));
//       tlpTracingReg <= False;
//   endrule

   FIFO#(TLPData#(16)) tlpFromBusFifo <- mkFIFO();
   FIFO#(TLPData#(16)) tlpToBusFifo <- mkFIFO();
   Reg#(Bool) skippingIncomingTlps <- mkReg(False);
   PulseWire fromPcie <- mkPulseWire;
   PulseWire   toPcie <- mkPulseWire;
   Wire#(TLPData#(16)) fromPcieTlp <- mkDWire(unpack(0));
   Wire#(TLPData#(16))   toPcieTlp <- mkDWire(unpack(0));

   rule doTracing if (fromPcie || toPcie);
      TimestampedTlpData fromttd = fromPcie ? TimestampedTlpData { timestamp: timestamp, source: 7'h04, tlp: fromPcieTlp } : unpack(0);
      fromPcieTraceBram.portA.request.put(BRAMRequest{ write: True, responseOnWrite: False, address: truncate(fromPcieTraceBramWrAddrReg), datain: fromttd });
      fromPcieTraceBramWrAddrReg <= fromPcieTraceBramWrAddrReg + 1;

      TimestampedTlpData   tottd = toPcie ? TimestampedTlpData { timestamp: timestamp, source: 7'h08, tlp: toPcieTlp } : unpack(0);
      toPcieTraceBram.portA.request.put(BRAMRequest{ write: True, responseOnWrite: False, address: truncate(toPcieTraceBramWrAddrReg), datain: tottd });
      toPcieTraceBramWrAddrReg <= toPcieTraceBramWrAddrReg + 1;
   endrule

   interface Server     bus;
       interface Get response;
           method ActionValue#(TLPData#(16)) get();
           let tlp = tlpFromBusFifo.first;
           tlpFromBusFifo.deq();
           //$display("tlp in: %h\n", tlp);
           if (tlpTracingReg) begin
               TLPMemoryIO3DWHeader hdr_3dw = unpack(tlp.data);
               // skip root_broadcast_messages sent to tlp.hit 0
               if (tlp.sof && tlp.hit == 0 && hdr_3dw.pkttype != COMPLETION) begin
 	          skippingIncomingTlps <= True;
	       end
	       else if (skippingIncomingTlps && !tlp.sof) begin
	          // do nothing
	       end
	       else begin
	          fromPcie.send();
	          fromPcieTlp <= tlp;
	           skippingIncomingTlps <= False;
	       end
           end
           return tlp;
           endmethod
       endinterface

       interface Put request;
           method Action put(TLPData#(16) tlp);
           tlpToBusFifo.enq(tlp);
           if (tlpTracingReg) begin
	      toPcie.send();
	      toPcieTlp <= tlp;
           end
           endmethod
       endinterface
   endinterface

   interface Client    pci;
      interface request = toGet(tlpToBusFifo);
      interface response = toPut(tlpFromBusFifo);
   endinterface
   interface Put trace;
       method Action put(TimestampedTlpData ttd);
	   if (tlpTracingReg) begin
	       ttd.timestamp = timestamp;
	       toPcieTraceBram.portA.request.put(BRAMRequest{ write: True, responseOnWrite: False, address: truncate(toPcieTraceBramWrAddrReg), datain: ttd });
	       toPcieTraceBramWrAddrReg <= toPcieTraceBramWrAddrReg + 1;
	   end
       endmethod
   endinterface: trace
   interface TlpTraceData tlpdata;
      interface Reg tlpTracing    = tlpTracingReg;
      interface Reg tlpTraceLimit = tlpTraceLimitReg;
      interface Reg fromPcieTraceBramWrAddr = fromPcieTraceBramWrAddrReg;
      interface Reg   toPcieTraceBramWrAddr =   toPcieTraceBramWrAddrReg;
      interface Server bramServer = bramMuxReg.bramServer;
   endinterface
endmodule: mkPcieTracer

// 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 Vector            :: *;
import Clocks          :: *;
import GetPut            :: *;
import Connectable    :: *;
import FIFO              :: *;
import FIFOF        :: *;
import PCIE               :: *;
import BRAM         :: *;
import Bscan          :: *;
import BramMux        :: *;

typedef 11 TlpTraceAddrSize;
typedef TAdd#(TlpTraceAddrSize,1) TlpTraceAddrSize1;

typedef struct {
    Bit#(32) timestamp;
    Bit#(7) source;   // 4==frombus 8=tobus
    TLPData#(16) tlp; // 153 bits
} TimestampedTlpData deriving (Bits);
typedef SizeOf#(TimestampedTlpData) TimestampedTlpDataSize;
typedef SizeOf#(TLPData#(16)) TlpData16Size;
typedef SizeOf#(TLPCompletionHeader) TLPCompletionHeaderSize;
interface TlpTrace;
   interface Get#(TimestampedTlpData) tlp;
endinterface

interface TlpTraceData;
   interface Reg#(Bool)     tlpTracing;
   interface Reg#(Bit#(TlpTraceAddrSize)) tlpTraceLimit;
   interface Reg#(Bit#(TlpTraceAddrSize)) fromPcieTraceBramWrAddr;
   interface Reg#(Bit#(TlpTraceAddrSize))   toPcieTraceBramWrAddr;
   interface BRAMServer#(Bit#(TAdd#(TlpTraceAddrSize,1)), TimestampedTlpData) bramServer;
endinterface
interface PcieTracer;
   interface Client#(TLPData#(16), TLPData#(16)) pci;
   interface Put#(TimestampedTlpData) trace;
   interface Server#(TLPData#(16), TLPData#(16)) bus;
   interface TlpTraceData tlpdata;
endinterface: PcieTracer

// The PCIe-to-AXI bridge puts all of the elements together
(* synthesize *)
module mkPcieTracer(PcieTracer);

   // Clocks and Resets
   Clock defaultClock <- exposeCurrentClock();
   Reset defaultReset <- exposeCurrentReset();

   // Trace Support
   Reg#(Bool) tlpTracingReg        <- mkReg(False);
   Reg#(Bit#(TlpTraceAddrSize)) tlpTraceLimitReg <- mkReg(0);
   Reg#(Bit#(TlpTraceAddrSize)) fromPcieTraceBramWrAddrReg <- mkReg(0);
   Reg#(Bit#(TlpTraceAddrSize))   toPcieTraceBramWrAddrReg <- mkReg(0);
   Integer memorySize = 2**valueOf(TlpTraceAddrSize);
   // TODO: lift BscanBram to *Top.bsv
`ifdef BSIM
   Clock jtagClock = defaultClock;
   Reset jtagReset = defaultReset;
`else
   Reg#(Bit#(TAdd#(TlpTraceAddrSize,1))) bscanPcieTraceBramWrAddrReg <- mkReg(0);
   BscanBram#(Bit#(TAdd#(TlpTraceAddrSize,1)), TimestampedTlpData) pcieBscanBram <- mkBscanBram(1, bscanPcieTraceBramWrAddrReg);
   Clock jtagClock = pcieBscanBram.jtagClock;
   Reset jtagReset = pcieBscanBram.jtagReset;
`endif

   BRAM_Configure bramCfg = defaultValue;
   bramCfg.memorySize = memorySize;
   bramCfg.latency = 1;
   BRAM2Port#(Bit#(TlpTraceAddrSize), TimestampedTlpData) fromPcieTraceBram <- mkSyncBRAM2Server(bramCfg, defaultClock, defaultReset,
												 jtagClock, jtagReset);
   BRAM2Port#(Bit#(TlpTraceAddrSize), TimestampedTlpData) toPcieTraceBram <- mkSyncBRAM2Server(bramCfg, defaultClock, defaultReset,
											       jtagClock, jtagReset);
   Vector#(2, BRAMServer#(Bit#(TlpTraceAddrSize), TimestampedTlpData)) bramServers;
   bramServers[0] = fromPcieTraceBram.portA;
   bramServers[1] =   toPcieTraceBram.portA;
   BramServerMux#(TAdd#(TlpTraceAddrSize,1), TimestampedTlpData) bramMuxReg <- mkBramServerMux(bramServers);

`ifndef BSIM
   Vector#(2, BRAMServer#(Bit#(TlpTraceAddrSize), TimestampedTlpData)) bscanBramServers;
   bscanBramServers[0] = fromPcieTraceBram.portB;
   bscanBramServers[1] =   toPcieTraceBram.portB;
   BramServerMux#(TAdd#(TlpTraceAddrSize,1), TimestampedTlpData) bscanBramMux <- mkBramServerMux(bscanBramServers, clocked_by jtagClock, reset_by jtagReset);
   mkConnection(pcieBscanBram.bramClient, bscanBramMux.bramServer, clocked_by jtagClock, reset_by jtagReset);
`endif

   Reg#(Bit#(32)) timestamp <- mkReg(0);
   rule incTimestamp;
       timestamp <= timestamp + 1;
   endrule
//   rule endTrace if (tlpTracingReg && tlpTraceLimitReg != 0 && tlpTraceBramWrAddr > truncate(tlpTraceLimitReg));
//       tlpTracingReg <= False;
//   endrule

   FIFO#(TLPData#(16)) tlpFromBusFifo <- mkFIFO();
   FIFO#(TLPData#(16)) tlpToBusFifo <- mkFIFO();
   Reg#(Bool) skippingIncomingTlps <- mkReg(False);
   PulseWire fromPcie <- mkPulseWire;
   PulseWire   toPcie <- mkPulseWire;
   Wire#(TLPData#(16)) fromPcieTlp <- mkDWire(unpack(0));
   Wire#(TLPData#(16))   toPcieTlp <- mkDWire(unpack(0));

   rule doTracing if (fromPcie || toPcie);
      TimestampedTlpData fromttd = fromPcie ? TimestampedTlpData { timestamp: timestamp, source: 7'h04, tlp: fromPcieTlp } : unpack(0);
      fromPcieTraceBram.portA.request.put(BRAMRequest{ write: True, responseOnWrite: False, address: truncate(fromPcieTraceBramWrAddrReg), datain: fromttd });
      fromPcieTraceBramWrAddrReg <= fromPcieTraceBramWrAddrReg + 1;

      TimestampedTlpData   tottd = toPcie ? TimestampedTlpData { timestamp: timestamp, source: 7'h08, tlp: toPcieTlp } : unpack(0);
      toPcieTraceBram.portA.request.put(BRAMRequest{ write: True, responseOnWrite: False, address: truncate(toPcieTraceBramWrAddrReg), datain: tottd });
      toPcieTraceBramWrAddrReg <= toPcieTraceBramWrAddrReg + 1;
   endrule

   interface Server     bus;
       interface Get response;
           method ActionValue#(TLPData#(16)) get();
           let tlp = tlpFromBusFifo.first;
           tlpFromBusFifo.deq();
           //$display("tlp in: %h\n", tlp);
           if (tlpTracingReg) begin
               TLPMemoryIO3DWHeader hdr_3dw = unpack(tlp.data);
               // skip root_broadcast_messages sent to tlp.hit 0
               if (tlp.sof && tlp.hit == 0 && hdr_3dw.pkttype != COMPLETION) begin
 	          skippingIncomingTlps <= True;
	       end
	       else if (skippingIncomingTlps && !tlp.sof) begin
	          // do nothing
	       end
	       else begin
	          fromPcie.send();
	          fromPcieTlp <= tlp;
	           skippingIncomingTlps <= False;
	       end
           end
           return tlp;
           endmethod
       endinterface

       interface Put request;
           method Action put(TLPData#(16) tlp);
           tlpToBusFifo.enq(tlp);
           if (tlpTracingReg) begin
	      toPcie.send();
	      toPcieTlp <= tlp;
           end
           endmethod
       endinterface
   endinterface

   interface Client    pci;
      interface request = toGet(tlpToBusFifo);
      interface response = toPut(tlpFromBusFifo);
   endinterface
   interface Put trace;
       method Action put(TimestampedTlpData ttd);
	   if (tlpTracingReg) begin
	       ttd.timestamp = timestamp;
	       toPcieTraceBram.portA.request.put(BRAMRequest{ write: True, responseOnWrite: False, address: truncate(toPcieTraceBramWrAddrReg), datain: ttd });
	       toPcieTraceBramWrAddrReg <= toPcieTraceBramWrAddrReg + 1;
	   end
       endmethod
   endinterface: trace
   interface TlpTraceData tlpdata;
      interface Reg tlpTracing    = tlpTracingReg;
      interface Reg tlpTraceLimit = tlpTraceLimitReg;
      interface Reg fromPcieTraceBramWrAddr = fromPcieTraceBramWrAddrReg;
      interface Reg   toPcieTraceBramWrAddr =   toPcieTraceBramWrAddrReg;
      interface Server bramServer = bramMuxReg.bramServer;
   endinterface
endmodule: mkPcieTracer