else case should take care both XILINX and BSIM

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

// NOTE:
// Implement a store-and-forward mechanism between ring-buffer and
// main packet memory. Packets are buffered completely in ring buffer
// before it is sent to main memory and vice versa.

import BuildVector::*;
import Connectable::*;
import Clocks::*;
import Cntrs::*;
import ClientServer::*;
import DefaultValue::*;
import DbgTypes::*;
import Ethernet::*;
import EthMac::*;
import FIFO::*;
import FIFOF::*;
import GetPut::*;
import Gearbox::*;
import MemTypes::*;
import MemServer::*;
import MemServerInternal::*;
import MemMgmt::*;
import PacketBuffer::*;
import SharedBuff::*;
import SharedBuffMMU::*;
import SpecialFIFOs::*;
import Vector::*;
import Pipe::*;
import DbgTypes::*;

interface StoreAndFwdFromRingToMem;
   interface PktReadClient readClient;
   interface MemAllocClient malloc;
   interface MemWriteClient#(`DataBusWidth) writeClient;
   interface PipeOut#(PacketInstance) eventPktCommitted;
endinterface

module mkStoreAndFwdFromRingToMem(StoreAndFwdFromRingToMem)
   provisos (Div#(`DataBusWidth, 8, bytesPerBeat)
            ,Log#(bytesPerBeat, beatShift));

   let verbose = False;

   // RingBuffer Read Client
   FIFO#(EtherData) readDataFifo <- mkFIFO;
   FIFO#(Bit#(EtherLen)) readLenFifo <- mkFIFO;
   FIFO#(EtherReq) readReqFifo <- mkFIFO;

   // Memory Client
   FIFO#(MemRequest) writeReqFifo <- mkSizedFIFO(4);
   FIFO#(MemData#(`DataBusWidth)) writeDataFifo <- mkSizedFIFO(16);
   FIFO#(Bit#(MemTagSize)) writeDoneFifo <- mkSizedFIFO(4);
   MemWriteClient#(`DataBusWidth) dmaWriteClient = (interface MemWriteClient;
   interface Get writeReq = toGet(writeReqFifo);
   interface Get writeData = toGet(writeDataFifo);
   interface Put writeDone = toPut(writeDoneFifo);
   endinterface);

   FIFO#(Bit#(EtherLen)) mallocReqFifo <- mkFIFO;
   FIFO#(Bit#(EtherLen)) pktLenFifo <- mkFIFO;
   FIFO#(Maybe#(PktId)) mallocDoneFifo <- mkFIFO;
   Reg#(Bool) readStarted <- mkReg(False);
   Reg#(Bool) mallocd <- mkReg(False);

   FIFOF#(PacketInstance) eventPktReceivedFifo <- mkFIFOF;
   FIFOF#(PacketInstance) eventPktCommittedFifo <- mkFIFOF;

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

   rule packetReadStart if (!readStarted);
      let pktLen <- toGet(readLenFifo).get;
      if (verbose) $display("StoreAndForward::packetReadStart %d: ReadLen %d", cycle, pktLen);
      mallocReqFifo.enq(pktLen);
      pktLenFifo.enq(pktLen);
      readStarted <= True;
   endrule

   rule allocMemory;
      let pktLen <- toGet(pktLenFifo).get;
      let allocId <- toGet(mallocDoneFifo).get;
      let bytesPerBeatMinusOne = fromInteger(valueOf(bytesPerBeat))-1;
      // roundup to 16 byte boundary
      let burstLen = ((pktLen + bytesPerBeatMinusOne) & ~(bytesPerBeatMinusOne));
      let mask = (1<< (pktLen % fromInteger(valueOf(bytesPerBeat))))-1;
      if (isValid(allocId)) begin
         mallocd <= True;
         readReqFifo.enq(EtherReq{len: truncate(pktLen)});
         //FIXME use correct sglId
         writeReqFifo.enq(MemRequest {sglId: extend(fromMaybe(?, allocId)), offset: 0,
                                      burstLen: truncate(burstLen), tag:0
`ifdef BYTE_ENABLES
                                      , firstbe: 'hffff, lastbe: mask
`endif
                                     });
         if (verbose) $display("StoreAndForward::allocMemory %d: alloc done", cycle);
         eventPktReceivedFifo.enq(PacketInstance {id: fromMaybe(?, allocId), size: pktLen});
      end
   endrule

   rule packetReadInProgress if (readStarted && mallocd);
      let v <- toGet(readDataFifo).get;
      if (v.eop) begin
         readStarted <= False;
         mallocd <= False;
         if (verbose) $display("StoreAndForward:: %d: packet finished", cycle);
      end
      if (verbose) $display("StoreAndForward::writeData: %d: data:%h, tag:%h, last:%h", cycle, v.data, 0, v.eop);
      writeDataFifo.enq(MemData {data: v.data, tag: 0, last: v.eop});
   endrule

   rule packetReadDone;
      let v <- toGet(writeDoneFifo).get;
      let recvd <- toGet(eventPktReceivedFifo).get;
      eventPktCommittedFifo.enq(recvd);
      if (verbose) $display("StoreAndForward::packetReadDone %d: packet written to memory %h", cycle, v);
   endrule

   interface PktReadClient readClient;
      interface readData = toPut(readDataFifo);
      interface readLen = toPut(readLenFifo);
      interface readReq = toGet(readReqFifo);
   endinterface

   interface malloc = (interface MemAllocClient;
      interface Get mallocReq = toGet(mallocReqFifo);
      interface Put mallocDone = toPut(mallocDoneFifo);
   endinterface);
   interface writeClient = dmaWriteClient;
   interface PipeOut eventPktCommitted = toPipeOut(eventPktCommittedFifo);
endmodule

interface StoreAndFwdFromMemToRing;
   interface PktWriteClient writeClient;
   interface MemReadClient#(`DataBusWidth) readClient;
   interface PipeIn#(PacketInstance) eventPktSend;
   interface MemFreeClient free;
endinterface

module mkStoreAndFwdFromMemToRing(StoreAndFwdFromMemToRing)
   provisos (Div#(`DataBusWidth, 8, bytesPerBeat)
            ,Log#(bytesPerBeat, beatShift));

   let verbose = False;

   // Ring Buffer Write Client
   FIFO#(EtherData) writeDataFifo <- mkFIFO;

   // read client interface
   FIFO#(MemRequest) readReqFifo <-mkSizedFIFO(4);
   FIFO#(MemData#(`DataBusWidth)) readDataFifo <- mkSizedFIFO(32);
   MemReadClient#(`DataBusWidth) dmaReadClient = (interface MemReadClient;
   interface Get readReq = toGet(readReqFifo);
   interface Put readData = toPut(readDataFifo);
   endinterface);

   FIFOF#(PacketInstance) eventPktSendFifo <- mkSizedFIFOF(4);
   FIFO#(PktId) freeReqFifo <- mkSizedFIFO(4);

   Reg#(Bool)                 outPacket <- mkReg(False);
   Reg#(PktId)            currPacketId <- mkReg(0);
   Reg#(Bit#(EtherLen))   readBurstCount <- mkReg(0);
   Reg#(Bit#(EtherLen))   readBurstLen <- mkReg(0);

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

   rule packetReadStart (!outPacket);
      let pkt <- toGet(eventPktSendFifo).get;
      let bytesPerBeatMinusOne = fromInteger(valueOf(bytesPerBeat))-1;
      // roundup to 16 byte boundary
      let burstLen = ((pkt.size + bytesPerBeatMinusOne) & ~(bytesPerBeatMinusOne));
      if (verbose) $display("StoreAndForward:: packetReadStart: %h, burstLen = %h", pkt.size, burstLen);
      let mask = (1<< (pkt.size % fromInteger(valueOf(bytesPerBeat))))-1;
      readReqFifo.enq(MemRequest{sglId: extend(pkt.id), offset: 0,
                                 burstLen: truncate(burstLen), tag: 0
`ifdef BYTE_ENABLES
                                 , firstbe: 'hffff, lastbe: mask
`endif
                                });
      if (verbose) $display("StoreAndForward::packetReadStart %d: send a new packet with size %h %h", cycle, burstLen, pack(mask));
      outPacket <= True;
      currPacketId <= pkt.id;
      readBurstLen <= pkt.size;
      readBurstCount <= pkt.size;
   endrule

   rule packetReadInProgress (outPacket);
      let d <- toGet(readDataFifo).get;
      let _bytesPerBeat= fromInteger(valueOf(bytesPerBeat));

      let sop = (readBurstLen == readBurstCount) ? True : False;
      let eop = (readBurstCount <= _bytesPerBeat) ? True : False;

      Bit#(bytesPerBeat) mask;
      if (readBurstCount <= _bytesPerBeat)
         mask = (1<<readBurstCount)-1;
      else
         mask = (1<<_bytesPerBeat)-1;

      writeDataFifo.enq(EtherData{data: d.data, mask: mask, sop: sop, eop: eop});

      if (verbose) $display("StoreAndForward::readdata %d: %h %h %h %h %h", cycle, readBurstCount, d.data, pack(mask), sop, eop);

      if (readBurstCount > _bytesPerBeat)
         readBurstCount <= readBurstCount - _bytesPerBeat;

      if (eop) begin
         outPacket <= False;
         freeReqFifo.enq(currPacketId);
      end
   endrule

   interface PktWriteClient writeClient;
      interface writeData = toGet(writeDataFifo);
   endinterface
   interface readClient = dmaReadClient;
   interface PipeIn eventPktSend = toPipeIn(eventPktSendFifo);
   interface free = (interface MemFreeClient;
      interface Get freeReq = toGet(freeReqFifo);
   endinterface);
endmodule

interface StoreAndFwdFromRingToMac;
   interface PktReadClient readClient;
   interface Get#(PacketDataT#(64)) macTx;
   method TxThruDbgRec dbg;
   method ThruDbgRec sdbg;
endinterface

// store data from ring buffer to network
// big-endianess -> little-endianess
module mkStoreAndFwdFromRingToMac#(Clock txClock, Reset txReset)(StoreAndFwdFromRingToMac);
   let verbose = False;
   Clock defaultClock <- exposeCurrentClock();
   Reset defaultReset <- exposeCurrentReset();

   Reg#(Bit#(64)) cycle_cnt <- mkReg(0);
   Reg#(Bit#(64)) last_startofpacket <- mkReg(0);
   Reg#(Bit#(64)) last_endofpacket <- mkReg(0);
   Reg#(Bit#(64)) goodputCount <- mkReg(0);
   Reg#(Bit#(64)) idleCount <- mkReg(0);

   // stats
   Reg#(Bit#(64)) total_cycles <- mkReg(0, clocked_by txClock, reset_by txReset);
   Reg#(Bit#(64)) idle_cycles <- mkReg(0, clocked_by txClock, reset_by txReset);
   Reg#(Bit#(64)) sopCount <- mkReg(0, clocked_by txClock, reset_by txReset);
   Reg#(Bit#(64)) eopCount <- mkReg(0, clocked_by txClock, reset_by txReset);
   Reg#(Bit#(64)) data_bytes <- mkReg(0, clocked_by txClock, reset_by txReset);

   // RingBuffer Read Client
   FIFO#(EtherData) readDataFifo <- mkFIFO;
   FIFO#(Bit#(EtherLen)) readLenFifo <- mkFIFO;
   FIFO#(EtherReq) readReqFifo <- mkFIFO;

   // Mac Facing Fifo
   FIFOF#(PacketDataT#(64)) writeMacFifo <- mkFIFOF(clocked_by txClock, reset_by txReset);
   Gearbox#(2, 1, PacketDataT#(64)) fifoTxData <- mkNto1Gearbox(txClock, txReset, txClock, txReset);
   SyncFIFOIfc#(EtherData) tx_fifo <- mkSyncFIFO(5, defaultClock, defaultReset, txClock);

   rule cycle;
      cycle_cnt <= cycle_cnt + 1;
   endrule

   rule total_cycle;
      total_cycles <= total_cycles + 1;
   endrule

   rule readDataStart;
      let pktLen <- toGet(readLenFifo).get;
      if (verbose) $display(fshow(" read packt ") + fshow(pktLen));
      readReqFifo.enq(EtherReq{len: pktLen});
   endrule

   function Vector#(2, PacketDataT#(64)) split(EtherData in);
      Vector#(2, PacketDataT#(64)) v = defaultValue;
      Vector#(8, Bit#(8)) v0_data = unpack(in.data[63:0]);
      Vector#(8, Bit#(8)) v1_data = unpack(in.data[127:64]);
      v[0].sop = pack(in.sop);
`ifdef ALTERA
      v[0].data = pack(reverse(v0_data));
`else
      v[0].data = pack(v0_data);
`endif
      v[0].eop = (in.mask[15:8] == 0) ? pack(in.eop) : 0;
      v[0].mask = in.mask[7:0];
      v[1].sop = 0;
`ifdef ALTERA
      v[1].data = pack(reverse(v1_data));
`else
      v[1].data = pack(v1_data);
`endif
      v[1].eop = pack(in.eop);
      v[1].mask = in.mask[15:8];
      return v;
   endfunction

   rule cross_clocking;
      let v <- toGet(readDataFifo).get;
      tx_fifo.enq(v);

      // performance analysis
      if (v.sop) begin
         last_startofpacket <= cycle_cnt;
         idleCount <= (last_endofpacket != 0) ? (idleCount + (cycle_cnt - last_endofpacket)) : 0;
      end
      if (v.eop) begin
         last_endofpacket <= cycle_cnt;
         goodputCount <= (last_startofpacket != 0) ? (goodputCount + (cycle_cnt - last_startofpacket)) : 0;
      end
   endrule

   rule process_incoming_packet;
      let v <- toGet(tx_fifo).get;
      fifoTxData.enq(split(v));
   endrule

   rule process_outgoing_packet;
      let data = fifoTxData.first; fifoTxData.deq;
      let temp = head(data);
      let bytes = zeroExtend(pack(countOnes(temp.mask)));
      if (unpack(temp.sop)) sopCount <= sopCount + 1;
      data_bytes <= data_bytes + bytes;
      if (temp.mask != 0) begin
         if (verbose) $display("ringToMac:: tx data %h", temp.data);
         if (unpack(temp.eop)) eopCount <= eopCount + 1;
         writeMacFifo.enq(temp);
      end
      else begin
         idle_cycles <= idle_cycles + 1;
      end
   endrule

   rule count_idle_cycles (!fifoTxData.notEmpty);
      idle_cycles <= idle_cycles + 1;
   endrule

   interface PktReadClient readClient;
      interface readData = toPut(readDataFifo);
      interface readLen = toPut(readLenFifo);
      interface readReq = toGet(readReqFifo);
   endinterface
   interface Get macTx = toGet(writeMacFifo);
   method TxThruDbgRec dbg;
      return TxThruDbgRec {goodputCount: goodputCount, idleCount: idleCount};
   endmethod
   method ThruDbgRec sdbg;
      return ThruDbgRec {data_bytes: data_bytes, sops: sopCount, eops: eopCount, idle_cycles: idle_cycles, total_cycles: total_cycles};
   endmethod
endmodule

interface StoreAndFwdFromMacToRing;
   interface PktWriteClient writeClient;
   interface Put#(PacketDataT#(64)) macRx;
   method ThruDbgRec sdbg;
endinterface

// store data from network to ring buffer
// little-endianess -> big-endianess
module mkStoreAndFwdFromMacToRing#(Clock rxClock, Reset rxReset)(StoreAndFwdFromMacToRing);
   let verbose = False;
   Clock defaultClock <- exposeCurrentClock();
   Reset defaultReset <- exposeCurrentReset();

   // Ring Buffer WriteClient
   FIFO#(EtherData) writeDataFifo <- mkFIFO;

   // stats
   Reg#(Bit#(64)) total_cycles <- mkReg(0, clocked_by rxClock, reset_by rxReset);
   Reg#(Bit#(64)) idle_cycles <- mkReg(0, clocked_by rxClock, reset_by rxReset);
   Reg#(Bit#(64)) sopCount <- mkReg(0, clocked_by rxClock, reset_by rxReset);
   Reg#(Bit#(64)) eopCount <- mkReg(0, clocked_by rxClock, reset_by rxReset);
   Reg#(Bit#(64)) data_bytes <- mkReg(0, clocked_by rxClock, reset_by rxReset);

   // Mac facing fifos
   Reg#(Bool) inProgress <- mkReg(False, clocked_by rxClock, reset_by rxReset);
   Reg#(Bool) oddBeat    <- mkReg(True, clocked_by rxClock, reset_by rxReset);
   Reg#(PacketDataT#(64)) v_prev <- mkReg(defaultValue, clocked_by rxClock, reset_by rxReset);

   FIFO#(PacketDataT#(64)) readMacFifo <- mkFIFO(clocked_by rxClock, reset_by rxReset);
   SyncFIFOIfc#(EtherData) rx_fifo <- mkSyncFIFO(5, rxClock, rxReset, defaultClock);

   rule total_cycle;
      total_cycles <= total_cycles + 1;
   endrule

   function EtherData combine(Vector#(2, PacketDataT#(64)) v);
      EtherData data = defaultValue;
      Vector#(8, Bit#(8)) v0_data = unpack(v[0].data);
      Vector#(8, Bit#(8)) v1_data = unpack(v[1].data);
`ifdef ALTERA
      data.data = {pack(reverse(v1_data)), pack(reverse(v0_data))};
`else
      data.data = {pack(v1_data), pack(v0_data)};
`endif
      data.mask = {v[1].mask, v[0].mask};
      data.sop = unpack(v[0].sop);
      data.eop = unpack(v[0].eop) || unpack(v[1].eop);
      return data;
   endfunction

   rule startOfPacket if (!inProgress);
      let v = readMacFifo.first;
      inProgress <= unpack(v.sop);
      if (v.sop == 0)
         readMacFifo.deq;
      else
         sopCount <= sopCount + 1;
      if (verbose) $display("macToRing:: start");
   endrule

   rule readPacketOdd if (inProgress && oddBeat);
      let v <- toGet(readMacFifo).get;
      let bytes = zeroExtend(pack(countOnes(v.mask)));
      data_bytes <= data_bytes + bytes;
      if (verbose) $display("macToRing:: read odd beat %h", v.data);
      if (unpack(v.eop)) begin
         PacketDataT#(64) vo = defaultValue;
         rx_fifo.enq(combine(vec(v, vo)));
         if (verbose) $display("macToRing:: odd eop %h %h", v.data, v.mask);
         inProgress <= False;
         eopCount <= eopCount +1;
      end
      else begin
         oddBeat <= !oddBeat;
      end
      v_prev <= v;
   endrule

   rule readPacketEven if (inProgress && !oddBeat);
      let v <- toGet(readMacFifo).get;
      let bytes = zeroExtend(pack(countOnes(v.mask)));
      data_bytes <= data_bytes + bytes;
      rx_fifo.enq(combine(vec(v_prev, v)));
      if (verbose) $display("macToRing:: read even beat %h", v.data);
      if (unpack(v.eop)) begin
         inProgress <= False;
         if (verbose) $display("macToRing:: even eop %h %h %h %h", v.data, v.mask, v_prev.data, v_prev.mask);
         eopCount <= eopCount +1;
      end
      oddBeat <= !oddBeat;
   endrule

   rule write_data;
      let v <- toGet(rx_fifo).get;
      writeDataFifo.enq(v);
      if (verbose) $display("macToRing:: writeToFifo");
   endrule

   rule count_idle_cycles (!inProgress);
      idle_cycles <= idle_cycles + 1;
   endrule

   interface PktWriteClient writeClient;
      interface writeData = toGet(writeDataFifo);
   endinterface
   interface Put macRx = toPut(readMacFifo);
   method ThruDbgRec sdbg;
      return ThruDbgRec {data_bytes: data_bytes, sops: sopCount, eops: eopCount, idle_cycles: idle_cycles, total_cycles: total_cycles};
   endmethod
endmodule

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

// NOTE:
// Implement a store-and-forward mechanism between ring-buffer and
// main packet memory. Packets are buffered completely in ring buffer
// before it is sent to main memory and vice versa.

import BuildVector::*;
import Connectable::*;
import Clocks::*;
import Cntrs::*;
import ClientServer::*;
import DefaultValue::*;
import DbgTypes::*;
import Ethernet::*;
import EthMac::*;
import FIFO::*;
import FIFOF::*;
import GetPut::*;
import Gearbox::*;
import MemTypes::*;
import MemServer::*;
import MemServerInternal::*;
import MemMgmt::*;
import PacketBuffer::*;
import SharedBuff::*;
import SharedBuffMMU::*;
import SpecialFIFOs::*;
import Vector::*;
import Pipe::*;
import DbgTypes::*;

interface StoreAndFwdFromRingToMem;
   interface PktReadClient readClient;
   interface MemAllocClient malloc;
   interface MemWriteClient#(`DataBusWidth) writeClient;
   interface PipeOut#(PacketInstance) eventPktCommitted;
endinterface

module mkStoreAndFwdFromRingToMem(StoreAndFwdFromRingToMem)
   provisos (Div#(`DataBusWidth, 8, bytesPerBeat)
            ,Log#(bytesPerBeat, beatShift));

   let verbose = False;

   // RingBuffer Read Client
   FIFO#(EtherData) readDataFifo <- mkFIFO;
   FIFO#(Bit#(EtherLen)) readLenFifo <- mkFIFO;
   FIFO#(EtherReq) readReqFifo <- mkFIFO;

   // Memory Client
   FIFO#(MemRequest) writeReqFifo <- mkSizedFIFO(4);
   FIFO#(MemData#(`DataBusWidth)) writeDataFifo <- mkSizedFIFO(16);
   FIFO#(Bit#(MemTagSize)) writeDoneFifo <- mkSizedFIFO(4);
   MemWriteClient#(`DataBusWidth) dmaWriteClient = (interface MemWriteClient;
   interface Get writeReq = toGet(writeReqFifo);
   interface Get writeData = toGet(writeDataFifo);
   interface Put writeDone = toPut(writeDoneFifo);
   endinterface);

   FIFO#(Bit#(EtherLen)) mallocReqFifo <- mkFIFO;
   FIFO#(Bit#(EtherLen)) pktLenFifo <- mkFIFO;
   FIFO#(Maybe#(PktId)) mallocDoneFifo <- mkFIFO;
   Reg#(Bool) readStarted <- mkReg(False);
   Reg#(Bool) mallocd <- mkReg(False);

   FIFOF#(PacketInstance) eventPktReceivedFifo <- mkFIFOF;
   FIFOF#(PacketInstance) eventPktCommittedFifo <- mkFIFOF;

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

   rule packetReadStart if (!readStarted);
      let pktLen <- toGet(readLenFifo).get;
      if (verbose) $display("StoreAndForward::packetReadStart %d: ReadLen %d", cycle, pktLen);
      mallocReqFifo.enq(pktLen);
      pktLenFifo.enq(pktLen);
      readStarted <= True;
   endrule

   rule allocMemory;
      let pktLen <- toGet(pktLenFifo).get;
      let allocId <- toGet(mallocDoneFifo).get;
      let bytesPerBeatMinusOne = fromInteger(valueOf(bytesPerBeat))-1;
      // roundup to 16 byte boundary
      let burstLen = ((pktLen + bytesPerBeatMinusOne) & ~(bytesPerBeatMinusOne));
      let mask = (1<< (pktLen % fromInteger(valueOf(bytesPerBeat))))-1;
      if (isValid(allocId)) begin
         mallocd <= True;
         readReqFifo.enq(EtherReq{len: truncate(pktLen)});
         //FIXME use correct sglId
         writeReqFifo.enq(MemRequest {sglId: extend(fromMaybe(?, allocId)), offset: 0,
                                      burstLen: truncate(burstLen), tag:0
`ifdef BYTE_ENABLES
                                      , firstbe: 'hffff, lastbe: mask
`endif
                                     });
         if (verbose) $display("StoreAndForward::allocMemory %d: alloc done", cycle);
         eventPktReceivedFifo.enq(PacketInstance {id: fromMaybe(?, allocId), size: pktLen});
      end
   endrule

   rule packetReadInProgress if (readStarted && mallocd);
      let v <- toGet(readDataFifo).get;
      if (v.eop) begin
         readStarted <= False;
         mallocd <= False;
         if (verbose) $display("StoreAndForward:: %d: packet finished", cycle);
      end
      if (verbose) $display("StoreAndForward::writeData: %d: data:%h, tag:%h, last:%h", cycle, v.data, 0, v.eop);
      writeDataFifo.enq(MemData {data: v.data, tag: 0, last: v.eop});
   endrule

   rule packetReadDone;
      let v <- toGet(writeDoneFifo).get;
      let recvd <- toGet(eventPktReceivedFifo).get;
      eventPktCommittedFifo.enq(recvd);
      if (verbose) $display("StoreAndForward::packetReadDone %d: packet written to memory %h", cycle, v);
   endrule

   interface PktReadClient readClient;
      interface readData = toPut(readDataFifo);
      interface readLen = toPut(readLenFifo);
      interface readReq = toGet(readReqFifo);
   endinterface

   interface malloc = (interface MemAllocClient;
      interface Get mallocReq = toGet(mallocReqFifo);
      interface Put mallocDone = toPut(mallocDoneFifo);
   endinterface);
   interface writeClient = dmaWriteClient;
   interface PipeOut eventPktCommitted = toPipeOut(eventPktCommittedFifo);
endmodule

interface StoreAndFwdFromMemToRing;
   interface PktWriteClient writeClient;
   interface MemReadClient#(`DataBusWidth) readClient;
   interface PipeIn#(PacketInstance) eventPktSend;
   interface MemFreeClient free;
endinterface

module mkStoreAndFwdFromMemToRing(StoreAndFwdFromMemToRing)
   provisos (Div#(`DataBusWidth, 8, bytesPerBeat)
            ,Log#(bytesPerBeat, beatShift));

   let verbose = False;

   // Ring Buffer Write Client
   FIFO#(EtherData) writeDataFifo <- mkFIFO;

   // read client interface
   FIFO#(MemRequest) readReqFifo <-mkSizedFIFO(4);
   FIFO#(MemData#(`DataBusWidth)) readDataFifo <- mkSizedFIFO(32);
   MemReadClient#(`DataBusWidth) dmaReadClient = (interface MemReadClient;
   interface Get readReq = toGet(readReqFifo);
   interface Put readData = toPut(readDataFifo);
   endinterface);

   FIFOF#(PacketInstance) eventPktSendFifo <- mkSizedFIFOF(4);
   FIFO#(PktId) freeReqFifo <- mkSizedFIFO(4);

   Reg#(Bool)                 outPacket <- mkReg(False);
   Reg#(PktId)            currPacketId <- mkReg(0);
   Reg#(Bit#(EtherLen))   readBurstCount <- mkReg(0);
   Reg#(Bit#(EtherLen))   readBurstLen <- mkReg(0);

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

   rule packetReadStart (!outPacket);
      let pkt <- toGet(eventPktSendFifo).get;
      let bytesPerBeatMinusOne = fromInteger(valueOf(bytesPerBeat))-1;
      // roundup to 16 byte boundary
      let burstLen = ((pkt.size + bytesPerBeatMinusOne) & ~(bytesPerBeatMinusOne));
      if (verbose) $display("StoreAndForward:: packetReadStart: %h, burstLen = %h", pkt.size, burstLen);
      let mask = (1<< (pkt.size % fromInteger(valueOf(bytesPerBeat))))-1;
      readReqFifo.enq(MemRequest{sglId: extend(pkt.id), offset: 0,
                                 burstLen: truncate(burstLen), tag: 0
`ifdef BYTE_ENABLES
                                 , firstbe: 'hffff, lastbe: mask
`endif
                                });
      if (verbose) $display("StoreAndForward::packetReadStart %d: send a new packet with size %h %h", cycle, burstLen, pack(mask));
      outPacket <= True;
      currPacketId <= pkt.id;
      readBurstLen <= pkt.size;
      readBurstCount <= pkt.size;
   endrule

   rule packetReadInProgress (outPacket);
      let d <- toGet(readDataFifo).get;
      let _bytesPerBeat= fromInteger(valueOf(bytesPerBeat));

      let sop = (readBurstLen == readBurstCount) ? True : False;
      let eop = (readBurstCount <= _bytesPerBeat) ? True : False;

      Bit#(bytesPerBeat) mask;
      if (readBurstCount <= _bytesPerBeat)
         mask = (1<<readBurstCount)-1;
      else
         mask = (1<<_bytesPerBeat)-1;

      writeDataFifo.enq(EtherData{data: d.data, mask: mask, sop: sop, eop: eop});

      if (verbose) $display("StoreAndForward::readdata %d: %h %h %h %h %h", cycle, readBurstCount, d.data, pack(mask), sop, eop);

      if (readBurstCount > _bytesPerBeat)
         readBurstCount <= readBurstCount - _bytesPerBeat;

      if (eop) begin
         outPacket <= False;
         freeReqFifo.enq(currPacketId);
      end
   endrule

   interface PktWriteClient writeClient;
      interface writeData = toGet(writeDataFifo);
   endinterface
   interface readClient = dmaReadClient;
   interface PipeIn eventPktSend = toPipeIn(eventPktSendFifo);
   interface free = (interface MemFreeClient;
      interface Get freeReq = toGet(freeReqFifo);
   endinterface);
endmodule

interface StoreAndFwdFromRingToMac;
   interface PktReadClient readClient;
   interface Get#(PacketDataT#(64)) macTx;
   method TxThruDbgRec dbg;
   method ThruDbgRec sdbg;
endinterface

// store data from ring buffer to network
// big-endianess -> little-endianess
module mkStoreAndFwdFromRingToMac#(Clock txClock, Reset txReset)(StoreAndFwdFromRingToMac);
   let verbose = False;
   Clock defaultClock <- exposeCurrentClock();
   Reset defaultReset <- exposeCurrentReset();

   Reg#(Bit#(64)) cycle_cnt <- mkReg(0);
   Reg#(Bit#(64)) last_startofpacket <- mkReg(0);
   Reg#(Bit#(64)) last_endofpacket <- mkReg(0);
   Reg#(Bit#(64)) goodputCount <- mkReg(0);
   Reg#(Bit#(64)) idleCount <- mkReg(0);

   // stats
   Reg#(Bit#(64)) total_cycles <- mkReg(0, clocked_by txClock, reset_by txReset);
   Reg#(Bit#(64)) idle_cycles <- mkReg(0, clocked_by txClock, reset_by txReset);
   Reg#(Bit#(64)) sopCount <- mkReg(0, clocked_by txClock, reset_by txReset);
   Reg#(Bit#(64)) eopCount <- mkReg(0, clocked_by txClock, reset_by txReset);
   Reg#(Bit#(64)) data_bytes <- mkReg(0, clocked_by txClock, reset_by txReset);

   // RingBuffer Read Client
   FIFO#(EtherData) readDataFifo <- mkFIFO;
   FIFO#(Bit#(EtherLen)) readLenFifo <- mkFIFO;
   FIFO#(EtherReq) readReqFifo <- mkFIFO;

   // Mac Facing Fifo
   FIFOF#(PacketDataT#(64)) writeMacFifo <- mkFIFOF(clocked_by txClock, reset_by txReset);
   Gearbox#(2, 1, PacketDataT#(64)) fifoTxData <- mkNto1Gearbox(txClock, txReset, txClock, txReset);
   SyncFIFOIfc#(EtherData) tx_fifo <- mkSyncFIFO(5, defaultClock, defaultReset, txClock);

   rule cycle;
      cycle_cnt <= cycle_cnt + 1;
   endrule

   rule total_cycle;
      total_cycles <= total_cycles + 1;
   endrule

   rule readDataStart;
      let pktLen <- toGet(readLenFifo).get;
      if (verbose) $display(fshow(" read packt ") + fshow(pktLen));
      readReqFifo.enq(EtherReq{len: pktLen});
   endrule

   function Vector#(2, PacketDataT#(64)) split(EtherData in);
      Vector#(2, PacketDataT#(64)) v = defaultValue;
      Vector#(8, Bit#(8)) v0_data = unpack(in.data[63:0]);
      Vector#(8, Bit#(8)) v1_data = unpack(in.data[127:64]);
      v[0].sop = pack(in.sop);
`ifdef ALTERA
      v[0].data = pack(reverse(v0_data));
`elsif XILINX
      v[0].data = pack(v0_data);
`endif
      v[0].eop = (in.mask[15:8] == 0) ? pack(in.eop) : 0;
      v[0].mask = in.mask[7:0];
      v[1].sop = 0;
`ifdef ALTERA
      v[1].data = pack(reverse(v1_data));
`elsif XILINX
      v[1].data = pack(v1_data);
`endif
      v[1].eop = pack(in.eop);
      v[1].mask = in.mask[15:8];
      return v;
   endfunction

   rule cross_clocking;
      let v <- toGet(readDataFifo).get;
      tx_fifo.enq(v);

      // performance analysis
      if (v.sop) begin
         last_startofpacket <= cycle_cnt;
         idleCount <= (last_endofpacket != 0) ? (idleCount + (cycle_cnt - last_endofpacket)) : 0;
      end
      if (v.eop) begin
         last_endofpacket <= cycle_cnt;
         goodputCount <= (last_startofpacket != 0) ? (goodputCount + (cycle_cnt - last_startofpacket)) : 0;
      end
   endrule

   rule process_incoming_packet;
      let v <- toGet(tx_fifo).get;
      fifoTxData.enq(split(v));
   endrule

   rule process_outgoing_packet;
      let data = fifoTxData.first; fifoTxData.deq;
      let temp = head(data);
      let bytes = zeroExtend(pack(countOnes(temp.mask)));
      if (unpack(temp.sop)) sopCount <= sopCount + 1;
      data_bytes <= data_bytes + bytes;
      if (temp.mask != 0) begin
         if (verbose) $display("ringToMac:: tx data %h", temp.data);
         if (unpack(temp.eop)) eopCount <= eopCount + 1;
         writeMacFifo.enq(temp);
      end
      else begin
         idle_cycles <= idle_cycles + 1;
      end
   endrule

   rule count_idle_cycles (!fifoTxData.notEmpty);
      idle_cycles <= idle_cycles + 1;
   endrule

   interface PktReadClient readClient;
      interface readData = toPut(readDataFifo);
      interface readLen = toPut(readLenFifo);
      interface readReq = toGet(readReqFifo);
   endinterface
   interface Get macTx = toGet(writeMacFifo);
   method TxThruDbgRec dbg;
      return TxThruDbgRec {goodputCount: goodputCount, idleCount: idleCount};
   endmethod
   method ThruDbgRec sdbg;
      return ThruDbgRec {data_bytes: data_bytes, sops: sopCount, eops: eopCount, idle_cycles: idle_cycles, total_cycles: total_cycles};
   endmethod
endmodule

interface StoreAndFwdFromMacToRing;
   interface PktWriteClient writeClient;
   interface Put#(PacketDataT#(64)) macRx;
   method ThruDbgRec sdbg;
endinterface

// store data from network to ring buffer
// little-endianess -> big-endianess
module mkStoreAndFwdFromMacToRing#(Clock rxClock, Reset rxReset)(StoreAndFwdFromMacToRing);
   let verbose = False;
   Clock defaultClock <- exposeCurrentClock();
   Reset defaultReset <- exposeCurrentReset();

   // Ring Buffer WriteClient
   FIFO#(EtherData) writeDataFifo <- mkFIFO;

   // stats
   Reg#(Bit#(64)) total_cycles <- mkReg(0, clocked_by rxClock, reset_by rxReset);
   Reg#(Bit#(64)) idle_cycles <- mkReg(0, clocked_by rxClock, reset_by rxReset);
   Reg#(Bit#(64)) sopCount <- mkReg(0, clocked_by rxClock, reset_by rxReset);
   Reg#(Bit#(64)) eopCount <- mkReg(0, clocked_by rxClock, reset_by rxReset);
   Reg#(Bit#(64)) data_bytes <- mkReg(0, clocked_by rxClock, reset_by rxReset);

   // Mac facing fifos
   Reg#(Bool) inProgress <- mkReg(False, clocked_by rxClock, reset_by rxReset);
   Reg#(Bool) oddBeat    <- mkReg(True, clocked_by rxClock, reset_by rxReset);
   Reg#(PacketDataT#(64)) v_prev <- mkReg(defaultValue, clocked_by rxClock, reset_by rxReset);

   FIFO#(PacketDataT#(64)) readMacFifo <- mkFIFO(clocked_by rxClock, reset_by rxReset);
   SyncFIFOIfc#(EtherData) rx_fifo <- mkSyncFIFO(5, rxClock, rxReset, defaultClock);

   rule total_cycle;
      total_cycles <= total_cycles + 1;
   endrule

   function EtherData combine(Vector#(2, PacketDataT#(64)) v);
      EtherData data = defaultValue;
      Vector#(8, Bit#(8)) v0_data = unpack(v[0].data);
      Vector#(8, Bit#(8)) v1_data = unpack(v[1].data);
`ifdef ALTERA
      data.data = {pack(reverse(v1_data)), pack(reverse(v0_data))};
`elsif XILINX
      data.data = {pack(v1_data), pack(v0_data)};
`endif
      data.mask = {v[1].mask, v[0].mask};
      data.sop = unpack(v[0].sop);
      data.eop = unpack(v[0].eop) || unpack(v[1].eop);
      return data;
   endfunction

   rule startOfPacket if (!inProgress);
      let v = readMacFifo.first;
      inProgress <= unpack(v.sop);
      if (v.sop == 0)
         readMacFifo.deq;
      else
         sopCount <= sopCount + 1;
      if (verbose) $display("macToRing:: start");
   endrule

   rule readPacketOdd if (inProgress && oddBeat);
      let v <- toGet(readMacFifo).get;
      let bytes = zeroExtend(pack(countOnes(v.mask)));
      data_bytes <= data_bytes + bytes;
      if (verbose) $display("macToRing:: read odd beat %h", v.data);
      if (unpack(v.eop)) begin
         PacketDataT#(64) vo = defaultValue;
         rx_fifo.enq(combine(vec(v, vo)));
         if (verbose) $display("macToRing:: odd eop %h %h", v.data, v.mask);
         inProgress <= False;
         eopCount <= eopCount +1;
      end
      else begin
         oddBeat <= !oddBeat;
      end
      v_prev <= v;
   endrule

   rule readPacketEven if (inProgress && !oddBeat);
      let v <- toGet(readMacFifo).get;
      let bytes = zeroExtend(pack(countOnes(v.mask)));
      data_bytes <= data_bytes + bytes;
      rx_fifo.enq(combine(vec(v_prev, v)));
      if (verbose) $display("macToRing:: read even beat %h", v.data);
      if (unpack(v.eop)) begin
         inProgress <= False;
         if (verbose) $display("macToRing:: even eop %h %h %h %h", v.data, v.mask, v_prev.data, v_prev.mask);
         eopCount <= eopCount +1;
      end
      oddBeat <= !oddBeat;
   endrule

   rule write_data;
      let v <- toGet(rx_fifo).get;
      writeDataFifo.enq(v);
      if (verbose) $display("macToRing:: writeToFifo");
   endrule

   rule count_idle_cycles (!inProgress);
      idle_cycles <= idle_cycles + 1;
   endrule

   interface PktWriteClient writeClient;
      interface writeData = toGet(writeDataFifo);
   endinterface
   interface Put macRx = toPut(readMacFifo);
   method ThruDbgRec sdbg;
      return ThruDbgRec {data_bytes: data_bytes, sops: sopCount, eops: eopCount, idle_cycles: idle_cycles, total_cycles: total_cycles};
   endmethod
endmodule


removing BRAMs from the Adapter modules

removing BRAMs from the Adapter modules

// Copyright (c) 2012 MIT
// Copyright (c) 2012 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 GetPut         ::*;
import FIFOF          ::*;
import SpecialFIFOs   ::*;

function Bit#(a) rtruncate(Bit#(b) x) provisos(Add#(k,a,b));
   match {.v,.*} = split(x);
   return v;
endfunction

interface ToBit32#(type a);
   method Bit#(32) depth32(); // size of a in 32-bit words
   method Bit#(32) count32(); // number of words in the adapter
   method Action enq(a v);
   method Maybe#(Bit#(32)) first;
   method Action deq();
   method Bool notEmpty();
   method Bool notFull();
endinterface

interface FromBit32#(type a);
   method Bit#(32) depth32(); // size of a in 32-bit words
   method Bit#(32) count32(); // number of words in the adapter
   method Action enq(Bit#(32) v);
   method a first();
   method Action deq();
   method Bool notEmpty();
   method Bool notFull();
endinterface

module mkToBit32(ToBit32#(a))
   provisos(Bits#(a,asz),
            Add#(1, z, asz),
	    Add#(32,asz,asz32));

   Bit#(32) size = fromInteger(valueOf(asz));
   Bit#(32) max  = ((size + 31) >> 5) - 1;

   FIFOF#(Bit#(asz)) fifo <- mkPipelineFIFOF;
   Reg#(Bit#(32))   count <- mkReg(0);

   method Bit#(32) depth32();
       return max+1;
   endmethod
   method Bit#(32) count32();
    return extend(max - count);
   endmethod

   method Action enq(a val) if (fifo.notFull);
      fifo.enq(pack(val));
   endmethod

   method Maybe#(Bit#(32)) first();
    if (fifo.notEmpty)
       begin
           let val = fifo.first();
           Bit#(asz32) vx = zeroExtend(val >> (32 * count));
           Bit#(32) x = vx[31:0];
           return tagged Valid x;
       end
    else
       begin
           return tagged Invalid;
       end
   endmethod
   method Action deq();
     if (fifo.notEmpty)
     begin
       if (count == max)
          begin
             count <= 0;
             fifo.deq();
          end
       else
          begin
             count <= count + 1;
          end
     end
   endmethod

   method Bool notEmpty = fifo.notEmpty;
   method Bool notFull = fifo.notFull;
endmodule

module mkFromBit32(FromBit32#(a))
   provisos(Bits#(a,asz),
            Add#(1,z,asz),
	    Add#(32,asz,asz32));

   Bit#(32) size   = fromInteger(valueOf(asz));
   Bit#(5)  offset = size[4:0];
   Bit#(32) max    = ((size + 31) >> 5) - 1;

   FIFOF#(Bit#(asz))  fifo <- mkPipelineFIFOF;
   Reg#(Bit#(asz))    buff <- mkReg(0);
   Reg#(Bit#(32))    count <- mkReg(0);

   method Bit#(32) depth32();
       return max+1;
   endmethod
   method Bit#(32) count32();
    return extend(count);
   endmethod

   method Action enq(Bit#(32) x) if (fifo.notFull);
      Bit#(asz32) concatedvalue = {x,buff};
      Bit#(asz) newval = rtruncate(concatedvalue);
      if (count == max)
         begin
            count <= 0;
            buff  <= ?;
            Bit#(asz) longval = truncate({x,buff} >> ((offset==0) ? 32'd32 : zeroExtend(offset)));
            fifo.enq(longval);
         end
      else
         begin
            count <= count+1;
            buff  <= newval;
         end
   endmethod

   method a first if (fifo.notEmpty());
       return unpack(fifo.first);
   endmethod

   method Action deq if (fifo.notEmpty());
       fifo.deq;
   endmethod

   method Bool notEmpty() = fifo.notEmpty;
   method Bool notFull() = fifo.notFull;
endmodule

interface ToBit64#(type a);
   method Action enq(a v);
   method Bit#(64) first;
   method Action deq();
   method Bool notEmpty();
   method Bool notFull();
endinterface

interface FromBit64#(type a);
   method Action enq(Bit#(64) v);
   method a first();
   method Action deq();
   method Bool notEmpty();
   method Bool notFull();
endinterface

module mkToBit64(ToBit64#(a))
   provisos(Bits#(a,asz),
            Add#(1,z,asz),
	    Add#(64,asz,asz64));

   Bit#(64) size = fromInteger(valueOf(asz));
   Bit#(64) max  = (size >> 6) + ((size[5:0] == 0) ? 0 : 1)-1;

   FIFOF#(Bit#(asz))   fifo <- mkPipelineFIFOF;
   Reg#(Bit#(64))     count <- mkReg(0);

   method Action enq(a val) if (fifo.notFull);
      fifo.enq(pack(val));
   endmethod

   method Bit#(64) first();
    if (fifo.notEmpty)
       begin
           let val = fifo.first();
           Bit#(asz64) vx = zeroExtend(val >> (64 * count));
           Bit#(64) x = vx[63:0];
           return x;
       end
    else
       begin
           return 0;
       end
   endmethod
   method Action deq();
     if (fifo.notEmpty)
     begin
       if (count == max)
          begin
             count <= 0;
             fifo.deq();
          end
       else
          begin
             count <= count + 1;
          end
     end
   endmethod

   method Bool notEmpty = fifo.notEmpty;
   method Bool notFull = fifo.notFull;
endmodule

module mkFromBit64(FromBit64#(a))
   provisos(Bits#(a,asz),
            Add#(1,zzz,asz),
	    Add#(64,asz,asz64));

   Bit#(64) size   = fromInteger(valueOf(asz));
   Bit#(6)  offset = size[5:0];
   Bit#(64) max    = (size >> 6) + ((offset == 0) ? 0 : 1) -1;

   FIFOF#(Bit#(asz))  fifo <- mkPipelineFIFOF;
   Reg#(Bit#(asz))    buff <- mkReg(0);
   Reg#(Bit#(64))    count <- mkReg(0);

   method Action enq(Bit#(64) x) if (fifo.notFull);
      Bit#(asz64) concatedvalue = {x,buff};
      Bit#(asz) newval = rtruncate(concatedvalue);
      if (count == max)
         begin
            count <= 0;
            buff  <= ?;
            Bit#(asz) longval = truncate({x,buff} >> ((offset==0) ? 64'd32 : zeroExtend(offset)));
            fifo.enq(longval);
         end
      else
         begin
            count <= count+1;
            buff  <= newval;
         end
   endmethod

   method a first if (fifo.notEmpty());
       return unpack(fifo.first);
   endmethod

   method Action deq if (fifo.notEmpty());
       fifo.deq;
   endmethod

   method Bool notEmpty() = fifo.notEmpty;
   method Bool notFull() = fifo.notFull;
endmodule

// Copyright (c) 2012 MIT
// Copyright (c) 2012 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 GetPut         ::*;
import BRAMFIFO       ::*;
import FIFOF          ::*;

function Bit#(a) rtruncate(Bit#(b) x) provisos(Add#(k,a,b));
   match {.v,.*} = split(x);
   return v;
endfunction

interface ToBit32#(type a);
   method Bit#(32) depth32(); // size of a in 32-bit words
   method Bit#(32) count32(); // number of words in the adapter
   method Action enq(a v);
   method Maybe#(Bit#(32)) first;
   method Action deq();
   method Bool notEmpty();
   method Bool notFull();
endinterface

interface FromBit32#(type a);
   method Bit#(32) depth32(); // size of a in 32-bit words
   method Bit#(32) count32(); // number of words in the adapter
   method Action enq(Bit#(32) v);
   method a first();
   method Action deq();
   method Bool notEmpty();
   method Bool notFull();
endinterface

module mkToBit32(ToBit32#(a))
   provisos(Bits#(a,asz),
            Add#(1, z, asz),
	    Add#(32,asz,asz32));

   Bit#(32) size = fromInteger(valueOf(asz));
   Bit#(32) max  = ((size + 31) >> 5) - 1;

   FIFOF#(Bit#(asz)) fifo <- mkSizedBRAMFIFOF(16);
   Reg#(Bit#(32))   count <- mkReg(0);

   method Bit#(32) depth32();
       return max+1;
   endmethod
   method Bit#(32) count32();
    return extend(max - count);
   endmethod

   method Action enq(a val) if (fifo.notFull);
      fifo.enq(pack(val));
   endmethod

   method Maybe#(Bit#(32)) first();
    if (fifo.notEmpty)
       begin
           let val = fifo.first();
           Bit#(asz32) vx = zeroExtend(val >> (32 * count));
           Bit#(32) x = vx[31:0];
           return tagged Valid x;
       end
    else
       begin
           return tagged Invalid;
       end
   endmethod
   method Action deq();
     if (fifo.notEmpty)
     begin
       if (count == max)
          begin
             count <= 0;
             fifo.deq();
          end
       else
          begin
             count <= count + 1;
          end
     end
   endmethod

   method Bool notEmpty = fifo.notEmpty;
   method Bool notFull = fifo.notFull;
endmodule

module mkFromBit32(FromBit32#(a))
   provisos(Bits#(a,asz),
            Add#(1,z,asz),
	    Add#(32,asz,asz32));

   Bit#(32) size   = fromInteger(valueOf(asz));
   Bit#(5)  offset = size[4:0];
   Bit#(32) max    = ((size + 31) >> 5) - 1;

   FIFOF#(Bit#(asz))  fifo <- mkSizedBRAMFIFOF(16);
   Reg#(Bit#(asz))    buff <- mkReg(0);
   Reg#(Bit#(32))    count <- mkReg(0);

   method Bit#(32) depth32();
       return max+1;
   endmethod
   method Bit#(32) count32();
    return extend(count);
   endmethod

   method Action enq(Bit#(32) x) if (fifo.notFull);
      Bit#(asz32) concatedvalue = {x,buff};
      Bit#(asz) newval = rtruncate(concatedvalue);
      if (count == max)
         begin
            count <= 0;
            buff  <= ?;
            Bit#(asz) longval = truncate({x,buff} >> ((offset==0) ? 32'd32 : zeroExtend(offset)));
            fifo.enq(longval);
         end
      else
         begin
            count <= count+1;
            buff  <= newval;
         end
   endmethod

   method a first if (fifo.notEmpty());
       return unpack(fifo.first);
   endmethod

   method Action deq if (fifo.notEmpty());
       fifo.deq;
   endmethod

   method Bool notEmpty() = fifo.notEmpty;
   method Bool notFull() = fifo.notFull;
endmodule

interface ToBit64#(type a);
   method Action enq(a v);
   method Bit#(64) first;
   method Action deq();
   method Bool notEmpty();
   method Bool notFull();
endinterface

interface FromBit64#(type a);
   method Action enq(Bit#(64) v);
   method a first();
   method Action deq();
   method Bool notEmpty();
   method Bool notFull();
endinterface

module mkToBit64(ToBit64#(a))
   provisos(Bits#(a,asz),
            Add#(1,z,asz),
	    Add#(64,asz,asz64));

   Bit#(64) size = fromInteger(valueOf(asz));
   Bit#(64) max  = (size >> 6) + ((size[5:0] == 0) ? 0 : 1)-1;

   FIFOF#(Bit#(asz))   fifo <- mkSizedBRAMFIFOF(16);
   Reg#(Bit#(64))     count <- mkReg(0);

   method Action enq(a val) if (fifo.notFull);
      fifo.enq(pack(val));
   endmethod

   method Bit#(64) first();
    if (fifo.notEmpty)
       begin
           let val = fifo.first();
           Bit#(asz64) vx = zeroExtend(val >> (64 * count));
           Bit#(64) x = vx[63:0];
           return x;
       end
    else
       begin
           return 0;
       end
   endmethod
   method Action deq();
     if (fifo.notEmpty)
     begin
       if (count == max)
          begin
             count <= 0;
             fifo.deq();
          end
       else
          begin
             count <= count + 1;
          end
     end
   endmethod

   method Bool notEmpty = fifo.notEmpty;
   method Bool notFull = fifo.notFull;
endmodule

module mkFromBit64(FromBit64#(a))
   provisos(Bits#(a,asz),
            Add#(1,zzz,asz),
	    Add#(64,asz,asz64));

   Bit#(64) size   = fromInteger(valueOf(asz));
   Bit#(6)  offset = size[5:0];
   Bit#(64) max    = (size >> 6) + ((offset == 0) ? 0 : 1) -1;

   FIFOF#(Bit#(asz))  fifo <- mkSizedBRAMFIFOF(16);
   Reg#(Bit#(asz))    buff <- mkReg(0);
   Reg#(Bit#(64))    count <- mkReg(0);

   method Action enq(Bit#(64) x) if (fifo.notFull);
      Bit#(asz64) concatedvalue = {x,buff};
      Bit#(asz) newval = rtruncate(concatedvalue);
      if (count == max)
         begin
            count <= 0;
            buff  <= ?;
            Bit#(asz) longval = truncate({x,buff} >> ((offset==0) ? 64'd32 : zeroExtend(offset)));
            fifo.enq(longval);
         end
      else
         begin
            count <= count+1;
            buff  <= newval;
         end
   endmethod

   method a first if (fifo.notEmpty());
       return unpack(fifo.first);
   endmethod

   method Action deq if (fifo.notEmpty());
       fifo.deq;
   endmethod

   method Bool notEmpty() = fifo.notEmpty;
   method Bool notFull() = fifo.notFull;
endmodule


reduce CSR addr size to 16 bits

reduce CSR addr size to 16 bits

Change-Id: Ib86ad14b1dac73e13f716c13eeb8668baac7c738

// 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 BRAM           :: *;
import FIFOF          :: *;
import GetPut         :: *;
import PCIE           :: *;
import Clocks         :: *;
import PcieTracer     :: *;
import MemSlave       :: *;

`define msix_base 1024

// An MSIX table entry, as defined in the PCIe spec
interface MSIX_Entry;
   interface Reg#(Bit#(32)) addr_lo;
   interface Reg#(Bit#(32)) addr_hi;
   interface Reg#(Bit#(32)) msg_data;
   interface Reg#(Bool)     masked;
endinterface

interface ReadOnly_MSIX_Entry;
   interface ReadOnly#(Bit#(32)) addr_lo;
   interface ReadOnly#(Bit#(32)) addr_hi;
   interface ReadOnly#(Bit#(32)) msg_data;
   interface ReadOnly#(Bool)     masked;
endinterface

function ReadOnly_MSIX_Entry toReadOnlyMsixEntry(MSIX_Entry msix);
   return (interface ReadOnly_MSIX_Entry;
	   interface ReadOnly addr_lo = regToReadOnly(msix.addr_lo);
	   interface ReadOnly addr_hi = regToReadOnly(msix.addr_hi);
	   interface ReadOnly msg_data = regToReadOnly(msix.msg_data);
	   interface ReadOnly masked = regToReadOnly(msix.masked);
	   endinterface);
endfunction

// control and status registers accessed from PCIe
interface PcieControlAndStatusRegs;
   interface MemSlaveClient client;
   interface Vector#(16,ReadOnly_MSIX_Entry) msixEntry;
endinterface: PcieControlAndStatusRegs

// This module encapsulates all of the logic for instantiating and
// accessing the control and status registers. It defines the
// registers, the address map, and how the registers respond to reads
// and writes.
module mkPcieControlAndStatusRegs#(TlpTraceData tlpdata)(PcieControlAndStatusRegs);

   // Utility for module creating all of the storage for a single MSIX
   // table entry
   module mkMSIXEntry(MSIX_Entry);
      Reg#(Bit#(32)) _addr_lo  <- mkReg(0);
      Reg#(Bit#(32)) _addr_hi  <- mkReg(0);
      Reg#(Bit#(32)) _msg_data <- mkReg(0);
      Reg#(Bool)     _masked   <- mkReg(True);

      interface addr_lo  = _addr_lo;
      interface addr_hi  = _addr_hi;
      interface msg_data = _msg_data;
      interface masked   = _masked;
   endmodule: mkMSIXEntry

   // Registers and their default values
   Vector#(16,MSIX_Entry) msix_entry              <- replicateM(mkMSIXEntry);
   Reg#(TimestampedTlpData) pcieTraceBramResponse <- mkReg(unpack(0));
   Reg#(Bit#(TAdd#(TlpTraceAddrSize,1))) bramMuxRdAddrReg <- mkReg(0);

   // Function to return a one-word slice of the tlpTraceBramResponse
   function Bit#(32) tlpTraceBramResponseSlice(Reg#(TimestampedTlpData) data, Bit#(3) i);
       Bit#(8) i8 = zeroExtend(i);
       begin
           Bit#(192) v = extend(pack(data));
           return v[31 + (i8*32) : 0 + (i8*32)];
       end
   endfunction

   // State used to actually service read and write requests
   rule brmMuxResponse;
       let v <- tlpdata.bramServer.response.get();
       pcieTraceBramResponse <= v;
   endrule

   interface MemSlaveClient client;
   // Function to read from the CSR address space (using DW address)
   method Bit#(32) rd(UInt#(16) addr);
      let modaddr = (addr % 8192);
      let msixaddr = modaddr - `msix_base;
      if (msixaddr >= 0 && msixaddr <= 63)
         begin
         let groupaddr = (msixaddr / 4);
         //******************************** area referenced from xilinx_x7_pcie_wrapper.v
         case (msixaddr % 4)
         0: return msix_entry[groupaddr].addr_lo;
         1: return msix_entry[groupaddr].addr_hi;
         2: return msix_entry[groupaddr].msg_data;
         3: return {'0, pack(msix_entry[groupaddr].masked)}; // vector control
         default: return 32'hbad0add0;
         endcase
         end
      else
      case (modaddr)
         // board identification
         0: return 32'h65756c42; // Blue
         1: return 32'h63657073; // spec

	 768: return extend(bramMuxRdAddrReg);
	 774: return fromInteger(2**valueOf(TAdd#(TlpTraceAddrSize,1)));
	 775: return (tlpdata.tlpTracing ? 1 : 0);
	 776: return tlpTraceBramResponseSlice(pcieTraceBramResponse, 0);
	 777: return tlpTraceBramResponseSlice(pcieTraceBramResponse, 1);
	 778: return tlpTraceBramResponseSlice(pcieTraceBramResponse, 2);
	 779: return tlpTraceBramResponseSlice(pcieTraceBramResponse, 3);
	 780: return tlpTraceBramResponseSlice(pcieTraceBramResponse, 4);
	 781: return tlpTraceBramResponseSlice(pcieTraceBramResponse, 5);
	 792: return extend(tlpdata.pcieTraceBramWrAddr);
	 794: return extend(tlpdata.tlpTraceLimit);

         //******************************** start of area referenced from xilinx_x7_pcie_wrapper.v
         // 4-bit MSIx pending bit field
         992: return '0;                               // PBA structure (low)
         993: return '0;                               // PBA structure (high)
         //******************************** end of area referenced from xilinx_x7_pcie_wrapper.v
         // unused addresses
         default: return 32'hbad0add0;
      endcase
   endmethod

   // Function to write to the CSR address space (using DW address)
   method Action wr(UInt#(16) addr, Bit#(32) dword);
         let modaddr = (addr % 8192);
         let msixaddr = modaddr - `msix_base;
         if (msixaddr >= 0 && msixaddr <= 63)
            begin
            let groupaddr = (msixaddr / 4);
            //******************************** area referenced from xilinx_x7_pcie_wrapper.v
            case (msixaddr % 4)
            0: msix_entry[groupaddr].addr_lo  <= (dword & 32'hfffffffc);
            1: msix_entry[groupaddr].addr_hi  <= dword;
            2: msix_entry[groupaddr].msg_data <= dword;
            3: msix_entry[groupaddr].masked <= unpack(dword[0]);
            endcase
            end
         else
         case (modaddr)
	    775: tlpdata.tlpTracing <= (dword != 0) ? True : False;

	    768: begin
		    tlpdata.bramServer.request.put(BRAMRequest{ write: False, responseOnWrite: False, address: bramMuxRdAddrReg, datain: unpack(0)});
		    bramMuxRdAddrReg <= bramMuxRdAddrReg + 1;
		    end
	    792: tlpdata.pcieTraceBramWrAddr <= truncate(dword);
	    794: tlpdata.tlpTraceLimit <= truncate(dword);
         endcase
   endmethod
   endinterface
   interface Vector msixEntry = map(toReadOnlyMsixEntry, msix_entry);
endmodule: mkPcieControlAndStatusRegs

// 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 BRAM           :: *;
import FIFOF          :: *;
import GetPut         :: *;
import PCIE           :: *;
import Clocks         :: *;
import PcieTracer     :: *;
import MemSlave       :: *;

`define msix_base 1024

// An MSIX table entry, as defined in the PCIe spec
interface MSIX_Entry;
   interface Reg#(Bit#(32)) addr_lo;
   interface Reg#(Bit#(32)) addr_hi;
   interface Reg#(Bit#(32)) msg_data;
   interface Reg#(Bool)     masked;
endinterface

interface ReadOnly_MSIX_Entry;
   interface ReadOnly#(Bit#(32)) addr_lo;
   interface ReadOnly#(Bit#(32)) addr_hi;
   interface ReadOnly#(Bit#(32)) msg_data;
   interface ReadOnly#(Bool)     masked;
endinterface

function ReadOnly_MSIX_Entry toReadOnlyMsixEntry(MSIX_Entry msix);
   return (interface ReadOnly_MSIX_Entry;
	   interface ReadOnly addr_lo = regToReadOnly(msix.addr_lo);
	   interface ReadOnly addr_hi = regToReadOnly(msix.addr_hi);
	   interface ReadOnly msg_data = regToReadOnly(msix.msg_data);
	   interface ReadOnly masked = regToReadOnly(msix.masked);
	   endinterface);
endfunction

// control and status registers accessed from PCIe
interface PcieControlAndStatusRegs;
   interface MemSlaveClient client;
   interface Vector#(16,ReadOnly_MSIX_Entry) msixEntry;
endinterface: PcieControlAndStatusRegs

// This module encapsulates all of the logic for instantiating and
// accessing the control and status registers. It defines the
// registers, the address map, and how the registers respond to reads
// and writes.
module mkPcieControlAndStatusRegs#(TlpTraceData tlpdata)(PcieControlAndStatusRegs);

   // Utility for module creating all of the storage for a single MSIX
   // table entry
   module mkMSIXEntry(MSIX_Entry);
      Reg#(Bit#(32)) _addr_lo  <- mkReg(0);
      Reg#(Bit#(32)) _addr_hi  <- mkReg(0);
      Reg#(Bit#(32)) _msg_data <- mkReg(0);
      Reg#(Bool)     _masked   <- mkReg(True);

      interface addr_lo  = _addr_lo;
      interface addr_hi  = _addr_hi;
      interface msg_data = _msg_data;
      interface masked   = _masked;
   endmodule: mkMSIXEntry

   // Registers and their default values
   Vector#(16,MSIX_Entry) msix_entry              <- replicateM(mkMSIXEntry);
   Reg#(TimestampedTlpData) pcieTraceBramResponse <- mkReg(unpack(0));
   Reg#(Bit#(TAdd#(TlpTraceAddrSize,1))) bramMuxRdAddrReg <- mkReg(0);

   // Function to return a one-word slice of the tlpTraceBramResponse
   function Bit#(32) tlpTraceBramResponseSlice(Reg#(TimestampedTlpData) data, Bit#(3) i);
       Bit#(8) i8 = zeroExtend(i);
       begin
           Bit#(192) v = extend(pack(data));
           return v[31 + (i8*32) : 0 + (i8*32)];
       end
   endfunction

   // State used to actually service read and write requests
   rule brmMuxResponse;
       let v <- tlpdata.bramServer.response.get();
       pcieTraceBramResponse <= v;
   endrule

   interface MemSlaveClient client;
   // Function to read from the CSR address space (using DW address)
   method Bit#(32) rd(UInt#(30) addr);
      let modaddr = (addr % 8192);
      let msixaddr = modaddr - `msix_base;
      if (msixaddr >= 0 && msixaddr <= 63)
         begin
         let groupaddr = (msixaddr / 4);
         //******************************** area referenced from xilinx_x7_pcie_wrapper.v
         case (msixaddr % 4)
         0: return msix_entry[groupaddr].addr_lo;
         1: return msix_entry[groupaddr].addr_hi;
         2: return msix_entry[groupaddr].msg_data;
         3: return {'0, pack(msix_entry[groupaddr].masked)}; // vector control
         default: return 32'hbad0add0;
         endcase
         end
      else
      case (modaddr)
         // board identification
         0: return 32'h65756c42; // Blue
         1: return 32'h63657073; // spec

	 768: return extend(bramMuxRdAddrReg);
	 774: return fromInteger(2**valueOf(TAdd#(TlpTraceAddrSize,1)));
	 775: return (tlpdata.tlpTracing ? 1 : 0);
	 776: return tlpTraceBramResponseSlice(pcieTraceBramResponse, 0);
	 777: return tlpTraceBramResponseSlice(pcieTraceBramResponse, 1);
	 778: return tlpTraceBramResponseSlice(pcieTraceBramResponse, 2);
	 779: return tlpTraceBramResponseSlice(pcieTraceBramResponse, 3);
	 780: return tlpTraceBramResponseSlice(pcieTraceBramResponse, 4);
	 781: return tlpTraceBramResponseSlice(pcieTraceBramResponse, 5);
	 792: return extend(tlpdata.pcieTraceBramWrAddr);
	 794: return extend(tlpdata.tlpTraceLimit);

         //******************************** start of area referenced from xilinx_x7_pcie_wrapper.v
         // 4-bit MSIx pending bit field
         992: return '0;                               // PBA structure (low)
         993: return '0;                               // PBA structure (high)
         //******************************** end of area referenced from xilinx_x7_pcie_wrapper.v
         // unused addresses
         default: return 32'hbad0add0;
      endcase
   endmethod

   // Function to write to the CSR address space (using DW address)
   method Action wr(UInt#(30) addr, Bit#(32) dword);
         let modaddr = (addr % 8192);
         let msixaddr = modaddr - `msix_base;
         if (msixaddr >= 0 && msixaddr <= 63)
            begin
            let groupaddr = (msixaddr / 4);
            //******************************** area referenced from xilinx_x7_pcie_wrapper.v
            case (msixaddr % 4)
            0: msix_entry[groupaddr].addr_lo  <= (dword & 32'hfffffffc);
            1: msix_entry[groupaddr].addr_hi  <= dword;
            2: msix_entry[groupaddr].msg_data <= dword;
            3: msix_entry[groupaddr].masked <= unpack(dword[0]);
            endcase
            end
         else
         case (modaddr)
	    775: tlpdata.tlpTracing <= (dword != 0) ? True : False;

	    768: begin
		    tlpdata.bramServer.request.put(BRAMRequest{ write: False, responseOnWrite: False, address: bramMuxRdAddrReg, datain: unpack(0)});
		    bramMuxRdAddrReg <= bramMuxRdAddrReg + 1;
		    end
	    792: tlpdata.pcieTraceBramWrAddr <= truncate(dword);
	    794: tlpdata.tlpTraceLimit <= truncate(dword);
         endcase
   endmethod
   endinterface
   interface Vector msixEntry = map(toReadOnlyMsixEntry, msix_entry);
endmodule: mkPcieControlAndStatusRegs