dumpvars for first 10K cycles in memwrite_bluesim

Change-Id: Ifd130334951958ac40a4f56ca02e2c02a8d06eda

// bsv libraries
import SpecialFIFOs::*;
import Vector::*;
import StmtFSM::*;
import FIFO::*;
import GetPut::*;
import ClientServer::*;
import Connectable::*;
import PCIE::*;

// portz libraries
import Leds::*;
import Directory::*;
import CtrlMux::*;
import Portal::*;
import PortalMemory::*;
import MemTypes::*;
import MemServer::*;
import MMU::*;
import HostInterface::*;
import MemSlaveEngine::*;

// generated by tool
import MemwriteRequestWrapper::*;
import DmaDebugRequestWrapper::*;
import MMUConfigRequestWrapper::*;
import MemwriteIndicationProxy::*;
import DmaDebugIndicationProxy::*;
import MMUConfigIndicationProxy::*;

// defined by user
import Memwrite::*;

typedef enum {HostDmaDebugIndication, HostDmaDebugRequest, HostMMUConfigRequest, HostMMUConfigIndication, MemwriteIndication, MemwriteRequest} IfcNames deriving (Eq,Bits);

module mkPortalTop(PortalTop#(PhysAddrWidth,DataBusWidth,Empty,1));

   MemwriteIndicationProxy memwriteIndicationProxy <- mkMemwriteIndicationProxy(MemwriteIndication);
   Memwrite memwrite <- mkMemwrite(memwriteIndicationProxy.ifc);
   MemwriteRequestWrapper memwriteRequestWrapper <- mkMemwriteRequestWrapper(MemwriteRequest,memwrite.request);

   Vector#(1, ObjectWriteClient#(DataBusWidth)) writeClients = cons(memwrite.dmaClient,nil);
   MMUConfigIndicationProxy hostMMUConfigIndicationProxy <- mkMMUConfigIndicationProxy(HostMMUConfigIndication);
   MMU#(PhysAddrWidth) hostMMU <- mkMMU(0, True, hostMMUConfigIndicationProxy.ifc);
   MMUConfigRequestWrapper hostMMUConfigRequestWrapper <- mkMMUConfigRequestWrapper(HostMMUConfigRequest, hostMMU.request);

   DmaDebugIndicationProxy hostDmaDebugIndicationProxy <- mkDmaDebugIndicationProxy(HostDmaDebugIndication);
   MemServer#(PhysAddrWidth,DataBusWidth,1) dma <- mkMemServerW(hostDmaDebugIndicationProxy.ifc, writeClients, cons(hostMMU,nil));
   DmaDebugRequestWrapper hostDmaDebugRequestWrapper <- mkDmaDebugRequestWrapper(HostDmaDebugRequest, dma.request);

   MemMaster#(PhysAddrWidth,DataBusWidth) dma1 = (interface MemMaster;
	  interface MemReadClient read_client;
	     interface Get readReq;
		method ActionValue#(MemRequest#(PhysAddrWidth)) get() if (False);
		   return ?;
	        endmethod
	     endinterface
	  endinterface
	  interface MemWriteClient write_client;
	     interface Get writeReq;
		method ActionValue#(MemRequest#(PhysAddrWidth)) get() if (False);
		   return ?;
	        endmethod
	     endinterface
	  endinterface
      endinterface);

   Reg#(Bit#(32)) cycles <- mkReg(0);
   Reg#(Bit#(32)) reqCycles <- mkReg(0);
   Reg#(Bit#(32)) dataCycles <- mkReg(0);
   rule count;
      cycles <= cycles + 1;
   endrule

   rule startdump if (cycles == 1);
      $dumpvars();
   endrule

   rule finish if (reqCycles == 10000);
      $dumpoff();
   endrule

   MemSlaveEngine#(DataBusWidth) memSlaveEngine <- mkMemSlaveEngine(PciId {bus: 4, dev: 2, func: 0});
   mkConnection(dma.masters[0], memSlaveEngine.slave);

   rule displayTlp;
      let tlp <- memSlaveEngine.tlp.request.get();
      TLPMemory4DWHeader hdr4dw = unpack(tlp.data);
      TLPMemoryIO3DWHeader hdr3dw = unpack(tlp.data);
      let newReqCycles = reqCycles;
      if (tlp.sof && hdr4dw.format == MEM_WRITE_4DW_DATA) begin
	 $display("%d 4dw req %h %d", cycles-reqCycles, hdr4dw.addr<<2, fromInteger(valueOf(DataBusWidth)));
	 newReqCycles = cycles;
      end
      else if (tlp.sof && hdr3dw.format == MEM_WRITE_3DW_DATA) begin
	 $display("%d 3dw req %h %d", cycles-reqCycles, hdr4dw.addr<<2, fromInteger(valueOf(DataBusWidth)));
	 newReqCycles = cycles;
      end
      else if (tlp.sof) begin
	 $display("%d sof %h", cycles-reqCycles, tlp.data);
	 newReqCycles = cycles;
      end
      else begin
	 $display("%d data %h", cycles-reqCycles, tlp.data);
	 dataCycles <= cycles;
	 newReqCycles = cycles;
      end
      reqCycles <= newReqCycles;
   endrule

   Vector#(6,StdPortal) portals;
   portals[0] = memwriteRequestWrapper.portalIfc;
   portals[1] = memwriteIndicationProxy.portalIfc;
   portals[2] = hostDmaDebugRequestWrapper.portalIfc;
   portals[3] = hostDmaDebugIndicationProxy.portalIfc;
   portals[4] = hostMMUConfigRequestWrapper.portalIfc;
   portals[5] = hostMMUConfigIndicationProxy.portalIfc;

   StdDirectory dir <- mkStdDirectory(portals);
   let ctrl_mux <- mkSlaveMux(dir,portals);

   interface interrupt = getInterruptVector(portals);
   interface slave = ctrl_mux;
   interface masters = cons(dma1,nil);
   interface leds = default_leds;
endmodule

// bsv libraries
import SpecialFIFOs::*;
import Vector::*;
import StmtFSM::*;
import FIFO::*;
import GetPut::*;
import ClientServer::*;
import Connectable::*;
import PCIE::*;

// portz libraries
import Leds::*;
import Directory::*;
import CtrlMux::*;
import Portal::*;
import PortalMemory::*;
import MemTypes::*;
import MemServer::*;
import MMU::*;
import HostInterface::*;
import MemSlaveEngine::*;

// generated by tool
import MemwriteRequestWrapper::*;
import DmaDebugRequestWrapper::*;
import MMUConfigRequestWrapper::*;
import MemwriteIndicationProxy::*;
import DmaDebugIndicationProxy::*;
import MMUConfigIndicationProxy::*;

// defined by user
import Memwrite::*;

typedef enum {HostDmaDebugIndication, HostDmaDebugRequest, HostMMUConfigRequest, HostMMUConfigIndication, MemwriteIndication, MemwriteRequest} IfcNames deriving (Eq,Bits);

module mkPortalTop(PortalTop#(PhysAddrWidth,DataBusWidth,Empty,1));

   MemwriteIndicationProxy memwriteIndicationProxy <- mkMemwriteIndicationProxy(MemwriteIndication);
   Memwrite memwrite <- mkMemwrite(memwriteIndicationProxy.ifc);
   MemwriteRequestWrapper memwriteRequestWrapper <- mkMemwriteRequestWrapper(MemwriteRequest,memwrite.request);

   Vector#(1, ObjectWriteClient#(DataBusWidth)) writeClients = cons(memwrite.dmaClient,nil);
   MMUConfigIndicationProxy hostMMUConfigIndicationProxy <- mkMMUConfigIndicationProxy(HostMMUConfigIndication);
   MMU#(PhysAddrWidth) hostMMU <- mkMMU(0, True, hostMMUConfigIndicationProxy.ifc);
   MMUConfigRequestWrapper hostMMUConfigRequestWrapper <- mkMMUConfigRequestWrapper(HostMMUConfigRequest, hostMMU.request);

   DmaDebugIndicationProxy hostDmaDebugIndicationProxy <- mkDmaDebugIndicationProxy(HostDmaDebugIndication);
   MemServer#(PhysAddrWidth,DataBusWidth,1) dma <- mkMemServerW(hostDmaDebugIndicationProxy.ifc, writeClients, cons(hostMMU,nil));
   DmaDebugRequestWrapper hostDmaDebugRequestWrapper <- mkDmaDebugRequestWrapper(HostDmaDebugRequest, dma.request);

   MemMaster#(PhysAddrWidth,DataBusWidth) dma1 = (interface MemMaster;
	  interface MemReadClient read_client;
	     interface Get readReq;
		method ActionValue#(MemRequest#(PhysAddrWidth)) get() if (False);
		   return ?;
	        endmethod
	     endinterface
	  endinterface
	  interface MemWriteClient write_client;
	     interface Get writeReq;
		method ActionValue#(MemRequest#(PhysAddrWidth)) get() if (False);
		   return ?;
	        endmethod
	     endinterface
	  endinterface
      endinterface);

   Reg#(Bit#(32)) cycles <- mkReg(0);
   Reg#(Bit#(32)) reqCycles <- mkReg(0);
   Reg#(Bit#(32)) dataCycles <- mkReg(0);
   rule count;
      cycles <= cycles + 1;
   endrule

   MemSlaveEngine#(DataBusWidth) memSlaveEngine <- mkMemSlaveEngine(PciId {bus: 4, dev: 2, func: 0});
   mkConnection(dma.masters[0], memSlaveEngine.slave);

   rule displayTlp;
      let tlp <- memSlaveEngine.tlp.request.get();
      TLPMemory4DWHeader hdr4dw = unpack(tlp.data);
      TLPMemoryIO3DWHeader hdr3dw = unpack(tlp.data);
      let newReqCycles = reqCycles;
      if (tlp.sof && hdr4dw.format == MEM_WRITE_4DW_DATA) begin
	 $display("%d req %h %d", cycles-reqCycles, hdr4dw.addr<<2, fromInteger(valueOf(DataBusWidth)));
	 newReqCycles = cycles;
      end
      if (tlp.sof && hdr3dw.format == MEM_WRITE_3DW_DATA) begin
	 $display("%d req %h %d", cycles-reqCycles, hdr4dw.addr<<2, fromInteger(valueOf(DataBusWidth)));
	 newReqCycles = cycles;
      end
      else if (tlp.sof) begin
	 $display("%d sof %h", cycles-reqCycles, tlp.data);
	 newReqCycles = cycles;
      end
      else begin
	 $display("%d data %h", cycles-dataCycles, tlp.data);
	 dataCycles <= cycles;
      end
      reqCycles <= newReqCycles;
   endrule

   Vector#(6,StdPortal) portals;
   portals[0] = memwriteRequestWrapper.portalIfc;
   portals[1] = memwriteIndicationProxy.portalIfc;
   portals[2] = hostDmaDebugRequestWrapper.portalIfc;
   portals[3] = hostDmaDebugIndicationProxy.portalIfc;
   portals[4] = hostMMUConfigRequestWrapper.portalIfc;
   portals[5] = hostMMUConfigIndicationProxy.portalIfc;

   StdDirectory dir <- mkStdDirectory(portals);
   let ctrl_mux <- mkSlaveMux(dir,portals);

   interface interrupt = getInterruptVector(portals);
   interface slave = ctrl_mux;
   interface masters = cons(dma1,nil);
   interface leds = default_leds;
endmodule


enable use of full speed pcie clock

enable use of full speed pcie clock

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

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

import ConnectalClocks   ::*;
import ConnectalXilinxCells   ::*;
import XilinxCells       ::*;
import PCIE              ::*;
import PCIEWRAPPER2      ::*;
import Bufgctrl           ::*;

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

interface PcieEndpointX7#(numeric type lanes);
   interface PciewrapPci_exp#(lanes)   pcie;
   interface PciewrapUser#(lanes)      user;
   interface PciewrapCfg#(lanes)       cfg;
   interface Server#(TLPData#(16), TLPData#(16)) tlp;
   interface Clock epPcieClock;
   interface Reset epPcieReset;
   interface Clock epPortalClock;
   interface Reset epPortalReset;
   interface Clock epDerivedClock;
   interface Reset epDerivedReset;
endinterface

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

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

`ifdef Artix7
typedef 4 PcieLanes;
`endif
`ifdef BOARD_zc706
typedef 4 PcieLanes;
`endif
`ifdef BOARD_vc707
typedef 8 PcieLanes;
`endif
`ifdef BOARD_kc705
typedef 8 PcieLanes;
`endif
`ifdef BOARD_netfpgasume
typedef 8 PcieLanes;
`endif

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

   Clock defaultClock <- exposeCurrentClock();
   Reset defaultReset <- exposeCurrentReset();

   PcieWrap#(PcieLanes) pcie_ep <- mkPcieWrap(defaultClock, defaultReset);

   Clock user_clk = pcie_ep.user_clk_out;
   Reset user_reset_n <- mkResetInverter(pcie_ep.user_reset_out, clocked_by user_clk);

   FIFOF#(AxiTx)             fAxiTx              <- mkFIFOF(clocked_by user_clk, reset_by user_reset_n);
   FIFOF#(AxiRx)             fAxiRx              <- mkFIFOF(clocked_by user_clk, reset_by user_reset_n);

   (* fire_when_enabled, no_implicit_conditions *)
   rule every1;
      pcie_ep.fc.sel(0 /*RECEIVE_BUFFER_AVAILABLE_SPACE*/);
      pcie_ep.cfg_dsn({ 32'h0000_0001, {{ 8'h1 } , 24'h000A35 }});
      pcie_ep.rx.np_ok(1);
      pcie_ep.rx.np_req(1);
      pcie_ep.tx.cfg_gnt(1);
      pcie_ep.s_axis_tx.tuser(4'b0);
      pcie_ep.m_axis_rx.tready(pack(fAxiRx.notFull));
   endrule
   rule every_cfg_err;
      pcie_ep.cfg_err.acs(0);
      pcie_ep.cfg_err.aer_headerlog(0);
      pcie_ep.cfg_err.atomic_egress_blocked(0);
      pcie_ep.cfg_err.cor(0);
      pcie_ep.cfg_err.cpl_abort(0);
      pcie_ep.cfg_err.cpl_timeout(0);
      pcie_ep.cfg_err.cpl_unexpect(0);
      pcie_ep.cfg_err.ecrc(0);
      pcie_ep.cfg_err.internal_cor(0);
      pcie_ep.cfg_err.internal_uncor(0);
      pcie_ep.cfg_err.locked(0);
      pcie_ep.cfg_err.malformed(0);
      pcie_ep.cfg_err.mc_blocked(0);
      pcie_ep.cfg_err.norecovery(0);
      pcie_ep.cfg_err.poisoned(0);
      pcie_ep.cfg_err.posted(0);
      pcie_ep.cfg_err.tlp_cpl_header(0);
      pcie_ep.cfg_err.ur(0);
   endrule
   rule every_interrupt;
      pcie_ep.cfg_interrupt.zzassert(0);
      pcie_ep.cfg_interrupt.di(0);
      pcie_ep.cfg_interrupt.stat(0);
   endrule
   rule every_mgmt;
      pcie_ep.cfg_mgmt.byte_en(0);
      pcie_ep.cfg_mgmt.di(0);
      pcie_ep.cfg_mgmt.dwaddr(0);
      pcie_ep.cfg_mgmt.rd_en(0);
      pcie_ep.cfg_mgmt.wr_en(0);
      pcie_ep.cfg_mgmt.wr_readonly(0);
   endrule
   rule every_pm;
      pcie_ep.cfg_pm.force_state(0);
      pcie_ep.cfg_pm.force_state_en(0);
      pcie_ep.cfg_pm.halt_aspm_l0s(0);
      pcie_ep.cfg_pm.halt_aspm_l1(0);
      pcie_ep.cfg_pm.send_pme_to(0);
      pcie_ep.cfg_pm.wake(0);
   endrule
   rule every_pl;
      pcie_ep.pl.directed_link_auton(0);
      pcie_ep.pl.directed_link_change(0);
      pcie_ep.pl.directed_link_speed(0);
      pcie_ep.pl.directed_link_width(0);
      pcie_ep.pl.downstream_deemph_source(0);
      pcie_ep.pl.transmit_hot_rst(0);
      pcie_ep.pl.upstream_prefer_deemph(1);
   endrule

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

   (* fire_when_enabled *)
   rule drive_axi_tx if (txready);
      let info = unpack(0);
      if (fAxiTx.notEmpty) begin
	 info <- toGet(fAxiTx).get();
      end
      pcie_ep.s_axis_tx.tlast(info.last);
      pcie_ep.s_axis_tx.tdata(info.data);
      pcie_ep.s_axis_tx.tkeep(info.keep);
   endrule
   (* fire_when_enabled, no_implicit_conditions *)
   rule drive_axi_txvalid if (fAxiTx.notEmpty);
      pcie_ep.s_axis_tx.tvalid(1);
   endrule
   (* fire_when_enabled, no_implicit_conditions *)
   rule drive_axi_tx2 if (!fAxiTx.notEmpty);
      pcie_ep.s_axis_tx.tvalid(0);
      pcie_ep.s_axis_tx.tlast(0);
      pcie_ep.s_axis_tx.tdata(0);
      pcie_ep.s_axis_tx.tkeep(0);
   endrule

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

   Reset user_reset <- mkAsyncReset(4, user_reset_n, user_clk);

   ClockGenerator7Params     clkgenParams = defaultValue;
   clkgenParams.clkin1_period    = 4.000; //  250MHz
   clkgenParams.clkin_buffer     = False;
   clkgenParams.clkfbout_mult_f  = 4.000; // 1000MHz
   clkgenParams.clkout0_divide_f = 4.000; //  250MHz
   clkgenParams.clkout1_divide     = round(mainClockPeriod);
   clkgenParams.clkout1_duty_cycle = 0.5;
   clkgenParams.clkout1_phase      = 0.0000;
   clkgenParams.clkout2_divide     = round(derivedClockPeriod);
   clkgenParams.clkout2_duty_cycle = 0.5;
   clkgenParams.clkout2_phase      = 0.0000;
   ClockGenerator7           clkgen <- mkClockGenerator7(clkgenParams, clocked_by user_clk, reset_by user_reset_n);
   Clock portalClock;
   Reset portalReset;
   if (mainClockPeriod == 4) begin
      portalClock = user_clk;
      portalReset = user_reset_n;
   end
   else begin
      portalClock = clkgen.clkout1;
      portalReset <- mkAsyncReset(4, user_reset_n, portalClock);
   end
   Clock derivedClock = clkgen.clkout2;
   Reset derivedReset <- mkAsyncReset(4, user_reset_n, derivedClock);

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

   interface tlp = tlp16;
   interface pcie    = pcie_ep.pci_exp;
   interface PciewrapUser user = pcie_ep.user;
   interface PciewrapCfg cfg = pcie_ep.cfg;
   interface Clock epPcieClock = user_clk;
   interface Reset epPcieReset = user_reset_n;
   interface Clock epPortalClock = portalClock;
   interface Reset epPortalReset = portalReset;
   interface Clock epDerivedClock = derivedClock;
   interface Reset epDerivedReset = derivedReset;
endmodule: mkPcieEndpointX7

endpackage: PcieEndpointX7Gen2

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

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

import ConnectalClocks   ::*;
import ConnectalXilinxCells   ::*;
import XilinxCells       ::*;
import PCIE              ::*;
import PCIEWRAPPER2      ::*;
import Bufgctrl           ::*;

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

interface PcieEndpointX7#(numeric type lanes);
   interface PciewrapPci_exp#(lanes)   pcie;
   interface PciewrapUser#(lanes)      user;
   interface PciewrapCfg#(lanes)       cfg;
   interface Server#(TLPData#(16), TLPData#(16)) tlp;
   interface Clock epPcieClock;
   interface Reset epPcieReset;
   interface Clock epPortalClock;
   interface Reset epPortalReset;
   interface Clock epDerivedClock;
   interface Reset epDerivedReset;
endinterface

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

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

`ifdef Artix7
typedef 4 PcieLanes;
`endif
`ifdef BOARD_zc706
typedef 4 PcieLanes;
`endif
`ifdef BOARD_vc707
typedef 8 PcieLanes;
`endif
`ifdef BOARD_kc705
typedef 8 PcieLanes;
`endif
`ifdef BOARD_netfpgasume
typedef 8 PcieLanes;
`endif

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

   Clock defaultClock <- exposeCurrentClock();
   Reset defaultReset <- exposeCurrentReset();

   PcieWrap#(PcieLanes) pcie_ep <- mkPcieWrap(defaultClock, defaultReset);

   Clock user_clk = pcie_ep.user_clk_out;
   Reset user_reset_n <- mkResetInverter(pcie_ep.user_reset_out, clocked_by user_clk);

   FIFOF#(AxiTx)             fAxiTx              <- mkFIFOF(clocked_by user_clk, reset_by user_reset_n);
   FIFOF#(AxiRx)             fAxiRx              <- mkFIFOF(clocked_by user_clk, reset_by user_reset_n);

   (* fire_when_enabled, no_implicit_conditions *)
   rule every1;
      pcie_ep.fc.sel(0 /*RECEIVE_BUFFER_AVAILABLE_SPACE*/);
      pcie_ep.cfg_dsn({ 32'h0000_0001, {{ 8'h1 } , 24'h000A35 }});
      pcie_ep.rx.np_ok(1);
      pcie_ep.rx.np_req(1);
      pcie_ep.tx.cfg_gnt(1);
      pcie_ep.s_axis_tx.tuser(4'b0);
      pcie_ep.m_axis_rx.tready(pack(fAxiRx.notFull));
   endrule
   rule every_cfg_err;
      pcie_ep.cfg_err.acs(0);
      pcie_ep.cfg_err.aer_headerlog(0);
      pcie_ep.cfg_err.atomic_egress_blocked(0);
      pcie_ep.cfg_err.cor(0);
      pcie_ep.cfg_err.cpl_abort(0);
      pcie_ep.cfg_err.cpl_timeout(0);
      pcie_ep.cfg_err.cpl_unexpect(0);
      pcie_ep.cfg_err.ecrc(0);
      pcie_ep.cfg_err.internal_cor(0);
      pcie_ep.cfg_err.internal_uncor(0);
      pcie_ep.cfg_err.locked(0);
      pcie_ep.cfg_err.malformed(0);
      pcie_ep.cfg_err.mc_blocked(0);
      pcie_ep.cfg_err.norecovery(0);
      pcie_ep.cfg_err.poisoned(0);
      pcie_ep.cfg_err.posted(0);
      pcie_ep.cfg_err.tlp_cpl_header(0);
      pcie_ep.cfg_err.ur(0);
   endrule
   rule every_interrupt;
      pcie_ep.cfg_interrupt.zzassert(0);
      pcie_ep.cfg_interrupt.di(0);
      pcie_ep.cfg_interrupt.stat(0);
   endrule
   rule every_mgmt;
      pcie_ep.cfg_mgmt.byte_en(0);
      pcie_ep.cfg_mgmt.di(0);
      pcie_ep.cfg_mgmt.dwaddr(0);
      pcie_ep.cfg_mgmt.rd_en(0);
      pcie_ep.cfg_mgmt.wr_en(0);
      pcie_ep.cfg_mgmt.wr_readonly(0);
   endrule
   rule every_pm;
      pcie_ep.cfg_pm.force_state(0);
      pcie_ep.cfg_pm.force_state_en(0);
      pcie_ep.cfg_pm.halt_aspm_l0s(0);
      pcie_ep.cfg_pm.halt_aspm_l1(0);
      pcie_ep.cfg_pm.send_pme_to(0);
      pcie_ep.cfg_pm.wake(0);
   endrule
   rule every_pl;
      pcie_ep.pl.directed_link_auton(0);
      pcie_ep.pl.directed_link_change(0);
      pcie_ep.pl.directed_link_speed(0);
      pcie_ep.pl.directed_link_width(0);
      pcie_ep.pl.downstream_deemph_source(0);
      pcie_ep.pl.transmit_hot_rst(0);
      pcie_ep.pl.upstream_prefer_deemph(1);
   endrule

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

   (* fire_when_enabled *)
   rule drive_axi_tx if (txready);
      let info = unpack(0);
      if (fAxiTx.notEmpty) begin
	 info <- toGet(fAxiTx).get();
      end
      pcie_ep.s_axis_tx.tlast(info.last);
      pcie_ep.s_axis_tx.tdata(info.data);
      pcie_ep.s_axis_tx.tkeep(info.keep);
   endrule
   (* fire_when_enabled, no_implicit_conditions *)
   rule drive_axi_txvalid if (fAxiTx.notEmpty);
      pcie_ep.s_axis_tx.tvalid(1);
   endrule
   (* fire_when_enabled, no_implicit_conditions *)
   rule drive_axi_tx2 if (!fAxiTx.notEmpty);
      pcie_ep.s_axis_tx.tvalid(0);
      pcie_ep.s_axis_tx.tlast(0);
      pcie_ep.s_axis_tx.tdata(0);
      pcie_ep.s_axis_tx.tkeep(0);
   endrule

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

   Reset user_reset <- mkAsyncReset(4, user_reset_n, user_clk);

   ClockGenerator7Params     clkgenParams = defaultValue;
   clkgenParams.clkin1_period    = 4.000; //  250MHz
   clkgenParams.clkin_buffer     = False;
   clkgenParams.clkfbout_mult_f  = 4.000; // 1000MHz
   clkgenParams.clkout0_divide_f = 4.000; //  250MHz
   clkgenParams.clkout1_divide     = round(mainClockPeriod);
   clkgenParams.clkout1_duty_cycle = 0.5;
   clkgenParams.clkout1_phase      = 0.0000;
   clkgenParams.clkout2_divide     = round(derivedClockPeriod);
   clkgenParams.clkout2_duty_cycle = 0.5;
   clkgenParams.clkout2_phase      = 0.0000;
   ClockGenerator7           clkgen <- mkClockGenerator7(clkgenParams, clocked_by user_clk, reset_by user_reset_n);
   Clock portalClock = clkgen.clkout1;
   Reset portalReset <- mkAsyncReset(4, user_reset_n, portalClock);
   Clock derivedClock = clkgen.clkout2;
   Reset derivedReset <- mkAsyncReset(4, user_reset_n, derivedClock);

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

   interface tlp = tlp16;
   interface pcie    = pcie_ep.pci_exp;
   interface PciewrapUser user = pcie_ep.user;
   interface PciewrapCfg cfg = pcie_ep.cfg;
   interface Clock epPcieClock = user_clk;
   interface Reset epPcieReset = user_reset_n;
   interface Clock epPortalClock = portalClock;
   interface Reset epPortalReset = portalReset;
   interface Clock epDerivedClock = derivedClock;
   interface Reset epDerivedReset = derivedReset;
endmodule: mkPcieEndpointX7

endpackage: PcieEndpointX7Gen2


Added Axi4Client and Axi4Server

Added Axi4Client and Axi4Server

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

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

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

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

import RegFile::*;
import BRAMFIFO::*;
import FIFO::*;
import FIFOF::*;
import FIFOLevel::*;
import SpecialFIFOs::*;

typedef struct {
    Bit#(addrWidth) address;
    Bit#(4) burstLen;
    // Bit#(3) burstWidth; // assume matches bus width of Axi3Client
    // Bit#(2) readBurstType();  // drive with 2'b01
    // Bit#(2) readBurstProt(); // drive with 3'b000
    // Bit#(3) readBurstCache(); // drive with 4'b0011
    Bit#(idWidth) id;
} Axi3ReadRequest#(type addrWidth, type idWidth) deriving (Bits);

typedef struct {
    Bit#(busWidth) data;
    Bit#(2) code;
    Bit#(1) last;
    Bit#(idWidth) id;
} Axi3ReadResponse#(type busWidth, type idWidth) deriving (Bits);

interface Axi3ReadClient#(type addrWidth, type busWidth, type idWidth);
   method ActionValue#(Axi3ReadRequest#(addrWidth, idWidth)) address();
   method Action data(Axi3ReadResponse#(busWidth, idWidth) response);
endinterface

typedef struct {
    Bit#(addrWidth) address;
    Bit#(4) burstLen;
    // Bit#(3) burstWidth; // assume matches bus width of Axi3Client
    // Bit#(2) burstType;  // drive with 2'b01
    // Bit#(2) burstProt; // drive with 3'b000
    // Bit#(3) burstCache; // drive with 4'b0011
    Bit#(idWidth) id;
} Axi3WriteRequest#(type addrWidth, type idWidth) deriving (Bits);

typedef struct {
    Bit#(busWidth) data;
    Bit#(busWidthBytes) byteEnable;
    Bit#(1)        last;
    Bit#(idWidth) id;
} Axi3WriteData#(type busWidth, type busWidthBytes, type idWidth) deriving (Bits);

typedef struct {
    Bit#(2) code;
    Bit#(idWidth) id;
} Axi3WriteResponse#(type idWidth) deriving (Bits);

interface Axi3WriteClient#(type addrWidth, type busWidth, type busWidthBytes, type idWidth);
   method ActionValue#(Axi3WriteRequest#(addrWidth, idWidth)) address();
   method ActionValue#(Axi3WriteData#(busWidth, busWidthBytes, idWidth)) data();
   method Action response(Axi3WriteResponse#(idWidth) response);
endinterface

interface Axi3Client#(type addrWidth, type busWidth, type busWidthBytes, type idWidth);
   interface Axi3ReadClient#(addrWidth, busWidth, idWidth) read;
   interface Axi3WriteClient#(addrWidth, busWidth, busWidthBytes, idWidth) write;
endinterface

module mkAxi3Client#(Axi3WriteClient#(addrWidth, busWidth,busWidthBytes,idWidth) writeClient,
                     Axi3ReadClient#(addrWidth, busWidth,idWidth) readClient)
                    (Axi3Client#(addrWidth, busWidth, busWidthBytes, idWidth));
    interface Axi3ReadClient read = readClient;
    interface Axi3WriteClient write = writeClient;
endmodule

interface Axi3ReadServer#(type addrWidth, type busWidth, type idWidth);
   method Action address(Axi3ReadRequest#(addrWidth, idWidth) request);
   method ActionValue#(Axi3ReadResponse#(busWidth, idWidth)) data();
endinterface

interface Axi3WriteServer#(type addrWidth, type busWidth, type busWidthBytes, type idWidth);
   method Action address(Axi3WriteRequest#(addrWidth, idWidth) request);
   method Action data(Axi3WriteData#(busWidth, busWidthBytes, idWidth) data);
   method ActionValue#(Axi3WriteResponse#(idWidth)) response();
endinterface

interface Axi3Server#(type addrWidth, type busWidth, type busWidthBytes, type idWidth);
   interface Axi3ReadServer#(addrWidth, busWidth, idWidth) read;
   interface Axi3WriteServer#(addrWidth, busWidth, busWidthBytes, idWidth) write;
endinterface

typedef struct {
    Bit#(addrWidth) address;
    Bit#(8) burstLen;
    // Bit#(3) burstWidth; // assume matches bus width of Axi4Client
    // Bit#(2) readBurstType();  // drive with 2'b01
    // Bit#(2) readBurstProt(); // drive with 3'b000
    // Bit#(3) readBurstCache(); // drive with 4'b0011
    Bit#(idWidth) id;
} Axi4ReadRequest#(type addrWidth, type idWidth) deriving (Bits);

typedef struct {
    Bit#(busWidth) data;
    Bit#(2) code;
    Bit#(1) last;
    Bit#(idWidth) id;
} Axi4ReadResponse#(type busWidth, type idWidth) deriving (Bits);

interface Axi4ReadClient#(type addrWidth, type busWidth, type idWidth);
   method ActionValue#(Axi4ReadRequest#(addrWidth, idWidth)) address();
   method Action data(Axi4ReadResponse#(busWidth, idWidth) response);
endinterface

typedef struct {
    Bit#(addrWidth) address;
    Bit#(8) burstLen;
    // Bit#(3) burstWidth; // assume matches bus width of Axi4Client
    // Bit#(2) burstType;  // drive with 2'b01
    // Bit#(2) burstProt; // drive with 3'b000
    // Bit#(3) burstCache; // drive with 4'b0011
    Bit#(idWidth) id;
} Axi4WriteRequest#(type addrWidth, type idWidth) deriving (Bits);

typedef struct {
    Bit#(busWidth) data;
    Bit#(busWidthBytes) byteEnable;
    Bit#(1)        last;
    Bit#(idWidth) id;
} Axi4WriteData#(type busWidth, type busWidthBytes, type idWidth) deriving (Bits);

typedef struct {
    Bit#(2) code;
    Bit#(idWidth) id;
} Axi4WriteResponse#(type idWidth) deriving (Bits);

interface Axi4WriteClient#(type addrWidth, type busWidth, type busWidthBytes, type idWidth);
   method ActionValue#(Axi4WriteRequest#(addrWidth, idWidth)) address();
   method ActionValue#(Axi4WriteData#(busWidth, busWidthBytes, idWidth)) data();
   method Action response(Axi4WriteResponse#(idWidth) response);
endinterface

interface Axi4Client#(type addrWidth, type busWidth, type busWidthBytes, type idWidth);
   interface Axi4ReadClient#(addrWidth, busWidth, idWidth) read;
   interface Axi4WriteClient#(addrWidth, busWidth, busWidthBytes, idWidth) write;
endinterface

module mkAxi4Client#(Axi4WriteClient#(addrWidth, busWidth,busWidthBytes,idWidth) writeClient,
                     Axi4ReadClient#(addrWidth, busWidth,idWidth) readClient)
                    (Axi4Client#(addrWidth, busWidth, busWidthBytes, idWidth));
    interface Axi4ReadClient read = readClient;
    interface Axi4WriteClient write = writeClient;
endmodule

interface Axi4ReadServer#(type addrWidth, type busWidth, type idWidth);
   method Action address(Axi4ReadRequest#(addrWidth, idWidth) request);
   method ActionValue#(Axi4ReadResponse#(busWidth, idWidth)) data();
endinterface

interface Axi4WriteServer#(type addrWidth, type busWidth, type busWidthBytes, type idWidth);
   method Action address(Axi4WriteRequest#(addrWidth, idWidth) request);
   method Action data(Axi4WriteData#(busWidth, busWidthBytes, idWidth) data);
   method ActionValue#(Axi4WriteResponse#(idWidth)) response();
endinterface

interface Axi4Server#(type addrWidth, type busWidth, type busWidthBytes, type idWidth);
   interface Axi4ReadServer#(addrWidth, busWidth, idWidth) read;
   interface Axi4WriteServer#(addrWidth, busWidth, busWidthBytes, idWidth) write;
endinterface


PipelineFIFOs scare me, using mkFIFO(F)

PipelineFIFOs scare me, using mkFIFO(F)

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

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

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

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

package Pcie3EndpointX7;

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

import ConnectalClocks   ::*;
import ConnectalXilinxCells   ::*;
import XilinxCells       ::*;
import PCIE              ::*;
import PCIEWRAPPER3      ::*;
import Bufgctrl           ::*;
import PcieGearbox       :: *;

interface PcieEndpointX7#(numeric type lanes);
   interface PciewrapPci_exp#(lanes)           pcie;
   interface PciewrapUser#(lanes)              user;
   interface PciewrapPipe#(lanes)              pipe;
   interface PciewrapCommon#(lanes)            common;
   interface Server#(TLPData#(16), TLPData#(16)) tlpr;
   interface Server#(TLPData#(16), TLPData#(16)) tlpc;
   interface Clock epPcieClock;
   interface Reset epPcieReset;
   interface Clock epPortalClock;
   interface Reset epPortalReset;
   interface Clock epDerivedClock;
   interface Reset epDerivedReset;
endinterface

typedef struct {
   Bit #(256)     data;
   Bool          sop;
   Bool          eop;
   Bit #(8)      keep;
   TLPFirstDWBE  first_be;
   TLPFirstDWBE  last_be;
} AxiStCq deriving (Bits, Eq);

typedef struct {
   Bit #(256)     data;
   Bit #(8)      keep;
   Bool          last;
} AxiStCc deriving (Bits, Eq);

typedef struct {
   Bit #(256)     data;
   Bool          last;
   Bit #(8)      keep;
   Bit #(4)      first_be;
   Bit #(4)      last_be;
} AxiStRq deriving (Bits, Eq);

typedef struct {
   Bit #(256)     data;
   Bool          sop;
   Bool          eop;
   Bit #(8)      keep;
   Bit #(8)      be;
} AxiStRc deriving (Bits, Eq);

`ifdef BOARD_vc709
typedef 8 PcieLanes;
typedef 8 NumLeds;
`endif
`ifdef BOARD_nfsume
typedef 8 PcieLanes;
typedef 2 NumLeds;
`endif

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

   PCIEParams params = defaultValue;
   Clock defaultClock <- exposeCurrentClock();
   Reset defaultReset <- exposeCurrentReset();
   Reset defaultResetInverted <- mkResetInverter(defaultReset, clocked_by defaultClock);
   PcieWrap#(PcieLanes) pcie_ep <- mkPcieWrap(defaultClock, defaultResetInverted);

   // The PCIe endpoint exports full (250MHz) and half-speed (125MHz) clocks
   Clock pcieClock250 = pcie_ep.user_clk;
   Reset user_reset_n <- mkResetInverter(pcie_ep.user_reset, clocked_by pcie_ep.user_clk);
   Reset pcieReset250 <- mkAsyncReset(4, user_reset_n, pcieClock250);

   ClockGenerator7Params     clkgenParams = defaultValue;
   clkgenParams.clkin1_period    = 4.000; //  250MHz
   clkgenParams.clkin1_period    = 4.000;
   clkgenParams.clkin_buffer     = False;
   clkgenParams.clkfbout_mult_f  = 4.000; // 1000MHz
   clkgenParams.clkout0_divide_f = derivedClockPeriod;
   clkgenParams.clkout1_divide     = round(mainClockPeriod);
   clkgenParams.clkout1_duty_cycle = 0.5;
   clkgenParams.clkout1_phase      = 0.0000;
   ClockGenerator7           clkgen <- mkClockGenerator7(clkgenParams, clocked_by pcieClock250, reset_by pcieReset250);
   Clock mainClock = clkgen.clkout1;
   Reset mainReset <- mkAsyncReset(4, pcieReset250, mainClock);
   Clock derivedClock = clkgen.clkout0;
   Reset derivedReset <- mkAsyncReset(4, pcieReset250, derivedClock);
   Reset user_reset <- mkAsyncReset(2, pcie_ep.user_reset, pcie_ep.user_clk);

   FIFOF#(AxiStCq) fAxiCq <- mkFIFOF(clocked_by pcie_ep.user_clk, reset_by user_reset_n);
   FIFOF#(AxiStRc) fAxiRc <- mkFIFOF(clocked_by pcie_ep.user_clk, reset_by user_reset_n);

   FIFOF#(AxiStRq) fAxiRq <- mkFIFOF(clocked_by pcie_ep.user_clk, reset_by user_reset_n);
   FIFOF#(AxiStCc) fAxiCc <- mkFIFOF(clocked_by pcie_ep.user_clk, reset_by user_reset_n);

   FIFOF#(TLPData#(16)) fcq <- mkFIFOF(clocked_by pcie_ep.user_clk, reset_by user_reset_n);
   FIFOF#(TLPData#(16)) frc <- mkFIFOF(clocked_by pcie_ep.user_clk, reset_by user_reset_n);
   FIFOF#(TLPData#(16)) fcc <- mkFIFOF(clocked_by pcie_ep.user_clk, reset_by user_reset_n);
   FIFOF#(TLPData#(16)) frq <- mkFIFOF(clocked_by pcie_ep.user_clk, reset_by user_reset_n);

   // Drive s_axis_rq
   let rq_txready = (pcie_ep.s_axis_rq.tready != 0 && fAxiRq.notEmpty);

   //(* fire_when_enabled, no_implicit_conditions *)
   rule drive_axi_rq if (rq_txready);
      let info = fAxiRq.first; fAxiRq.deq;
      pcie_ep.s_axis_rq.tvalid(1);
      pcie_ep.s_axis_rq.tlast(pack(info.last));
      pcie_ep.s_axis_rq.tdata(info.data);
      pcie_ep.s_axis_rq.tkeep(info.keep);
      pcie_ep.s_axis_rq.tuser({0, info.last_be, info.first_be});
   endrule

   (* fire_when_enabled, no_implicit_conditions *)
   rule drive_axi_rq2 if (!rq_txready);
      pcie_ep.s_axis_rq.tvalid(0);
      pcie_ep.s_axis_rq.tlast(0);
      pcie_ep.s_axis_rq.tdata(0);
      pcie_ep.s_axis_rq.tkeep(0);
      pcie_ep.s_axis_rq.tuser(0);
   endrule

   // Drive s_axis_cc
   let cc_txready = (pcie_ep.s_axis_cc.tready != 0 && fAxiCc.notEmpty);

   //(* fire_when_enabled, no_implicit_conditions *)
   rule drive_axi_cc if (cc_txready);
      let info = fAxiCc.first; fAxiCc.deq;
      $display("drive axi_cc, data: %h, keep: %h, last: %h", info.data, info.keep, info.last);
      pcie_ep.s_axis_cc.tvalid(1);
      pcie_ep.s_axis_cc.tlast(pack(info.last));
      pcie_ep.s_axis_cc.tdata(info.data);
      pcie_ep.s_axis_cc.tkeep(info.keep);
      pcie_ep.s_axis_cc.tuser(0);
   endrule

   (* fire_when_enabled, no_implicit_conditions *)
   rule drive_axi_cc2 if (!cc_txready);
      pcie_ep.s_axis_cc.tvalid(0);
      pcie_ep.s_axis_cc.tlast(0);
      pcie_ep.s_axis_cc.tdata(0);
      pcie_ep.s_axis_cc.tkeep(0);
      pcie_ep.s_axis_cc.tuser(0);
   endrule

   (* fire_when_enabled, no_implicit_conditions *)
   rule drive_axi_rc_ready;
      pcie_ep.m_axis_rc.tready (duplicate (pack (fAxiRc.notFull)));
   endrule

   // Drive m_axis_rc
   (* fire_when_enabled *)
   rule sink_axi_rc if (pcie_ep.m_axis_rc.tvalid != 0 && fAxiRc.notFull);
      let rc = AxiStRc {data:pcie_ep.m_axis_rc.tdata,
			sop: unpack (pcie_ep.m_axis_rc.tuser [32]),         // tuser.is_sof_0
			eop: unpack (pcie_ep.m_axis_rc.tlast),
			keep:pcie_ep.m_axis_rc.tkeep,
			be:  truncate (pcie_ep.m_axis_rc.tuser [31:0])};    // tuser.byte_en
      fAxiRc.enq (rc);
   endrule

   (* fire_when_enabled, no_implicit_conditions *)
   rule drive_axi_cq_ready;
      pcie_ep.m_axis_cq.tready (duplicate (pack (fAxiCq.notFull)));
   endrule

   (* fire_when_enabled *)
   rule sink_axi_cq if (pcie_ep.m_axis_cq.tvalid != 0 && fAxiCq.notFull);
      let cq = AxiStCq {data:     pcie_ep.m_axis_cq.tdata,
			sop:      unpack (pcie_ep.m_axis_cq.tuser [40]),  // tuser.sop
			eop:      unpack (pcie_ep.m_axis_cq.tlast),
			keep:     pcie_ep.m_axis_cq.tkeep,
			first_be: pcie_ep.m_axis_cq.tuser [3:0],    // tuser.first_be,
			last_be:  pcie_ep.m_axis_cq.tuser [7:4]};   // tuser.last_be
      fAxiCq.enq (cq);
   endrule

   // CQ.
   CQDescriptor cq_desc = unpack(fAxiCq.first.data [127:0]);

   rule rl_cq_wr_header (fAxiCq.first.sop && ((cq_desc.reqtype == MEMORY_WRITE) || (cq_desc.reqtype == IO_WRITE)));
      Bit#(32) data = fAxiCq.first.data[159:128];
      // get data;
      TLPData#(16) tlp16 = convertCQDescriptorToTLP16(cq_desc, data, fAxiCq.first.first_be, fAxiCq.first.last_be);
      $display("cq_desc.reqtype=%h", cq_desc.reqtype);
      // enqueue?
      fcq.enq(tlp16);
      fAxiCq.deq;
   endrule

   // Write data payload, no data remaining
   rule rl_cq_wr_payload((!fAxiCq.first.sop));
      fAxiCq.deq;
   endrule

   // Write data payload, 1 to 3 DWs remaining
   // Write data payload, 4 or more DWs remaining

   rule rl_cq_rd_header (fAxiCq.first.sop && ((cq_desc.reqtype == MEMORY_READ) || (cq_desc.reqtype == IO_READ)));
      Bit#(32) data = 0;
      TLPData#(16) tlp16 = convertCQDescriptorToTLP16(cq_desc, data, fAxiCq.first.first_be, fAxiCq.first.last_be);
      $display("rl_cq_rd_header: cq_desc = %16x", cq_desc);
      fcq.enq(tlp16);
      fAxiCq.deq;
   endrule

   // RC.
   Reg#(DWCount) rg_dwcount <- mkRegU(clocked_by pcie_ep.user_clk, reset_by user_reset_n);

   rule rl_rc_header (fAxiRc.first.sop);
      RCDescriptor rc_desc = unpack(fAxiRc.first.data [95:0]);
      Bit#(32) data = fAxiRc.first.data[128+32-1:128];
      TLPData#(16) tlp16 = convertRCDescriptorToTLP16(rc_desc, data);
      rg_dwcount <= (rc_desc.dwcount == 0) ? 0 : rc_desc.dwcount - 1;
      frc.enq(tlp16);
      fAxiRc.deq;
   endrule

   rule rl_rc_data ((!(fAxiRc.first.sop)) && (rg_dwcount != 0));
      Bit#(16) be16;
      case (rg_dwcount)
         1: be16 = 16'hF000;
         2: be16 = 16'hFF00;
         3: be16 = 16'hFFF0;
         default: be16 = 16'hFFFF;
      endcase
      TLPData#(16) tlp16 = TLPData{sof: False,
                                   eof: (rg_dwcount <= 4),
                                   hit: 0,
                                   be: be16,
                                   data: pack(fAxiRc.first.data[127:0])};
      frc.enq(tlp16);
      fAxiRc.deq;
   endrule

   Reg#(DWCount) cc_dwcount <- mkReg(0, clocked_by pcie_ep.user_clk, reset_by user_reset_n);
   FIFOF#(TLPData#(16)) fcc_tlps <- mkFIFOF (clocked_by pcie_ep.user_clk, reset_by user_reset_n);
   // CC.
   rule get_cc_tlps;
      let tlp <- toGet(fcc).get;
      fcc_tlps.enq(tlp);
   endrule

   rule rl_cc_header(fcc_tlps.first.sof);
      match { .cc_desc, .dw} = convertTLP16ToCCDescriptor(fcc_tlps.first);
      cc_dwcount <= cc_desc.dwcount - 1;
      fAxiCc.enq(AxiStCc {data: zeroExtend({dw, pack(cc_desc)[95:0]}),
                       last: fcc_tlps.first.eof,
                       keep: 8'h0F});
      fcc_tlps.deq;
   endrule

   rule rl_cc_data((!fcc_tlps.first.sof) && (cc_dwcount != 0));
      Bit#(256) x = zeroExtend(fcc_tlps.first.data); //FIXME
      fAxiCc.enq(AxiStCc {data: {x},
                       last: cc_dwcount <= 4,
                       keep: (cc_dwcount == 3) ? 8'h0F : 8'hFF});
      fcc_tlps.deq;
   endrule

   // RQ.
   FIFOF#(TLPData#(16)) frq_tlps <- mkFIFOF (clocked_by pcie_ep.user_clk, reset_by user_reset_n);
   Reg#(DWCount) rq_dwcount <- mkReg(0, clocked_by pcie_ep.user_clk, reset_by user_reset_n);
   Reg#(Maybe#(Bit#(32))) rq_mdw <- mkRegU(clocked_by pcie_ep.user_clk, reset_by user_reset_n);
   Reg#(Bit#(4)) rq_first_be <- mkRegU(clocked_by pcie_ep.user_clk, reset_by user_reset_n);
   Reg#(Bit#(4)) rq_last_be <- mkRegU(clocked_by pcie_ep.user_clk, reset_by user_reset_n);
   rule get_rq_tlps;
      let tlp <- toGet(frq).get;
      frq_tlps.enq(tlp);
   endrule

   rule rl_rq_header(frq_tlps.first.sof);
      match { .rq_desc, .first_be, .last_be, .mdata} = convertTLP16ToRQDescriptor(frq_tlps.first);
      rq_dwcount <= ((rq_desc.reqtype == MEMORY_WRITE) ? rq_desc.dwcount : 0);
      rq_mdw <= mdata;
      rq_first_be <= first_be;
      rq_last_be <= last_be;
      fAxiRq.enq(AxiStRq {data: zeroExtend(pack(rq_desc)), //FIXME:
                       last: frq_tlps.first.eof,
                       keep: 8'hFF,
                       first_be: first_be,
                       last_be: last_be});
      frq_tlps.deq;
   endrule

   // rq_mdw contains last DW
   rule rl_rq_data_a (rq_mdw matches tagged Valid .dw &&& (rq_dwcount == 1));
      rq_dwcount <= 0;
      rq_mdw <= tagged Invalid;
   endrule

   // rq_mdw Valid, and there are more DWs.
   rule rl_rq_data_b(rq_mdw matches tagged Valid .dw &&& (rq_dwcount != 1));

   endrule

   // rq_mdw Invalid, and there are more DWs.
   rule rl_rq_data_c(rq_mdw matches tagged Invalid &&& (rq_dwcount != 1));

   endrule

   // The PCIE endpoint is processing Gen3 descriptors at 250MHz. The
   // AXI bridge is accepting TLPData#(16)s at 250 MHz. The
   // conversion uses half of Gen3 descriptor.
   //mkConnection(tlp8, gb.tlp, clocked_by portalClock, reset_by portalReset);

   let portalClock = (mainClockPeriod == pcieClockPeriod) ? pcieClock250 : mainClock;
   let portalReset = (mainClockPeriod == pcieClockPeriod) ? pcieReset250 : mainReset;

   interface Server tlpr;
      interface request = toPut(frq);
      interface response = toGet(frc);
   endinterface
   // Requests from other PCIe devices
   interface Server tlpc;
      interface request = toPut(fcc);
      interface response = toGet(fcq);
   endinterface
   interface pcie    = pcie_ep.pci_exp;
   interface Pcie3wrapUser user = pcie_ep.user;
   interface PciewrapPipe pipe = pcie_ep.pipe;
   interface PciewrapCommon common= pcie_ep.common;
   interface Clock epPcieClock = pcieClock250;
   interface Reset epPcieReset = pcieReset250;
   interface Clock epPortalClock = portalClock;
   interface Reset epPortalReset = portalReset;
   interface Clock epDerivedClock = derivedClock;
   interface Reset epDerivedReset = derivedReset;
endmodule: mkPcieEndpointX7

endpackage: Pcie3EndpointX7

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

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

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

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

package Pcie3EndpointX7;

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

import ConnectalClocks   ::*;
import ConnectalXilinxCells   ::*;
import XilinxCells       ::*;
import PCIE              ::*;
import PCIEWRAPPER3      ::*;
import Bufgctrl           ::*;
import PcieGearbox       :: *;

interface PcieEndpointX7#(numeric type lanes);
   interface PciewrapPci_exp#(lanes)           pcie;
   interface PciewrapUser#(lanes)              user;
   interface PciewrapPipe#(lanes)              pipe;
   interface PciewrapCommon#(lanes)            common;
   interface Server#(TLPData#(16), TLPData#(16)) tlpr;
   interface Server#(TLPData#(16), TLPData#(16)) tlpc;
   interface Clock epPcieClock;
   interface Reset epPcieReset;
   interface Clock epPortalClock;
   interface Reset epPortalReset;
   interface Clock epDerivedClock;
   interface Reset epDerivedReset;
endinterface

typedef struct {
   Bit #(256)     data;
   Bool          sop;
   Bool          eop;
   Bit #(8)      keep;
   TLPFirstDWBE  first_be;
   TLPFirstDWBE  last_be;
} AxiStCq deriving (Bits, Eq);

typedef struct {
   Bit #(256)     data;
   Bit #(8)      keep;
   Bool          last;
} AxiStCc deriving (Bits, Eq);

typedef struct {
   Bit #(256)     data;
   Bool          last;
   Bit #(8)      keep;
   Bit #(4)      first_be;
   Bit #(4)      last_be;
} AxiStRq deriving (Bits, Eq);

typedef struct {
   Bit #(256)     data;
   Bool          sop;
   Bool          eop;
   Bit #(8)      keep;
   Bit #(8)      be;
} AxiStRc deriving (Bits, Eq);

`ifdef BOARD_vc709
typedef 8 PcieLanes;
typedef 8 NumLeds;
`endif
`ifdef BOARD_nfsume
typedef 8 PcieLanes;
typedef 2 NumLeds;
`endif

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

   PCIEParams params = defaultValue;
   Clock defaultClock <- exposeCurrentClock();
   Reset defaultReset <- exposeCurrentReset();
   Reset defaultResetInverted <- mkResetInverter(defaultReset, clocked_by defaultClock);
   PcieWrap#(PcieLanes) pcie_ep <- mkPcieWrap(defaultClock, defaultResetInverted);

   // The PCIe endpoint exports full (250MHz) and half-speed (125MHz) clocks
   Clock pcieClock250 = pcie_ep.user_clk;
   Reset user_reset_n <- mkResetInverter(pcie_ep.user_reset, clocked_by pcie_ep.user_clk);
   Reset pcieReset250 <- mkAsyncReset(4, user_reset_n, pcieClock250);

   ClockGenerator7Params     clkgenParams = defaultValue;
   clkgenParams.clkin1_period    = 4.000; //  250MHz
   clkgenParams.clkin1_period    = 4.000;
   clkgenParams.clkin_buffer     = False;
   clkgenParams.clkfbout_mult_f  = 4.000; // 1000MHz
   clkgenParams.clkout0_divide_f = derivedClockPeriod;
   clkgenParams.clkout1_divide     = round(mainClockPeriod);
   clkgenParams.clkout1_duty_cycle = 0.5;
   clkgenParams.clkout1_phase      = 0.0000;
   ClockGenerator7           clkgen <- mkClockGenerator7(clkgenParams, clocked_by pcieClock250, reset_by pcieReset250);
   Clock mainClock = clkgen.clkout1;
   Reset mainReset <- mkAsyncReset(4, pcieReset250, mainClock);
   Clock derivedClock = clkgen.clkout0;
   Reset derivedReset <- mkAsyncReset(4, pcieReset250, derivedClock);
   Reset user_reset <- mkAsyncReset(2, pcie_ep.user_reset, pcie_ep.user_clk);

   FIFOF#(AxiStCq) fAxiCq <- mkFIFOF(clocked_by pcie_ep.user_clk, reset_by user_reset_n);
   FIFOF#(AxiStRc) fAxiRc <- mkFIFOF(clocked_by pcie_ep.user_clk, reset_by user_reset_n);

   FIFOF#(AxiStRq) fAxiRq <- mkFIFOF(clocked_by pcie_ep.user_clk, reset_by user_reset_n);
   FIFOF#(AxiStCc) fAxiCc <- mkFIFOF(clocked_by pcie_ep.user_clk, reset_by user_reset_n);

   FIFOF#(TLPData#(16)) fcq <- mkFIFOF(clocked_by pcie_ep.user_clk, reset_by user_reset_n);
   FIFOF#(TLPData#(16)) frc <- mkFIFOF(clocked_by pcie_ep.user_clk, reset_by user_reset_n);
   FIFOF#(TLPData#(16)) fcc <- mkFIFOF(clocked_by pcie_ep.user_clk, reset_by user_reset_n);
   FIFOF#(TLPData#(16)) frq <- mkFIFOF(clocked_by pcie_ep.user_clk, reset_by user_reset_n);

   // Drive s_axis_rq
   let rq_txready = (pcie_ep.s_axis_rq.tready != 0 && fAxiRq.notEmpty);

   //(* fire_when_enabled, no_implicit_conditions *)
   rule drive_axi_rq if (rq_txready);
      let info = fAxiRq.first; fAxiRq.deq;
      pcie_ep.s_axis_rq.tvalid(1);
      pcie_ep.s_axis_rq.tlast(pack(info.last));
      pcie_ep.s_axis_rq.tdata(info.data);
      pcie_ep.s_axis_rq.tkeep(info.keep);
      pcie_ep.s_axis_rq.tuser({0, info.last_be, info.first_be});
   endrule

   (* fire_when_enabled, no_implicit_conditions *)
   rule drive_axi_rq2 if (!rq_txready);
      pcie_ep.s_axis_rq.tvalid(0);
      pcie_ep.s_axis_rq.tlast(0);
      pcie_ep.s_axis_rq.tdata(0);
      pcie_ep.s_axis_rq.tkeep(0);
      pcie_ep.s_axis_rq.tuser(0);
   endrule

   // Drive s_axis_cc
   let cc_txready = (pcie_ep.s_axis_cc.tready != 0 && fAxiCc.notEmpty);

   //(* fire_when_enabled, no_implicit_conditions *)
   rule drive_axi_cc if (cc_txready);
      let info = fAxiCc.first; fAxiCc.deq;
      $display("drive axi_cc, data: %h, keep: %h, last: %h", info.data, info.keep, info.last);
      pcie_ep.s_axis_cc.tvalid(1);
      pcie_ep.s_axis_cc.tlast(pack(info.last));
      pcie_ep.s_axis_cc.tdata(info.data);
      pcie_ep.s_axis_cc.tkeep(info.keep);
      pcie_ep.s_axis_cc.tuser(0);
   endrule

   (* fire_when_enabled, no_implicit_conditions *)
   rule drive_axi_cc2 if (!cc_txready);
      pcie_ep.s_axis_cc.tvalid(0);
      pcie_ep.s_axis_cc.tlast(0);
      pcie_ep.s_axis_cc.tdata(0);
      pcie_ep.s_axis_cc.tkeep(0);
      pcie_ep.s_axis_cc.tuser(0);
   endrule

   (* fire_when_enabled, no_implicit_conditions *)
   rule drive_axi_rc_ready;
      pcie_ep.m_axis_rc.tready (duplicate (pack (fAxiRc.notFull)));
   endrule

   // Drive m_axis_rc
   (* fire_when_enabled *)
   rule sink_axi_rc if (pcie_ep.m_axis_rc.tvalid != 0 && fAxiRc.notFull);
      let rc = AxiStRc {data:pcie_ep.m_axis_rc.tdata,
			sop: unpack (pcie_ep.m_axis_rc.tuser [32]),         // tuser.is_sof_0
			eop: unpack (pcie_ep.m_axis_rc.tlast),
			keep:pcie_ep.m_axis_rc.tkeep,
			be:  truncate (pcie_ep.m_axis_rc.tuser [31:0])};    // tuser.byte_en
      fAxiRc.enq (rc);
   endrule

   (* fire_when_enabled, no_implicit_conditions *)
   rule drive_axi_cq_ready;
      pcie_ep.m_axis_cq.tready (duplicate (pack (fAxiCq.notFull)));
   endrule

   (* fire_when_enabled *)
   rule sink_axi_cq if (pcie_ep.m_axis_cq.tvalid != 0 && fAxiCq.notFull);
      let cq = AxiStCq {data:     pcie_ep.m_axis_cq.tdata,
			sop:      unpack (pcie_ep.m_axis_cq.tuser [40]),  // tuser.sop
			eop:      unpack (pcie_ep.m_axis_cq.tlast),
			keep:     pcie_ep.m_axis_cq.tkeep,
			first_be: pcie_ep.m_axis_cq.tuser [3:0],    // tuser.first_be,
			last_be:  pcie_ep.m_axis_cq.tuser [7:4]};   // tuser.last_be
      fAxiCq.enq (cq);
   endrule

   // CQ.
   CQDescriptor cq_desc = unpack(fAxiCq.first.data [127:0]);

   rule rl_cq_wr_header (fAxiCq.first.sop && ((cq_desc.reqtype == MEMORY_WRITE) || (cq_desc.reqtype == IO_WRITE)));
      Bit#(32) data = fAxiCq.first.data[159:128];
      // get data;
      TLPData#(16) tlp16 = convertCQDescriptorToTLP16(cq_desc, data, fAxiCq.first.first_be, fAxiCq.first.last_be);
      $display("cq_desc.reqtype=%h", cq_desc.reqtype);
      // enqueue?
      fcq.enq(tlp16);
      fAxiCq.deq;
   endrule

   // Write data payload, no data remaining
   rule rl_cq_wr_payload((!fAxiCq.first.sop));
      fAxiCq.deq;
   endrule

   // Write data payload, 1 to 3 DWs remaining
   // Write data payload, 4 or more DWs remaining

   rule rl_cq_rd_header (fAxiCq.first.sop && ((cq_desc.reqtype == MEMORY_READ) || (cq_desc.reqtype == IO_READ)));
      Bit#(32) data = 0;
      TLPData#(16) tlp16 = convertCQDescriptorToTLP16(cq_desc, data, fAxiCq.first.first_be, fAxiCq.first.last_be);
      $display("rl_cq_rd_header: cq_desc = %16x", cq_desc);
      fcq.enq(tlp16);
      fAxiCq.deq;
   endrule

   // RC.
   Reg#(DWCount) rg_dwcount <- mkRegU(clocked_by pcie_ep.user_clk, reset_by user_reset_n);

   rule rl_rc_header (fAxiRc.first.sop);
      RCDescriptor rc_desc = unpack(fAxiRc.first.data [95:0]);
      Bit#(32) data = fAxiRc.first.data[128+32-1:128];
      TLPData#(16) tlp16 = convertRCDescriptorToTLP16(rc_desc, data);
      rg_dwcount <= (rc_desc.dwcount == 0) ? 0 : rc_desc.dwcount - 1;
      frc.enq(tlp16);
      fAxiRc.deq;
   endrule

   rule rl_rc_data ((!(fAxiRc.first.sop)) && (rg_dwcount != 0));
      Bit#(16) be16;
      case (rg_dwcount)
         1: be16 = 16'hF000;
         2: be16 = 16'hFF00;
         3: be16 = 16'hFFF0;
         default: be16 = 16'hFFFF;
      endcase
      TLPData#(16) tlp16 = TLPData{sof: False,
                                   eof: (rg_dwcount <= 4),
                                   hit: 0,
                                   be: be16,
                                   data: pack(fAxiRc.first.data[127:0])};
      frc.enq(tlp16);
      fAxiRc.deq;
   endrule

   Reg#(DWCount) cc_dwcount <- mkReg(0, clocked_by pcie_ep.user_clk, reset_by user_reset_n);
   FIFOF#(TLPData#(16)) fcc_tlps <- mkPipelineFIFOF (clocked_by pcie_ep.user_clk, reset_by user_reset_n);
   // CC.
   rule get_cc_tlps;
      let tlp <- toGet(fcc).get;
      fcc_tlps.enq(tlp);
   endrule

   rule rl_cc_header(fcc_tlps.first.sof);
      match { .cc_desc, .dw} = convertTLP16ToCCDescriptor(fcc_tlps.first);
      cc_dwcount <= cc_desc.dwcount - 1;
      fAxiCc.enq(AxiStCc {data: zeroExtend({dw, pack(cc_desc)[95:0]}),
                       last: fcc_tlps.first.eof,
                       keep: 8'h0F});
      fcc_tlps.deq;
   endrule

   rule rl_cc_data((!fcc_tlps.first.sof) && (cc_dwcount != 0));
      Bit#(256) x = zeroExtend(fcc_tlps.first.data); //FIXME
      fAxiCc.enq(AxiStCc {data: {x},
                       last: cc_dwcount <= 4,
                       keep: (cc_dwcount == 3) ? 8'h0F : 8'hFF});
      fcc_tlps.deq;
   endrule

   // RQ.
   FIFOF#(TLPData#(16)) frq_tlps <- mkPipelineFIFOF (clocked_by pcie_ep.user_clk, reset_by user_reset_n);
   Reg#(DWCount) rq_dwcount <- mkReg(0, clocked_by pcie_ep.user_clk, reset_by user_reset_n);
   Reg#(Maybe#(Bit#(32))) rq_mdw <- mkRegU(clocked_by pcie_ep.user_clk, reset_by user_reset_n);
   Reg#(Bit#(4)) rq_first_be <- mkRegU(clocked_by pcie_ep.user_clk, reset_by user_reset_n);
   Reg#(Bit#(4)) rq_last_be <- mkRegU(clocked_by pcie_ep.user_clk, reset_by user_reset_n);
   rule get_rq_tlps;
      let tlp <- toGet(frq).get;
      frq_tlps.enq(tlp);
   endrule

   rule rl_rq_header(frq_tlps.first.sof);
      match { .rq_desc, .first_be, .last_be, .mdata} = convertTLP16ToRQDescriptor(frq_tlps.first);
      rq_dwcount <= ((rq_desc.reqtype == MEMORY_WRITE) ? rq_desc.dwcount : 0);
      rq_mdw <= mdata;
      rq_first_be <= first_be;
      rq_last_be <= last_be;
      fAxiRq.enq(AxiStRq {data: zeroExtend(pack(rq_desc)), //FIXME:
                       last: frq_tlps.first.eof,
                       keep: 8'hFF,
                       first_be: first_be,
                       last_be: last_be});
      frq_tlps.deq;
   endrule

   // rq_mdw contains last DW
   rule rl_rq_data_a (rq_mdw matches tagged Valid .dw &&& (rq_dwcount == 1));
      rq_dwcount <= 0;
      rq_mdw <= tagged Invalid;
   endrule

   // rq_mdw Valid, and there are more DWs.
   rule rl_rq_data_b(rq_mdw matches tagged Valid .dw &&& (rq_dwcount != 1));

   endrule

   // rq_mdw Invalid, and there are more DWs.
   rule rl_rq_data_c(rq_mdw matches tagged Invalid &&& (rq_dwcount != 1));

   endrule

   // The PCIE endpoint is processing Gen3 descriptors at 250MHz. The
   // AXI bridge is accepting TLPData#(16)s at 250 MHz. The
   // conversion uses half of Gen3 descriptor.
   //mkConnection(tlp8, gb.tlp, clocked_by portalClock, reset_by portalReset);

   let portalClock = (mainClockPeriod == pcieClockPeriod) ? pcieClock250 : mainClock;
   let portalReset = (mainClockPeriod == pcieClockPeriod) ? pcieReset250 : mainReset;

   interface Server tlpr;
      interface request = toPut(frq);
      interface response = toGet(frc);
   endinterface
   // Requests from other PCIe devices
   interface Server tlpc;
      interface request = toPut(fcc);
      interface response = toGet(fcq);
   endinterface
   interface pcie    = pcie_ep.pci_exp;
   interface Pcie3wrapUser user = pcie_ep.user;
   interface PciewrapPipe pipe = pcie_ep.pipe;
   interface PciewrapCommon common= pcie_ep.common;
   interface Clock epPcieClock = pcieClock250;
   interface Reset epPcieReset = pcieReset250;
   interface Clock epPortalClock = portalClock;
   interface Reset epPortalReset = portalReset;
   interface Clock epDerivedClock = derivedClock;
   interface Reset epDerivedReset = derivedReset;
endmodule: mkPcieEndpointX7

endpackage: Pcie3EndpointX7


first pass at complete Algorithm C

first pass at complete Algorithm C

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

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

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

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

import StmtFSM::*;
import BRAM::*;
import MCSAlgorithm::*;

/* frame arguments */
typedef struct {
   Bit#(7) aStart;
   Bit#(7) bStart;
   Bit#(7) aLen;
   Bit#(7) bLen;
   } CArgs deriving(Bits);

typedef struct {
   Bit#(7) midi;
   Bit#(7) maxj;
   } CVars deriving(Bits);

typedef enum {HCSIdle, HCS1, HCS2, HCSComplete} HCState deriving (Bits, Eq);

module mkHirschC#(BRAMServer#(Bit#(strIndexWidth), Bit#(8)) strA, BRAMServer#(Bit#(strIndexWidth), Bit#(8)) strB, BRAMServer#(Bit#(lIndexWidth), Bit#(16)) matL, MCSAlgorithm chirschB0, chirschB1, BRAMServer#(Bit#(lIndexWidth)) l0, BRAMServer#(lIndexWidth)) l1)(MCSAlgorithm)
         provisos(Add#(0, 7, strIndexWidth),
	       Add#(0, 14, lIndexWidth));

      /* pc, args, vars */
   StackReg#(128, FSState, CArgs, CVars) fr <- mkStackReg(128, HCSIDLE);

   Reg#(Bit#(7)) aStartReg <- mkReg(0);
   Reg#(Bit#(7)) bStartReg <- mkReg(0);
   Reg#(Bit#(14)) rStartReg <- mkReg(0);
   Reg#(Bit#(7)) aLenReg <- mkReg(0);
   Reg#(Bit#(7)) bLenReg <- mkReg(0);
   Reg#(Bit#(7)) ii <- mkReg(0);
   Reg#(Bit#(7)) jj <- mkReg(0);
   Reg#(Bit#(8)) aData <- mkReg(0);
   Reg#(Bit#(8)) bData <- mkReg(0);
   Reg#(Bit#(16)) k1j <- mkReg(0);
   Reg#(Bit#(16)) k1jm1 <- mkReg(0);
   Reg#(Bit#(16)) k0j <- mkReg(0);
   Reg#(Bit#(16)) k0jm1 <- mkReg(0);
   BRAM1Port#(Bit#(lIndexWidth), Bit#(16)) k0  <- mkBRAM1Server(defaultValue);

/*
 * HirschC(Astart, Alen, Bstart, Blen, output fifo)
 * implicit A storage, B storage
 *
 */

  // This FSM searches string B looking for the first char of string A
  Stmt hirschC2stmt =
   seq
      $display("hirschC running ");
      // read A[0]
      strA.request.put(BRAMRequest{write: False, responseOnWrite: False, address: fr.args.aStart, datain: ?});
      action
	 let tmp <- strA.response.get();
	 aData <= tmp;
      endaction
      // scan for it in B
      for (jj <= 0; jj < fr.args.bLen; jj <= jj + 1)
	 seq
	    strB.request.put(BRAMRequest{write: False, responseOnWrite: False, address: bstart + jj, datain: ?});
	    action
	       let tmp <- strB.response.get();
	       bData <= tmp;
	    endaction
	    if (aData == bData)
	       seq
		  out.put(aData);
		  break;
	       endseq
	 endseq
      fr.nextpc(HCSComplete);
   endseq;

   FSM hC2fsm <- mkFSM(hirschC2Stmt);

   // AlgC step 1, 2, and 3
   rule hc1 (fr.pc == HCS1)
      if (fr.args.bLen == 0)
	doreturn();
     else if (fr.args.aLen == 1)
	begin
	   hc2fsm.start()
	   fr.nextpc(HCS2);
	end
     else
	action
	   let midi = fr.aLen >> 1;
	   fr.vars.midi <= midi;
	   chirschB0.setupA(fr.args.aStart, midi);
	   chirschB0.setupB(fr.args.bStart, fr.args.bLen);
	   chirschB1.setupA(fr.args.aStart+midi, fr.args.aLen - midi);
	   chirschB1.setupB(fr.args.bStart, fr.args.bLen);
	   chirschB0.start();
	   chirschB1.start();
	   fr.nextPC(HCS3);
	endaction
   endrule

   // This FSM searches the results of the two calls to HirschB
   Stmt hirschC4Stmt =
   seq
      maxjvalue <= 0;
      for (jj <= 0; jj <= fr.args.bLen; jj <= jj + 1)
	 seq
	    l0.request.put(BRAMRequest{write: False, responseOnWrite: False, address: jj, datain: ?});
	    l1.request.put(BRAMRequest{write: False, responseOnWrite: False, address: fr.args.bLen - jj, datain: ?});
	    action
	       let t1 <- lo.response.get();
	       let t2 <- l1.response.get();
	       if ((t1 + t2) > maxjvalue)
		  action
		     maxjvalue <= t1 + t2;
		     fr.vars.maxj <= jj;
		  endaction
	    endaction
	 endseq

      fr.docall(HCS1, HCS5, {startA: fr.args.startA, lenA: fr.vars.midi, startB: fr.args.startB, lenB: fr.vars.maxj});
   endseq

   FSM hc4fsm <- mkFSM(hirschC4Stmt);

   rule hc3 (fr.pc == HCS3 && chirschB0.done() && chirschB1.done);
      hc4fsm.start();
      fr.nextPC(HCS4);
   endrule

   rule hc5 (fr.pc == HCS5);
      fr.docall(HCS1, HCS6, {startA: 0, lenA: maxj, startB: 0, lenB: fr.args.bLen});
   endrule

   rule hc6 (fr.pc == HCS6);
      fr.doreturn();
   endrule

   method Action setupA(Bit#(7) start, Bit#(7) length);
      aStartReg <= start;
      aLenReg <= length;
   endmethod

   method Action setupB(Bit#(7) start, Bit#(7) length);
      bStartReg <= start;
      bLenReg <= length;
   endmethod

   method Action setupL(Bit#(14) start);
      rStartReg <= start;
   endmethod

   interface FSM fsm = hC;

endmodule

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

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

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

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

import StmtFSM::*;
import BRAM::*;
import MCSAlgorithm::*;

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

   Reg#(Bit#(7)) aStartReg <- mkReg(0);
   Reg#(Bit#(7)) bStartReg <- mkReg(0);
   Reg#(Bit#(14)) rStartReg <- mkReg(0);
   Reg#(Bit#(7)) aLenReg <- mkReg(0);
   Reg#(Bit#(7)) bLenReg <- mkReg(0);
   Reg#(Bit#(7)) ii <- mkReg(0);
   Reg#(Bit#(7)) jj <- mkReg(0);
   Reg#(Bit#(8)) aData <- mkReg(0);
   Reg#(Bit#(8)) bData <- mkReg(0);
   Reg#(Bit#(16)) k1j <- mkReg(0);
   Reg#(Bit#(16)) k1jm1 <- mkReg(0);
   Reg#(Bit#(16)) k0j <- mkReg(0);
   Reg#(Bit#(16)) k0jm1 <- mkReg(0);
   BRAM1Port#(Bit#(lIndexWidth), Bit#(16)) k0  <- mkBRAM1Server(defaultValue);

/*
 * HirschC(Astart, Alen, Bstart, Blen, output fifo)
 * implicit A storage, B storage
 *
 */
  Stmt hirschC =
   seq
      $display("hirschC running ");

   endseq;

   FSM hC <- mkFSM(hirschC);

   method Action setupA(Bit#(7) start, Bit#(7) length);
      aStartReg <= start;
      aLenReg <= length;
   endmethod

   method Action setupB(Bit#(7) start, Bit#(7) length);
      bStartReg <= start;
      bLenReg <= length;
   endmethod

   method Action setupL(Bit#(14) start);
      rStartReg <= start;
   endmethod

   interface FSM fsm = hC;

endmodule


change memcpy to perf

change memcpy to perf

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

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

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

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

import Vector::*;
import FIFOF::*;
import GetPutF::*;

import PortalMemory::*;
import Dma::*;

interface PerfRequest;
   method Action startCopy(Bit#(32) wrPointer, Bit#(32) rdPointer, Bit#(32) numWords);
   method Action readWord();
   method Action getStateDbg();
endinterface

interface PerfIndication;
   method Action started(Bit#(32) numWords);
   method Action readWordResult(Bit#(32) v);
   method Action done(Bit#(32) dataMismatch);
   method Action rData(Bit#(64) v);
   method Action readReq(Bit#(32) v);
   method Action writeReq(Bit#(32) v);
   method Action writeAck(Bit#(32) v);
   method Action reportStateDbg(Bit#(32) srcGen, Bit#(32) streamRdCnt, Bit#(32) streamWrCnt, Bit#(32) writeInProg, Bit#(32) dataMismatch);
endinterface

module mkPerfRequest#(PerfIndication indication,
			DmaReadServer#(busWidth) dma_stream_read_server,
			DmaWriteServer#(busWidth) dma_stream_write_server,
			DmaReadServer#(busWidth) dma_word_read_server)
   (PerfRequest)
   provisos (Div#(busWidth,8,busWidthBytes),
	     Add#(a__,32,busWidth));

   let busWidthBytes = valueOf(busWidthBytes);
   let busWidthWords = busWidthBytes/4;

   Reg#(Bit#(32))      srcGen <- mkReg(0);
   Reg#(Bit#(32)) streamRdCnt <- mkReg(0);
   Reg#(Bit#(32)) streamWrCnt <- mkReg(0);
   Reg#(Bit#(32)) streamAckCnt <- mkReg(0);
   Reg#(Bit#(DmaOffsetSize)) streamRdOff <- mkReg(0);
   Reg#(Bit#(DmaOffsetSize)) streamWrOff <- mkReg(0);
   Reg#(DmaPointer)    streamRdPointer <- mkReg(0);
   Reg#(DmaPointer)    streamWrPointer <- mkReg(0);
   Reg#(Bool)               writeInProg <- mkReg(False);
   Reg#(Bool)              dataMismatch <- mkReg(False);

   Reg#(Bit#(8)) burstLen <- mkReg(8);
   Reg#(Bit#(DmaOffsetSize)) deltaOffset <- mkReg(8*fromInteger(busWidthBytes));

   rule readReq(streamRdCnt > 0);
      streamRdCnt <= streamRdCnt - extend(burstLen);
      streamRdOff <= streamRdOff + deltaOffset;
      //$display("readReq.put pointer=%h address=%h, burstlen=%h", streamRdPointer, streamRdOff, burstLen);
      dma_stream_read_server.readReq.put(DmaRequest {pointer: streamRdPointer, offset: streamRdOff, burstLen: extend(burstLen), tag: truncate(streamRdOff>>5)});
      //indication.readReq(streamRdCnt);
   endrule

   rule writeReq(streamWrCnt > 0 && !writeInProg);
      writeInProg <= True;
      streamWrCnt <= streamWrCnt-extend(burstLen);
      streamWrOff <= streamWrOff + deltaOffset;
      //$display("writeReq.put pointer=%h address=%h", streamWrPointer, streamWrOff);
      dma_stream_write_server.writeReq.put(DmaRequest {pointer: streamWrPointer, offset: streamWrOff, burstLen: extend(burstLen), tag: truncate(streamWrOff>>5)});
      //indication.writeReq(streamWrCnt);
   endrule

   rule writeAck(writeInProg);
      writeInProg <= False;
      let tag <- dma_stream_write_server.writeDone.get();
      //$display("writeAck: tag=%d", tag);
      streamAckCnt <= streamAckCnt-extend(burstLen);
      //indication.writeAck(streamAckCnt);
      if(streamAckCnt==extend(burstLen))
   	 indication.done(dataMismatch ? 32'd1 : 32'd0);
   endrule

   rule loopback;
      let tagdata <- dma_stream_read_server.readData.get();
      let v = tagdata.data;
      Bool mismatch = False;
      for (Integer i = 0; i < busWidthWords; i = i+1)
	 mismatch = mismatch || (v[31+i*32:i*32] != (srcGen + fromInteger(i)));
      dataMismatch <= dataMismatch || mismatch;
      dma_stream_write_server.writeData.put(tagdata);
      bs.dataIn(v,v);
      srcGen <= srcGen+fromInteger(busWidthWords);
      //$display("loopback %h", tagdata.data);
      // indication.rData(v);
   endrule

   rule readWordResp;
      let tagdata <- dma_word_read_server.readData.get;
      indication.readWordResult(truncate(tagdata.data));
   endrule

   method Action startCopy(Bit#(32) wrPointer, Bit#(32) rdPointer, Bit#(32) numWords) if (streamRdCnt == 0 && streamWrCnt == 0);
      //$display("startCopy wrPointer=%h rdPointer=%h numWords=%d", wrPointer, rdPointer, numWords);
      streamRdOff <= 0;
      streamWrOff <= 0;

      streamWrPointer <= wrPointer;
      streamRdPointer <= rdPointer;
      streamRdCnt <= numWords>>1;
      streamWrCnt <= numWords>>1;
      streamAckCnt <= numWords>>1;
      indication.started(numWords);
   endmethod

   method Action readWord();
      dma_word_read_server.readReq.put(DmaRequest {pointer: streamWrPointer, offset: 0, burstLen: 1, tag: 1});
   endmethod

   method Action getStateDbg();
      indication.reportStateDbg(srcGen, streamRdCnt, streamWrCnt, writeInProg ? 32'd1 : 32'd0, dataMismatch  ? 32'd1 : 32'd0);
   endmethod

endmodule

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

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

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

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

import Vector::*;
import FIFOF::*;
import GetPutF::*;

import PortalMemory::*;
import Dma::*;

interface MemcpyRequest;
   method Action startCopy(Bit#(32) wrPointer, Bit#(32) rdPointer, Bit#(32) numWords);
   method Action readWord();
   method Action getStateDbg();
endinterface

interface MemcpyIndication;
   method Action started(Bit#(32) numWords);
   method Action readWordResult(Bit#(32) v);
   method Action done(Bit#(32) dataMismatch);
   method Action rData(Bit#(64) v);
   method Action readReq(Bit#(32) v);
   method Action writeReq(Bit#(32) v);
   method Action writeAck(Bit#(32) v);
   method Action reportStateDbg(Bit#(32) srcGen, Bit#(32) streamRdCnt, Bit#(32) streamWrCnt, Bit#(32) writeInProg, Bit#(32) dataMismatch);
endinterface

module mkMemcpyRequest#(MemcpyIndication indication,
			DmaReadServer#(busWidth) dma_stream_read_server,
			DmaWriteServer#(busWidth) dma_stream_write_server,
			DmaReadServer#(busWidth) dma_word_read_server)
   (MemcpyRequest)
   provisos (Div#(busWidth,8,busWidthBytes),
	     Add#(a__,32,busWidth));

   let busWidthBytes = valueOf(busWidthBytes);
   let busWidthWords = busWidthBytes/4;

   Reg#(Bit#(32))      srcGen <- mkReg(0);
   Reg#(Bit#(32)) streamRdCnt <- mkReg(0);
   Reg#(Bit#(32)) streamWrCnt <- mkReg(0);
   Reg#(Bit#(32)) streamAckCnt <- mkReg(0);
   Reg#(Bit#(DmaOffsetSize)) streamRdOff <- mkReg(0);
   Reg#(Bit#(DmaOffsetSize)) streamWrOff <- mkReg(0);
   Reg#(DmaPointer)    streamRdPointer <- mkReg(0);
   Reg#(DmaPointer)    streamWrPointer <- mkReg(0);
   Reg#(Bool)               writeInProg <- mkReg(False);
   Reg#(Bool)              dataMismatch <- mkReg(False);

   Reg#(Bit#(8)) burstLen <- mkReg(8);
   Reg#(Bit#(DmaOffsetSize)) deltaOffset <- mkReg(8*fromInteger(busWidthBytes));

   rule readReq(streamRdCnt > 0);
      streamRdCnt <= streamRdCnt - extend(burstLen);
      streamRdOff <= streamRdOff + deltaOffset;
      //$display("readReq.put pointer=%h address=%h, burstlen=%h", streamRdPointer, streamRdOff, burstLen);
      dma_stream_read_server.readReq.put(DmaRequest {pointer: streamRdPointer, offset: streamRdOff, burstLen: extend(burstLen), tag: truncate(streamRdOff>>5)});
      //indication.readReq(streamRdCnt);
   endrule

   rule writeReq(streamWrCnt > 0 && !writeInProg);
      writeInProg <= True;
      streamWrCnt <= streamWrCnt-extend(burstLen);
      streamWrOff <= streamWrOff + deltaOffset;
      //$display("writeReq.put pointer=%h address=%h", streamWrPointer, streamWrOff);
      dma_stream_write_server.writeReq.put(DmaRequest {pointer: streamWrPointer, offset: streamWrOff, burstLen: extend(burstLen), tag: truncate(streamWrOff>>5)});
      //indication.writeReq(streamWrCnt);
   endrule

   rule writeAck(writeInProg);
      writeInProg <= False;
      let tag <- dma_stream_write_server.writeDone.get();
      //$display("writeAck: tag=%d", tag);
      streamAckCnt <= streamAckCnt-extend(burstLen);
      //indication.writeAck(streamAckCnt);
      if(streamAckCnt==extend(burstLen))
   	 indication.done(dataMismatch ? 32'd1 : 32'd0);
   endrule

   rule loopback;
      let tagdata <- dma_stream_read_server.readData.get();
      let v = tagdata.data;
      Bool mismatch = False;
      for (Integer i = 0; i < busWidthWords; i = i+1)
	 mismatch = mismatch || (v[31+i*32:i*32] != (srcGen + fromInteger(i)));
      dataMismatch <= dataMismatch || mismatch;
      dma_stream_write_server.writeData.put(tagdata);
      bs.dataIn(v,v);
      srcGen <= srcGen+fromInteger(busWidthWords);
      //$display("loopback %h", tagdata.data);
      // indication.rData(v);
   endrule

   rule readWordResp;
      let tagdata <- dma_word_read_server.readData.get;
      indication.readWordResult(truncate(tagdata.data));
   endrule

   method Action startCopy(Bit#(32) wrPointer, Bit#(32) rdPointer, Bit#(32) numWords) if (streamRdCnt == 0 && streamWrCnt == 0);
      //$display("startCopy wrPointer=%h rdPointer=%h numWords=%d", wrPointer, rdPointer, numWords);
      streamRdOff <= 0;
      streamWrOff <= 0;

      streamWrPointer <= wrPointer;
      streamRdPointer <= rdPointer;
      streamRdCnt <= numWords>>1;
      streamWrCnt <= numWords>>1;
      streamAckCnt <= numWords>>1;
      indication.started(numWords);
   endmethod

   method Action readWord();
      dma_word_read_server.readReq.put(DmaRequest {pointer: streamWrPointer, offset: 0, burstLen: 1, tag: 1});
   endmethod

   method Action getStateDbg();
      indication.reportStateDbg(srcGen, streamRdCnt, streamWrCnt, writeInProg ? 32'd1 : 32'd0, dataMismatch  ? 32'd1 : 32'd0);
   endmethod

endmodule


silence $display

silence $display

import GetPut::*;
import FIFOF::*;
import Pipe::*;

interface SerialRequest;
   method Action tx(Bit#(8) c);
endinterface

interface SerialIndication;
   method Action rx(Bit#(8) c);
endinterface

interface SerialPort;
   interface PipeOut#(Bit#(8)) out;
   interface PipeIn#(Bit#(8)) in;
endinterface
interface Serial;
   interface SerialRequest request;
   interface SerialPort port;
endinterface

module mkSerial#(SerialIndication indication)(Serial);
   FIFOF#(Bit#(8)) infifo <- mkSizedFIFOF(16);
   FIFOF#(Bit#(8)) outfifo <- mkSizedFIFOF(16);
   rule rl_in;
      let ch <- toGet(infifo).get();
      indication.rx(ch);
   endrule
   interface SerialRequest request;
      method Action tx(Bit#(8) c);
	 //$display("%h", c);
	 outfifo.enq(c);
      endmethod
   endinterface
   interface SerialPort port;
      interface PipeOut out = toPipeOut(outfifo);
      interface PipeIn  in  = toPipeIn(infifo);
   endinterface
endmodule

import GetPut::*;
import FIFOF::*;
import Pipe::*;

interface SerialRequest;
   method Action tx(Bit#(8) c);
endinterface

interface SerialIndication;
   method Action rx(Bit#(8) c);
endinterface

interface SerialPort;
   interface PipeOut#(Bit#(8)) out;
   interface PipeIn#(Bit#(8)) in;
endinterface
interface Serial;
   interface SerialRequest request;
   interface SerialPort port;
endinterface

module mkSerial#(SerialIndication indication)(Serial);
   FIFOF#(Bit#(8)) infifo <- mkSizedFIFOF(16);
   FIFOF#(Bit#(8)) outfifo <- mkSizedFIFOF(16);
   rule rl_in;
      let ch <- toGet(infifo).get();
      indication.rx(ch);
   endrule
   interface SerialRequest request;
      method Action tx(Bit#(8) c);
	 $display("%h", c);
	 outfifo.enq(c);
      endmethod
   endinterface
   interface SerialPort port;
      interface PipeOut out = toPipeOut(outfifo);
      interface PipeIn  in  = toPipeIn(infifo);
   endinterface
endmodule


added instances of mkConnectionWithClocks for PhysMemMaster and PhysMemSlave

// Copyright (c) 2013,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 GetPut :: *;
import ClientServer :: *;
import Clocks :: *;
import MemTypes :: *;

////////////////////////////////////////////////////////////////////////////////
/// Typeclass Definition
////////////////////////////////////////////////////////////////////////////////
typeclass ConnectableWithClocks#(type a, type b);
   module mkConnectionWithClocks#(a x1, b x2, Clock fastClock, Reset fastReset, Clock slowClock, Reset slowReset)(Empty);
endtypeclass

instance ConnectableWithClocks#(Get#(a), Put#(a)) provisos (Bits#(a, awidth));
   module mkConnectionWithClocks#(Get#(a) in, Put#(a) out,
                                  Clock inClock, Reset inReset,
                                  Clock outClock, Reset outReset)(Empty) provisos (Bits#(a, awidth));
       SyncFIFOIfc#(a) synchronizer <- mkSyncFIFO(1, inClock, inReset, outClock);
       rule doGet;
           let v <- in.get();
	   synchronizer.enq(v);
       endrule
       rule doPut;
           let v = synchronizer.first;
	   synchronizer.deq;
	   out.put(v);
       endrule
   endmodule: mkConnectionWithClocks
endinstance: ConnectableWithClocks

instance ConnectableWithClocks#(Client#(a,b), Server#(a,b)) provisos (Bits#(a, awidth), Bits#(b, bwidth));
   module mkConnectionWithClocks#(Client#(a,b) client, Server#(a,b) server,
                                  Clock sourceClock, Reset sourceReset,
                                  Clock destClock, Reset destReset)(Empty)
      provisos (ConnectableWithClocks#(Get#(a), Put#(a)),
		ConnectableWithClocks#(Get#(b), Put#(b)),
		Bits#(a, awidth),
		Bits#(b, bwidth));
      mkConnectionWithClocks(client.request, server.request, sourceClock, sourceReset, destClock, destReset);
      mkConnectionWithClocks(server.response, client.response, destClock, destReset, sourceClock, sourceReset);
   endmodule
endinstance

instance ConnectableWithClocks#(PhysMemReadClient#(addrWidth, dataWidth),
				PhysMemReadServer#(addrWidth, dataWidth));
   module mkConnectionWithClocks#(PhysMemReadClient#(addrWidth, dataWidth) client,
				  PhysMemReadServer#(addrWidth, dataWidth) server,
                                  Clock sourceClock, Reset sourceReset,
				  Clock destClock, Reset destReset)(Empty);
      mkConnectionWithClocks(client.readReq, server.readReq, sourceClock, sourceReset, destClock, destReset);
      mkConnectionWithClocks(server.readData, client.readData, destClock, destReset, sourceClock, sourceReset);
   endmodule
endinstance

instance ConnectableWithClocks#(PhysMemWriteClient#(addrWidth, dataWidth),
				PhysMemWriteServer#(addrWidth, dataWidth));
   module mkConnectionWithClocks#(PhysMemWriteClient#(addrWidth, dataWidth) client,
				  PhysMemWriteServer#(addrWidth, dataWidth) server,
                                  Clock sourceClock, Reset sourceReset,
				  Clock destClock, Reset destReset)(Empty);
      mkConnectionWithClocks(client.writeReq, server.writeReq, destClock, destReset, sourceClock, sourceReset);
      mkConnectionWithClocks(client.writeData, server.writeData, destClock, destReset, sourceClock, sourceReset);
      mkConnectionWithClocks(server.writeDone, client.writeDone, sourceClock, sourceReset, destClock, destReset);
   endmodule
endinstance

instance ConnectableWithClocks#(PhysMemMaster#(addrWidth, dataWidth), PhysMemSlave#(addrWidth, dataWidth));
   module mkConnectionWithClocks#(PhysMemMaster#(addrWidth, dataWidth) client,
				  PhysMemSlave#(addrWidth, dataWidth) server,
                                  Clock sourceClock, Reset sourceReset,
				  Clock destClock, Reset destReset)(Empty);
      mkConnectionWithClocks(client.read_client, server.read_server, sourceClock, sourceReset, destClock, destReset);
      mkConnectionWithClocks(client.write_client, server.write_server, destClock, destReset, sourceClock, sourceReset);
   endmodule
endinstance

module mkClockBinder#(a ifc) (a);
   return ifc;
endmodule

// Copyright (c) 2013,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 GetPut :: *;
import ClientServer :: *;
import Clocks :: *;

////////////////////////////////////////////////////////////////////////////////
/// Typeclass Definition
////////////////////////////////////////////////////////////////////////////////
typeclass ConnectableWithClocks#(type a, type b);
   module mkConnectionWithClocks#(a x1, b x2, Clock fastClock, Reset fastReset, Clock slowClock, Reset slowReset)(Empty);
endtypeclass

instance ConnectableWithClocks#(Get#(a), Put#(a)) provisos (Bits#(a, awidth));
   module mkConnectionWithClocks#(Get#(a) in, Put#(a) out,
                                  Clock inClock, Reset inReset,
                                  Clock outClock, Reset outReset)(Empty) provisos (Bits#(a, awidth));
       SyncFIFOIfc#(a) synchronizer <- mkSyncFIFO(1, inClock, inReset, outClock);
       rule doGet;
           let v <- in.get();
	   synchronizer.enq(v);
       endrule
       rule doPut;
           let v = synchronizer.first;
	   synchronizer.deq;
	   out.put(v);
       endrule
   endmodule: mkConnectionWithClocks
endinstance: ConnectableWithClocks

instance ConnectableWithClocks#(Client#(a,b), Server#(a,b)) provisos (Bits#(a, awidth), Bits#(b, bwidth));
   module mkConnectionWithClocks#(Client#(a,b) client, Server#(a,b) server,
                                  Clock sourceClock, Reset sourceReset,
                                  Clock destClock, Reset destReset)(Empty)
      provisos (ConnectableWithClocks#(Get#(a), Put#(a)),
		ConnectableWithClocks#(Get#(b), Put#(b)),
		Bits#(a, awidth),
		Bits#(b, bwidth));
      mkConnectionWithClocks(client.request, server.request, sourceClock, sourceReset, destClock, destReset);
      mkConnectionWithClocks(server.response, client.response, destClock, destReset, sourceClock, sourceReset);
   endmodule
endinstance

module mkClockBinder#(a ifc) (a);
   return ifc;
endmodule


intermediate step to bufgctrl support

intermediate step to bufgctrl support