one more missing proviso in mkBsimHost

one more missing proviso in mkBsimHost

// 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 Clocks            :: *;
import Vector            :: *;
import FIFOF             :: *;
import FIFO              :: *;
import SpecialFIFOs      :: *;
import GetPut            :: *;
import Connectable       :: *;
import StmtFSM           :: *;
import Portal            :: *;
import Top               :: *;
import MemTypes          :: *;
import HostInterface     :: *;
import CtrlMux           :: *;
import ClientServer      :: *;
import MemToPcie    :: *;
import PcieToMem   :: *;
import PCIE              :: *;
import SimDma            :: *;
import `PinTypeInclude::*;
import Platform          :: *;

// implemented in BsimCtrl.cpp
import "BDPI" function Action                 initPortal();
import "BDPI" function Bool                   checkForRequest(Bit#(32) v);
import "BDPI" function ActionValue#(Bit#(64)) getRequest32(Bit#(32) v);
import "BDPI" function Action                 readResponse32(Bit#(32) d, Bit#(32) tag);
import "BDPI" function Action                 interruptLevel(Bit#(1) d);

module mkBsimCtrlReadWrite(PhysMemMaster#(clientAddrWidth, clientBusWidth))
   provisos(Add#(a__, 32, clientAddrWidth), Add#(b__, 32, clientBusWidth));
   FIFO#(Bit#(clientBusWidth)) wf <- mkPipelineFIFO;
   Reg#(Bit#(32)) cycles      <- mkReg(0);
   rule count;
      cycles <= cycles + 1;
   endrule

   let verbose = False;
   let init_fsm <- mkOnce(initPortal());

   rule init_rule;
      init_fsm.start;
   endrule
   interface PhysMemReadClient read_client;
     interface Get readReq;
	 method ActionValue#(PhysMemRequest#(clientAddrWidth,clientBusWidth)) get() if (checkForRequest(0));
	 //$write("req_ar: ");
	 let ra <- getRequest32(0);
	 //$display("ra=%h", ra);
	 let burstLen = fromInteger(valueOf(clientBusWidth) / 8);
	 if (verbose) $display("\n%d BsimHost.readReq addr=%h burstLen=%d", cycles, ra, burstLen);
	 return PhysMemRequest { addr: extend(ra[31:0]), burstLen: burstLen, tag: truncate(ra[63:32])
`ifdef BYTE_ENABLES
				, firstbe: maxBound, lastbe: maxBound
`endif
				};
	 endmethod
     endinterface
     interface Put readData;
	 method Action put(MemData#(clientBusWidth) rd);
	 //$display("resp_read: rd=%h", rd);
	 if (verbose) $display("%d BsimHost.readData %h", cycles, rd.data);
	 readResponse32(truncate(rd.data), extend(rd.tag));
	 endmethod
     endinterface
   endinterface
   interface PhysMemWriteClient write_client;
     interface Get writeReq;
	 method ActionValue#(PhysMemRequest#(clientAddrWidth,clientBusWidth)) get() if (checkForRequest(1));
	 let wd <- getRequest32(1);
	 wf.enq(extend(wd[63:32]));
	 let burstLen = fromInteger(valueOf(clientBusWidth) / 8);
	 if (verbose) $display("\n%d BsimHost.writeReq addr/data=%h burstLen=%d", cycles, wd, burstLen);
	 return PhysMemRequest { addr: extend(wd[31:0]), burstLen: burstLen, tag: 0
`ifdef BYTE_ENABLES
				, firstbe: maxBound, lastbe: maxBound
`endif
				};
	 endmethod
     endinterface
     interface Get writeData;
	 method ActionValue#(MemData#(clientBusWidth)) get;
	 wf.deq;
	 if (verbose) $display("%d BsimHost.writeData %h", cycles, wf.first);
	 return MemData { data: wf.first, tag: 0, last: True };
	 endmethod
     endinterface
     interface Put writeDone;
	 method Action put(Bit#(MemTagSize) resp);
	 if (verbose) $display("%d BsimHost.writeDone %d", cycles, resp);
	 endmethod
     endinterface
   endinterface
endmodule

module  mkBsimHost#(Clock derived_clock, Reset derived_reset)(BsimHost#(clientAddrWidth, clientBusWidth, clientIdWidth,
			      serverAddrWidth, serverBusWidth, serverIdWidth,
			      nSlaves))
   provisos (Add#(a__, 32, clientAddrWidth), Add#(b__, 32, clientBusWidth),
	     Mul#(TDiv#(serverBusWidth, 32), 32, serverBusWidth),
             Mul#(TDiv#(serverBusWidth, 8), 8, serverBusWidth),
	     Mul#(TDiv#(serverBusWidth, 32), 4, TDiv#(serverBusWidth, 8)),
	     Add#(c__, ByteEnableSize,TDiv#(serverBusWidth, 8)));

   Vector#(nSlaves,PhysMemSlave#(serverAddrWidth,  serverBusWidth)) servers <- replicateM(mkSimDmaDmaMaster);
   PhysMemMaster#(clientAddrWidth, clientBusWidth) crw <- mkBsimCtrlReadWrite();

   interface mem_servers = servers;
   interface PhysMemMaster mem_client = crw;
   interface derivedClock = derived_clock;
   interface derivedReset = derived_reset;
endmodule

module  mkBsimTop(Empty);
   let divider <- mkClockDivider(2);
   Clock derivedClock = divider.fastClock;
   Clock singleClock = divider.slowClock;
   Reset derivedReset <- exposeCurrentReset;
   let single_reset <- mkReset(2, True, singleClock);
   Reset singleReset = single_reset.new_rst;
   BsimHost#(32,32,12,PhysAddrWidth,DataBusWidth,6,NumberOfMasters) host <- mkBsimHost(clocked_by singleClock, reset_by singleReset, derivedClock, derivedReset);
   Vector#(NumberOfUserTiles,ConnectalTop) ts <- replicateM(mkConnectalTop(
`ifdef IMPORT_HOSTIF
       host,
`else
`ifdef IMPORT_HOST_CLOCKS
       host.derivedClock, host.derivedReset,
`endif
`endif
       clocked_by singleClock, reset_by singleReset));
   Platform top <- mkPlatform(ts, clocked_by singleClock, reset_by singleReset);
   mapM(uncurry(mkConnection),zip(top.masters, host.mem_servers), clocked_by singleClock, reset_by singleReset);
`ifndef BSIM_EXERCISE_MEM_MASTER_SLAVE
   mkConnection(host.mem_client, top.slave, clocked_by singleClock, reset_by singleReset);
`else
   PciId masterPciId = unpack(22);
   PciId slavePciId = unpack(23);
   PcieToMem masterEngine <- mkPcieToMem(masterPciId, clocked_by singleClock, reset_by singleReset);
   MemToPcie#(32) slaveEngine <- mkMemToPcie(slavePciId, clocked_by singleClock, reset_by singleReset);
   mkConnection(host.mem_client, slaveEngine.slave, clocked_by singleClock, reset_by singleReset);
   mkConnection(slaveEngine.tlp.request, masterEngine.tlp.response, clocked_by singleClock, reset_by singleReset);
   mkConnection(slaveEngine.tlp.response, masterEngine.tlp.request, clocked_by singleClock, reset_by singleReset);
   mkConnection(masterEngine.master, top.slave, clocked_by singleClock, reset_by singleReset);
`endif

   let intr_mux <- mkInterruptMux(top.interrupt);
   rule int_rule;
      interruptLevel(truncate(pack(intr_mux)));
   endrule

`ifdef BSIMRESPONDER
   `BSIMRESPONDER (top.pins);
`endif
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 Clocks            :: *;
import Vector            :: *;
import FIFOF             :: *;
import FIFO              :: *;
import SpecialFIFOs      :: *;
import GetPut            :: *;
import Connectable       :: *;
import StmtFSM           :: *;
import Portal            :: *;
import Top               :: *;
import MemTypes          :: *;
import HostInterface     :: *;
import CtrlMux           :: *;
import ClientServer      :: *;
import MemToPcie    :: *;
import PcieToMem   :: *;
import PCIE              :: *;
import SimDma            :: *;
import `PinTypeInclude::*;
import Platform          :: *;

// implemented in BsimCtrl.cpp
import "BDPI" function Action                 initPortal();
import "BDPI" function Bool                   checkForRequest(Bit#(32) v);
import "BDPI" function ActionValue#(Bit#(64)) getRequest32(Bit#(32) v);
import "BDPI" function Action                 readResponse32(Bit#(32) d, Bit#(32) tag);
import "BDPI" function Action                 interruptLevel(Bit#(1) d);

module mkBsimCtrlReadWrite(PhysMemMaster#(clientAddrWidth, clientBusWidth))
   provisos(Add#(a__, 32, clientAddrWidth), Add#(b__, 32, clientBusWidth));
   FIFO#(Bit#(clientBusWidth)) wf <- mkPipelineFIFO;
   Reg#(Bit#(32)) cycles      <- mkReg(0);
   rule count;
      cycles <= cycles + 1;
   endrule

   let verbose = False;
   let init_fsm <- mkOnce(initPortal());

   rule init_rule;
      init_fsm.start;
   endrule
   interface PhysMemReadClient read_client;
     interface Get readReq;
	 method ActionValue#(PhysMemRequest#(clientAddrWidth,clientBusWidth)) get() if (checkForRequest(0));
	 //$write("req_ar: ");
	 let ra <- getRequest32(0);
	 //$display("ra=%h", ra);
	 let burstLen = fromInteger(valueOf(clientBusWidth) / 8);
	 if (verbose) $display("\n%d BsimHost.readReq addr=%h burstLen=%d", cycles, ra, burstLen);
	 return PhysMemRequest { addr: extend(ra[31:0]), burstLen: burstLen, tag: truncate(ra[63:32])
`ifdef BYTE_ENABLES
				, firstbe: maxBound, lastbe: maxBound
`endif
				};
	 endmethod
     endinterface
     interface Put readData;
	 method Action put(MemData#(clientBusWidth) rd);
	 //$display("resp_read: rd=%h", rd);
	 if (verbose) $display("%d BsimHost.readData %h", cycles, rd.data);
	 readResponse32(truncate(rd.data), extend(rd.tag));
	 endmethod
     endinterface
   endinterface
   interface PhysMemWriteClient write_client;
     interface Get writeReq;
	 method ActionValue#(PhysMemRequest#(clientAddrWidth,clientBusWidth)) get() if (checkForRequest(1));
	 let wd <- getRequest32(1);
	 wf.enq(extend(wd[63:32]));
	 let burstLen = fromInteger(valueOf(clientBusWidth) / 8);
	 if (verbose) $display("\n%d BsimHost.writeReq addr/data=%h burstLen=%d", cycles, wd, burstLen);
	 return PhysMemRequest { addr: extend(wd[31:0]), burstLen: burstLen, tag: 0
`ifdef BYTE_ENABLES
				, firstbe: maxBound, lastbe: maxBound
`endif
				};
	 endmethod
     endinterface
     interface Get writeData;
	 method ActionValue#(MemData#(clientBusWidth)) get;
	 wf.deq;
	 if (verbose) $display("%d BsimHost.writeData %h", cycles, wf.first);
	 return MemData { data: wf.first, tag: 0, last: True };
	 endmethod
     endinterface
     interface Put writeDone;
	 method Action put(Bit#(MemTagSize) resp);
	 if (verbose) $display("%d BsimHost.writeDone %d", cycles, resp);
	 endmethod
     endinterface
   endinterface
endmodule

module  mkBsimHost#(Clock derived_clock, Reset derived_reset)(BsimHost#(clientAddrWidth, clientBusWidth, clientIdWidth,
			      serverAddrWidth, serverBusWidth, serverIdWidth,
			      nSlaves))
   provisos (Add#(a__, 32, clientAddrWidth), Add#(b__, 32, clientBusWidth),
	     Mul#(TDiv#(serverBusWidth, 32), 32, serverBusWidth),
             Mul#(TDiv#(serverBusWidth, 8), 8, serverBusWidth),
	     Add#(c__, ByteEnableSize,TDiv#(serverBusWidth, 8)));

   Vector#(nSlaves,PhysMemSlave#(serverAddrWidth,  serverBusWidth)) servers <- replicateM(mkSimDmaDmaMaster);
   PhysMemMaster#(clientAddrWidth, clientBusWidth) crw <- mkBsimCtrlReadWrite();

   interface mem_servers = servers;
   interface PhysMemMaster mem_client = crw;
   interface derivedClock = derived_clock;
   interface derivedReset = derived_reset;
endmodule

module  mkBsimTop(Empty);
   let divider <- mkClockDivider(2);
   Clock derivedClock = divider.fastClock;
   Clock singleClock = divider.slowClock;
   Reset derivedReset <- exposeCurrentReset;
   let single_reset <- mkReset(2, True, singleClock);
   Reset singleReset = single_reset.new_rst;
   BsimHost#(32,32,12,PhysAddrWidth,DataBusWidth,6,NumberOfMasters) host <- mkBsimHost(clocked_by singleClock, reset_by singleReset, derivedClock, derivedReset);
   Vector#(NumberOfUserTiles,ConnectalTop) ts <- replicateM(mkConnectalTop(
`ifdef IMPORT_HOSTIF
       host,
`else
`ifdef IMPORT_HOST_CLOCKS
       host.derivedClock, host.derivedReset,
`endif
`endif
       clocked_by singleClock, reset_by singleReset));
   Platform top <- mkPlatform(ts, clocked_by singleClock, reset_by singleReset);
   mapM(uncurry(mkConnection),zip(top.masters, host.mem_servers), clocked_by singleClock, reset_by singleReset);
`ifndef BSIM_EXERCISE_MEM_MASTER_SLAVE
   mkConnection(host.mem_client, top.slave, clocked_by singleClock, reset_by singleReset);
`else
   PciId masterPciId = unpack(22);
   PciId slavePciId = unpack(23);
   PcieToMem masterEngine <- mkPcieToMem(masterPciId, clocked_by singleClock, reset_by singleReset);
   MemToPcie#(32) slaveEngine <- mkMemToPcie(slavePciId, clocked_by singleClock, reset_by singleReset);
   mkConnection(host.mem_client, slaveEngine.slave, clocked_by singleClock, reset_by singleReset);
   mkConnection(slaveEngine.tlp.request, masterEngine.tlp.response, clocked_by singleClock, reset_by singleReset);
   mkConnection(slaveEngine.tlp.response, masterEngine.tlp.request, clocked_by singleClock, reset_by singleReset);
   mkConnection(masterEngine.master, top.slave, clocked_by singleClock, reset_by singleReset);
`endif

   let intr_mux <- mkInterruptMux(top.interrupt);
   rule int_rule;
      interruptLevel(truncate(pack(intr_mux)));
   endrule

`ifdef BSIMRESPONDER
   `BSIMRESPONDER (top.pins);
`endif
endmodule


pipeline trace BRAM read request

pipeline trace BRAM read request

Change-Id: I9efe3558b9ea27caa370a5d23fe3dce36bb0db04

// 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 Connectable    :: *;
import PCIE           :: *;
import Clocks         :: *;
import PcieTracer     :: *;
import MemTypes       :: *;
import AddressGenerator::*;

`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 MemSlave#(32,32) memSlave;
   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

   AddressGenerator#(16)              csrRag <- mkAddressGenerator;
   AddressGenerator#(16)              csrWag <- mkAddressGenerator;
   FIFOF#(MemData#(32))     readResponseFifo <- mkFIFOF();
   FIFOF#(MemData#(32))        writeDataFifo <- mkFIFOF();
   FIFOF#(Bit#(ObjectTagSize)) writeDoneFifo <- mkFIFOF();

   rule readDataRule;
      let beat <- csrRag.addrBeat.get();
      let addr = beat.addr;
      Bit#(32) data = 0;
      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: data = msix_entry[groupaddr].addr_lo;
               1: data = msix_entry[groupaddr].addr_hi;
               2: data = msix_entry[groupaddr].msg_data;
               3: data = {'0, pack(msix_entry[groupaddr].masked)}; // vector control
               default: data = 32'hbad0add0;
            endcase
         end
      else
	 case (modaddr)
            // board identification
            0: data = 32'h65756c42; // Blue
            1: data = 32'h63657073; // spec

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

            //******************************** start of area referenced from xilinx_x7_pcie_wrapper.v
            // 4-bit MSIx pending bit field
            992: data = '0;                               // PBA structure (low)
            993: data = '0;                               // PBA structure (high)
            //******************************** end of area referenced from xilinx_x7_pcie_wrapper.v
            // unused addresses
            default: data = 32'hbad0add0;
	 endcase
      readResponseFifo.enq(MemData { data: data, tag: beat.tag, last: beat.last });
   endrule

   FIFOF#(BRAMRequest#(Bit#(TAdd#(TlpTraceAddrSize,1)),TimestampedTlpData)) bramRequestFifo <- mkFIFOF();
   mkConnection(toGet(bramRequestFifo), tlpdata.bramServer.request);

   rule writeDataRule;
      let beat <- csrWag.addrBeat.get();
      let addr = beat.addr;
      let memData <- toGet(writeDataFifo).get();
      let dword = memData.data;

      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
		    bramRequestFifo.enq(BRAMRequest{ write: False, responseOnWrite: False, address: bramMuxRdAddrReg, datain: ?});
		    bramMuxRdAddrReg <= bramMuxRdAddrReg + 1;
		 end
	    792: tlpdata.pcieTraceBramWrAddr <= truncate(dword);
	    794: tlpdata.tlpTraceLimit <= truncate(dword);
         endcase
      if (beat.last)
	 writeDoneFifo.enq(beat.tag);
   endrule

   interface MemSlave memSlave;
      interface MemReadServer read_server;
	 interface Put readReq;
	    method Action put(MemRequest#(32) req);
	       csrRag.request.put(MemRequest { addr: truncate(req.addr), burstLen: req.burstLen, tag: req.tag});
	    endmethod
	 endinterface
	 interface Get readData = toGet(readResponseFifo);
   endinterface: read_server

  interface MemWriteServer write_server;
	 interface Put writeReq;
	    method Action put(MemRequest#(32) req);
	       csrWag.request.put(MemRequest { addr: truncate(req.addr), burstLen: req.burstLen, tag: req.tag});
	    endmethod
	 endinterface
     interface Put writeData = toPut(writeDataFifo);
     interface Get writeDone = toGet(writeDoneFifo);
   endinterface: write_server
   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 MemTypes       :: *;
import AddressGenerator::*;

`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 MemSlave#(32,32) memSlave;
   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

   AddressGenerator#(16)              csrRag <- mkAddressGenerator;
   AddressGenerator#(16)              csrWag <- mkAddressGenerator;
   FIFOF#(MemData#(32))     readResponseFifo <- mkFIFOF();
   FIFOF#(MemData#(32))        writeDataFifo <- mkFIFOF();
   FIFOF#(Bit#(ObjectTagSize)) writeDoneFifo <- mkFIFOF();

   rule readDataRule;
      let beat <- csrRag.addrBeat.get();
      let addr = beat.addr;
      Bit#(32) data = 0;
      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: data = msix_entry[groupaddr].addr_lo;
               1: data = msix_entry[groupaddr].addr_hi;
               2: data = msix_entry[groupaddr].msg_data;
               3: data = {'0, pack(msix_entry[groupaddr].masked)}; // vector control
               default: data = 32'hbad0add0;
            endcase
         end
      else
	 case (modaddr)
            // board identification
            0: data = 32'h65756c42; // Blue
            1: data = 32'h63657073; // spec

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

            //******************************** start of area referenced from xilinx_x7_pcie_wrapper.v
            // 4-bit MSIx pending bit field
            992: data = '0;                               // PBA structure (low)
            993: data = '0;                               // PBA structure (high)
            //******************************** end of area referenced from xilinx_x7_pcie_wrapper.v
            // unused addresses
            default: data = 32'hbad0add0;
	 endcase
      readResponseFifo.enq(MemData { data: data, tag: beat.tag, last: beat.last });
   endrule

   rule writeDataRule;
      let beat <- csrWag.addrBeat.get();
      let addr = beat.addr;
      let memData <- toGet(writeDataFifo).get();
      let dword = memData.data;

      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
      if (beat.last)
	 writeDoneFifo.enq(beat.tag);
   endrule

   interface MemSlave memSlave;
      interface MemReadServer read_server;
	 interface Put readReq;
	    method Action put(MemRequest#(32) req);
	       csrRag.request.put(MemRequest { addr: truncate(req.addr), burstLen: req.burstLen, tag: req.tag});
	    endmethod
	 endinterface
	 interface Get readData = toGet(readResponseFifo);
   endinterface: read_server

  interface MemWriteServer write_server;
	 interface Put writeReq;
	    method Action put(MemRequest#(32) req);
	       csrWag.request.put(MemRequest { addr: truncate(req.addr), burstLen: req.burstLen, tag: req.tag});
	    endmethod
	 endinterface
     interface Put writeData = toPut(writeDataFifo);
     interface Get writeDone = toGet(writeDoneFifo);
   endinterface: write_server
   endinterface
   interface Vector msixEntry = map(toReadOnlyMsixEntry, msix_entry);
endmodule: mkPcieControlAndStatusRegs


remove non-BluenocTop parts of XsimTop.bsv

// Copyright (c) 2015 Quanta Research Cambridge, Inc.

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

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

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

`ifndef PinType
`define PinType Empty
`endif

typedef `PinType PinType;
typedef `NumberOfMasters NumberOfMasters;

module  mkXsimHost#(Clock derivedClock, Reset derivedReset)(XsimHost);
   interface derivedClock = derivedClock;
   interface derivedReset = derivedReset;
endmodule

interface XsimTop;
   interface MsgSource#(4) msgSource;
   interface MsgSink#(4) msgSink;
   interface Clock singleClock;
   interface Reset singleReset;
endinterface

module mkXsimTop(XsimTop);
   Clock derivedClock <- exposeCurrentClock;
   Reset derivedReset <- exposeCurrentReset;
   Clock single_clock = derivedClock;
   Reset single_reset = derivedReset;

   Reg#(Bool) dumpstarted <- mkReg(False);
   rule startdump if (!dumpstarted);
      $dumpfile("dump.vcd");
      $dumpvars;
   endrule
   XsimHost host <- mkXsimHost(derivedClock, derivedReset);
   BluenocTop#(1,1) top <- mkBluenocTop(
`ifdef IMPORT_HOSTIF
       host
`endif
       );

   interface msgSink = top.requests[0];
   interface msgSource = top.indications[0];
   interface Clock singleClock = single_clock;
   interface Reset singleReset = single_reset;
endmodule

// Copyright (c) 2015 Quanta Research Cambridge, Inc.

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

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

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

import Clocks            :: *;
import Vector            :: *;
import FIFOF             :: *;
import FIFO              :: *;
import SpecialFIFOs      :: *;
import GetPut            :: *;
import Connectable       :: *;
import StmtFSM           :: *;
import Portal            :: *;
//import Leds              :: *;
import Top               :: *;
import MemTypes          :: *;
import HostInterface     :: *;
import CtrlMux           :: *;
import ClientServer      :: *;
import PCIE              :: *;

`ifndef PinType
`define PinType Empty
`endif

typedef `PinType PinType;
typedef `NumberOfMasters NumberOfMasters;

module  mkXsimHost#(Clock derivedClock, Reset derivedReset)(XsimHost);
   interface derivedClock = derivedClock;
   interface derivedReset = derivedReset;
endmodule

`ifndef BluenocTop
interface XsimTop;
   method ActionValue#(Bit#(4)) interrupt();
   method ActionValue#(Bit#(32)) directoryEntry();
   method Action read(Bit#(32) addr);
   method ActionValue#(Bit#(32)) readData();
   method Action write(Bit#(32) addr, Bit#(32) data);

   interface Clock singleClock;
   interface Reset singleReset;
endinterface

module  mkXsimTop(XsimTop);
   //let divider <- mkClockDivider(2);
   Clock derivedClock <- exposeCurrentClock; //= divider.fastClock;
   Clock single_clock = derivedClock; //divider.slowClock;
   Reset derivedReset <- exposeCurrentReset;
   //let sr <- mkReset(2, True, single_clock);
   Reset single_reset = derivedReset; //sr.new_rst;

   XsimHost host <- mkXsimHost(clocked_by single_clock, reset_by single_reset, derivedClock, derivedReset);
   ConnectalTop#(PhysAddrWidth,DataBusWidth,PinType,NumberOfMasters) top <- mkConnectalTop(
`ifdef IMPORT_HOSTIF
       host,
`endif
       clocked_by single_clock, reset_by single_reset);
   //mapM(uncurry(mkConnection),zip(top.masters, host.mem_servers), clocked_by single_clock, reset_by single_reset);

   Vector#(16,Reg#(Bool)) interruptSent <- replicateM(mkReg(False));
   FIFO#(Bit#(4)) interruptFifo <- mkFIFO();
   rule int_rule;
      Bool found = False;
      Bit#(4) intrNum = 0;
      for (Integer i = 0; i < 16; i = i + 1) begin
	 if (top.interrupt[i] && !interruptSent[i] && !found) begin
	    found = True;
	    intrNum = fromInteger(i);
	 end
	 if (!top.interrupt[i])
	    interruptSent[i] <= False;
      end
      if (found) begin
	 interruptSent[intrNum] <= True;
	 interruptFifo.enq(intrNum);
      end
   endrule

   Reg#(Bool) readingDirectory <- mkReg(True);
   Reg#(Bool) token <- mkReg(True);
   Reg#(Bit#(8)) portalNumber <- mkReg(0);
   Reg#(Bit#(8)) offset <- mkReg(8'h10);
   Reg#(Bit#(32)) idReg <- mkReg(0);
   FIFO#(Bit#(32)) directoryFifo <- mkFIFO();
   rule readDirectory if (readingDirectory && portalNumber < 16 && token);
      let o = offset;
      let pn = portalNumber;
      top.slave.read_server.readReq.put(PhysMemRequest { addr: (extend(portalNumber) << 16) | extend(offset), burstLen: 4, tag: (o == 8'h10) ? 7 : 9});
      if (offset == 8'h14) begin
	 o = 8'h10;
	 pn = pn + 1;
      end
      else begin
	 o = o + 4;
      end
      offset <= o;
      portalNumber <= pn;
      token <= False;
   endrule
   rule directoryValue if (readingDirectory && !token);
      let memData <- top.slave.read_server.readData.get();

      let t = token;
      if (memData.tag == 7) begin
	 idReg <= memData.data;
	 t = True;
      end
      else begin
	 directoryFifo.enq((extend(memData.data[0]) << 31) | idReg);
	 // if this is not the last one, then read the next portal
	 t = (memData.data[0] == 0);
      end
      token <= t;
   endrule

   FIFO#(Bit#(32)) writeDataFifo <- mkFIFO();
   rule writedatarule;
      let data <- toGet(writeDataFifo).get();
      top.slave.write_server.writeData.put(MemData { data: data, tag: 0, last: True });
   endrule
   rule writedonerule;
      let done <- top.slave.write_server.writeDone.get();
   endrule

   method ActionValue#(Bit#(4)) interrupt();
      let i <- toGet(interruptFifo).get();
      return i;
   endmethod
   method ActionValue#(Bit#(32)) directoryEntry() if (readingDirectory);
      let v <- toGet(directoryFifo).get();
      if (v[31] == 1)
	 readingDirectory <= False;
      return v;
   endmethod

   method Action read(Bit#(32) addr) if (!readingDirectory);
      $display("read addr=%h", addr);
      top.slave.read_server.readReq.put(PhysMemRequest { addr: addr, burstLen: 4, tag: 0 });
   endmethod

   method ActionValue#(Bit#(32)) readData() if (!readingDirectory);
      let memData <- top.slave.read_server.readData.get();
      $display("read data=%h", memData.data);
      return memData.data;
   endmethod

   method Action write(Bit#(32) addr, Bit#(32) data);
      top.slave.write_server.writeReq.put(PhysMemRequest { addr: addr, burstLen: 4, tag: 0});
      writeDataFifo.enq(data);
   endmethod

`ifdef BSIMRESPONDER
   `BSIMRESPONDER (top.pins);
`endif
   interface Clock singleClock = single_clock;
   interface Reset singleReset = single_reset;
endmodule

`else
import BlueNoC::*;
import BnocPortal::*;

interface XsimTop;
   interface MsgSource#(4) msgSource;
   interface MsgSink#(4) msgSink;

   interface Clock singleClock;
   interface Reset singleReset;
endinterface

module mkXsimTop(XsimTop);
   //let divider <- mkClockDivider(2);
   Clock derivedClock <- exposeCurrentClock; //= divider.fastClock;
   Clock single_clock = derivedClock; //divider.slowClock;
   Reset derivedReset <- exposeCurrentReset;
   //let sr <- mkReset(2, True, single_clock);
   Reset single_reset = derivedReset; //sr.new_rst;

   Reg#(Bool) dumpstarted <- mkReg(False);
   rule startdump if (!dumpstarted);
      $dumpfile("dump.vcd");
      $dumpvars;
   endrule
   XsimHost host <- mkXsimHost(clocked_by single_clock, reset_by single_reset, derivedClock, derivedReset);
   BluenocTop#(1,1) top <- mkBluenocTop(
`ifdef IMPORT_HOSTIF
       host,
`endif
       clocked_by single_clock, reset_by single_reset);

   interface msgSink = top.requests[0];
   interface msgSource = top.indications[0];

   interface Clock singleClock = single_clock;
   interface Reset singleReset = single_reset;
endmodule
`endif