use mkFIFO1 for isRootBroadcastMessage

use mkFIFO1 for isRootBroadcastMessage

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

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

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

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

import Vector            :: *;
import Clocks          :: *;
import GetPut            :: *;
import Connectable    :: *;
import FIFO              :: *;
import FIFOF        :: *;
import PCIE               :: *;
import BRAM         :: *;
import BramMux        :: *;

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

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

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

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

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

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

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

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

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

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

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

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

   endrule

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

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

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

      tlpTraceBramWrAddrReg <= writeAddr + 1;
   endrule

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

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

	      isRootBroadcastMessage.deq();
	      return tlp;
	   endmethod
      endinterface

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

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

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

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

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

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

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

import Vector            :: *;
import Clocks          :: *;
import GetPut            :: *;
import Connectable    :: *;
import FIFO              :: *;
import FIFOF        :: *;
import PCIE               :: *;
import BRAM         :: *;
import BramMux        :: *;

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

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

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

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

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

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

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

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

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

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

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

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

   endrule

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

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

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

      tlpTraceBramWrAddrReg <= writeAddr + 1;
   endrule

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

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

	      isRootBroadcastMessage.deq();
	      return tlp;
	   endmethod
      endinterface

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

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

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


not using the result of mapM

not using the result of mapM

// 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 FIFO::*;
import FIFOF::*;
import BRAMFIFO::*;
import CBus::*; // extendNP and truncateNP

import Arith::*;

(* always_ready, always_enabled *)
interface X7FifoSyncMacro#(numeric type data_width);
   method Bit#(1) empty();
   method Bit#(1) full();
   method Action din(Bit#(data_width) v);
   method Action wren(Bit#(1) wren);
   method Bit#(data_width) dout();
   method Action rden(Bit#(1) rden);
   method Bit#(9) wrcount();
   method Bit#(9) rdcount();
endinterface

import "BVI" FIFO_DUALCLOCK_MACRO =
module  vmkBramFifo#(Clock wrclk, String fifo_size)(X7FifoSyncMacro#(data_width));
   parameter DEVICE = "7SERIES";
   parameter DATA_WIDTH = valueOf(data_width);
   parameter FIFO_SIZE = fifo_size;
   parameter FIRST_WORD_FALL_THROUGH = 1;
   default_clock clk(RDCLK);
   default_reset rst(RST);
   input_clock wrclk(WRCLK) = wrclk;
   method EMPTY empty();
   method FULL full();
   method din(DI) enable ((*inhigh*)EN_di);
   method wren(WREN) enable ((*inhigh*)EN_wren);
   method DO dout();
   method rden(RDEN) enable ((*inhigh*)EN_rden);
   // wrcount and rdcount ports are needed for xsim
   method WRCOUNT wrcount();
   method RDCOUNT rdcount();
   schedule (empty, full, dout, din, wren, rden, wrcount, rdcount) CF (empty, full, dout, din, wren, rden, wrcount, rdcount);
endmodule

module mkSizedBRAMFIFOF#(Integer m)(FIFOF#(t))
   provisos (Bits#(t,sizet),
	     Add#(1,a__,sizet));
   String fifo_size = "36Kb";
   let defaultClock <- exposeCurrentClock;
   let defaultReset <- exposeCurrentReset;
   let invertReset <- mkResetInverter(defaultReset);
   Vector#(TDiv#(sizet,72),X7FifoSyncMacro#(72)) fifos <- replicateM(vmkBramFifo(defaultClock, fifo_size, reset_by invertReset));
   Wire#(Bit#(1)) rdenWire <- mkDWire(0);
   Wire#(Bit#(1)) wrenWire <- mkDWire(0);
   Vector#(TDiv#(sizet,72),Wire#(Bit#(72))) dinWires <- replicateM(mkDWire(0));

   for (Integer i = 0; i < valueOf(TDiv#(sizet,72)); i = i+1) begin
      Reg#(Bit#(9)) rdcount <- mkReg(0);
      Reg#(Bit#(9)) wrcount <- mkReg(0);
      rule enables;
	 fifos[i].rden(rdenWire);
	 fifos[i].wren(wrenWire);
      endrule
      rule inputs;
	 fifos[i].din(dinWires[i]);
      endrule
      rule counts;
	 rdcount <= fifos[i].rdcount();
	 wrcount <= fifos[i].wrcount();
      endrule
   end

   function Bool fifoNotEmpty(Integer i); return fifos[i].empty == 0; endfunction
   function Bool fifoNotFull(Integer i); return fifos[i].full == 0; endfunction
   Vector#(TDiv#(sizet,72), Bool) vNotEmpty = genWith(fifoNotEmpty);
   Vector#(TDiv#(sizet,72), Bool) vNotFull = genWith(fifoNotFull);

   method t first() if (fifos[0].empty == 0);
      function Bit#(72) fifoFirst(Integer i); return fifos[i].dout(); endfunction
      Vector#(TDiv#(sizet,72), Bit#(72)) v = genWith(fifoFirst);
      return unpack(truncateNP(pack(v)));
   endmethod
   method Action deq() if (fifos[0].empty == 0);
      rdenWire <= 1;
   endmethod
   method notEmpty = (fifos[0].empty == 0);
   method Action enq(t v) if (fifos[0].full == 0);
      Vector#(TDiv#(sizet,72), Bit#(72)) vs = unpack(extendNP(pack(v)));
      Vector#(TDiv#(sizet,72), Integer) indices = genVector();
      function Action fifoEnq(Integer i); action dinWires[i] <= vs[i]; endaction endfunction
      mapM_(fifoEnq, indices);
      wrenWire <= 1;
   endmethod
   method notFull = (fifos[0].full == 0);
endmodule

module mkSizedBRAMFIFO#(Integer m)(FIFO#(t))
   provisos (Bits#(t,sizet),
	     Add#(1,a__,sizet));
   let fifo <- mkSizedBRAMFIFOF(m);
   method first = fifo.first;
   method deq = fifo.deq;
   method enq = fifo.enq;
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 FIFO::*;
import FIFOF::*;
import BRAMFIFO::*;
import CBus::*; // extendNP and truncateNP

import Arith::*;

(* always_ready, always_enabled *)
interface X7FifoSyncMacro#(numeric type data_width);
   method Bit#(1) empty();
   method Bit#(1) full();
   method Action din(Bit#(data_width) v);
   method Action wren(Bit#(1) wren);
   method Bit#(data_width) dout();
   method Action rden(Bit#(1) rden);
   method Bit#(9) wrcount();
   method Bit#(9) rdcount();
endinterface

import "BVI" FIFO_DUALCLOCK_MACRO =
module  vmkBramFifo#(Clock wrclk, String fifo_size)(X7FifoSyncMacro#(data_width));
   parameter DEVICE = "7SERIES";
   parameter DATA_WIDTH = valueOf(data_width);
   parameter FIFO_SIZE = fifo_size;
   parameter FIRST_WORD_FALL_THROUGH = 1;
   default_clock clk(RDCLK);
   default_reset rst(RST);
   input_clock wrclk(WRCLK) = wrclk;
   method EMPTY empty();
   method FULL full();
   method din(DI) enable ((*inhigh*)EN_di);
   method wren(WREN) enable ((*inhigh*)EN_wren);
   method DO dout();
   method rden(RDEN) enable ((*inhigh*)EN_rden);
   // wrcount and rdcount ports are needed for xsim
   method WRCOUNT wrcount();
   method RDCOUNT rdcount();
   schedule (empty, full, dout, din, wren, rden, wrcount, rdcount) CF (empty, full, dout, din, wren, rden, wrcount, rdcount);
endmodule

module mkSizedBRAMFIFOF#(Integer m)(FIFOF#(t))
   provisos (Bits#(t,sizet),
	     Add#(1,a__,sizet));
   String fifo_size = "36Kb";
   let defaultClock <- exposeCurrentClock;
   let defaultReset <- exposeCurrentReset;
   let invertReset <- mkResetInverter(defaultReset);
   Vector#(TDiv#(sizet,72),X7FifoSyncMacro#(72)) fifos <- replicateM(vmkBramFifo(defaultClock, fifo_size, reset_by invertReset));
   Wire#(Bit#(1)) rdenWire <- mkDWire(0);
   Wire#(Bit#(1)) wrenWire <- mkDWire(0);
   Vector#(TDiv#(sizet,72),Wire#(Bit#(72))) dinWires <- replicateM(mkDWire(0));

   for (Integer i = 0; i < valueOf(TDiv#(sizet,72)); i = i+1) begin
      Reg#(Bit#(9)) rdcount <- mkReg(0);
      Reg#(Bit#(9)) wrcount <- mkReg(0);
      rule enables;
	 fifos[i].rden(rdenWire);
	 fifos[i].wren(wrenWire);
      endrule
      rule inputs;
	 fifos[i].din(dinWires[i]);
      endrule
      rule counts;
	 rdcount <= fifos[i].rdcount();
	 wrcount <= fifos[i].wrcount();
      endrule
   end

   function Bool fifoNotEmpty(Integer i); return fifos[i].empty == 0; endfunction
   function Bool fifoNotFull(Integer i); return fifos[i].full == 0; endfunction
   Vector#(TDiv#(sizet,72), Bool) vNotEmpty = genWith(fifoNotEmpty);
   Vector#(TDiv#(sizet,72), Bool) vNotFull = genWith(fifoNotFull);

   method t first() if (fifos[0].empty == 0);
      function Bit#(72) fifoFirst(Integer i); return fifos[i].dout(); endfunction
      Vector#(TDiv#(sizet,72), Bit#(72)) v = genWith(fifoFirst);
      return unpack(truncateNP(pack(v)));
   endmethod
   method Action deq() if (fifos[0].empty == 0);
      rdenWire <= 1;
   endmethod
   method notEmpty = (fifos[0].empty == 0);
   method Action enq(t v) if (fifos[0].full == 0);
      Vector#(TDiv#(sizet,72), Bit#(72)) vs = unpack(extendNP(pack(v)));
      Vector#(TDiv#(sizet,72), Integer) indices = genVector();
      function Action fifoEnq(Integer i); action dinWires[i] <= vs[i]; endaction endfunction
      let unused <- mapM(fifoEnq, indices);
      wrenWire <= 1;
   endmethod
   method notFull = (fifos[0].full == 0);
endmodule

module mkSizedBRAMFIFO#(Integer m)(FIFO#(t))
   provisos (Bits#(t,sizet),
	     Add#(1,a__,sizet));
   let fifo <- mkSizedBRAMFIFOF(m);
   method first = fifo.first;
   method deq = fifo.deq;
   method enq = fifo.enq;
endmodule


added mac to test_mixed_phy with mgmtClock

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

import Pipe::*;
import MemTypes::*;
import Ethernet::*;
import PacketBuffer::*;
import AlteraMacWrap::*;
import EthMac::*;
import EthPhy::*;
import AlteraEthPhy::*;
import DE5Pins::*;

interface TestIndication;
   method Action done(Bit#(32) matchCount);
endinterface

interface TestRequest;
   method Action writePacketData(Vector#(2, Bit#(64)) data, Vector#(2, Bit#(8)) mask, Bit#(1) sop, Bit#(1) eop);
endinterface

interface Test;
   interface TestRequest request;
   interface `PinType pins;
endinterface

module mkTest#(TestIndication indication) (Test);
   let verbose = True;
   Clock defaultClock <- exposeCurrentClock();
   Reset defaultReset <- exposeCurrentReset();

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

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

   Reg#(Bit#(32)) cycle <- mkReg(0, clocked_by txClock, reset_by txReset);

   Gearbox#(2, 1, PacketDataT#(64)) fifoTxData <- mkNto1Gearbox(txClock, txReset, txClock, txReset);

   PacketBuffer buff <- mkPacketBuffer();
   EthPhyIfc phys <- mkAlteraEthPhy(mgmtClock, phyClock, txClock, defaultReset, clocked_by mgmtClock, reset_by mgmtReset);
   DtpPhyIfc#(1) dtpPhy <- mkEthPhy(mgmtClock, txClock, phyClock, clocked_by mgmtClock, reset_by mgmtReset);

   Clock rxClock = phys.rx_clkout;
   Reset rxReset <- mkSyncReset(2, defaultReset, rxClock);
   Vector#(3, EthMacIfc) mac <- replicateM(mkEthMac(mgmtClock, txClock, rxClock, txReset));
   EthMacIfc dtpMac <- mkEthMac(mgmtClock, txClock, dtpPhy.rx_clkout[0], txReset);

   SyncFIFOIfc#(EtherData) tx_fifo <- mkSyncFIFO(5, defaultClock, defaultReset, txClock);

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

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

   mkConnection(dtpMac.tx, toPut(dtpPhy.tx[0]));
   mkConnection(toGet(dtpPhy.rx[0]), dtpMac.rx);

   rule readDataStart;
      let pktLen <- buff.readServer.readLen.get;
      if (verbose) $display(fshow(" read packt ") + fshow(pktLen));
      buff.readServer.readReq.put(EtherReq{len: truncate(pktLen)});
   endrule

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

   rule cross_clocking;
      let v <- buff.readServer.readData.get;
      tx_fifo.enq(v);
   endrule

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

   rule process_outgoing_packet;
      let data = fifoTxData.first; fifoTxData.deq;
      let temp = head(data);
      if (temp.mask != 0) begin
         if (verbose) $display("tx data %h", temp.data);
         mac[0].packet_tx.put(temp);
      end
   endrule

   rule rx_packet;
      let v <- mac[1].packet_rx.get();
      $display("rx data %h", v.data);
   endrule

   interface TestRequest request;
      method Action writePacketData(Vector#(2, Bit#(64)) data, Vector#(2, Bit#(8)) mask, Bit#(1) sop, Bit#(1) eop);
         EtherData beat = defaultValue;
         beat.data = pack(reverse(data));
         beat.mask = pack(reverse(mask));
         beat.sop = unpack(sop);
         beat.eop = unpack(eop);
         buff.writeServer.writeData.put(beat);
      endmethod
   endinterface
   interface `PinType pins;
      method Action osc_50(Bit#(1) b3d, Bit#(1) b4a, Bit#(1) b4d, Bit#(1) b7a, Bit#(1) b7d, Bit#(1) b8a, Bit#(1) b8d);
         clk_50_wire <= b4a;
      endmethod
      method Vector#(4, Bit#(1)) serial_tx_data;
         let v = append(dtpPhy.serial_tx, phys.serial_tx);
         return v;
      endmethod
      method Action serial_rx (Vector#(4, Bit#(1)) v);
         phys.serial_rx(takeAt(0, v));
         dtpPhy.serial_rx(takeAt(3, v));
      endmethod
      method Action sfp(Bit#(1) refclk);
         clk_644_wire <= refclk;
      endmethod
      interface i2c = clocks.i2c;
      interface led = leds.led_out;
      interface led_bracket = leds.led_out;
      interface sfpctrl = sfpctrl;
      interface buttons = buttons.pins;
      interface deleteme_unused_clock = defaultClock;
      interface deleteme_unused_clock2 = clocks.clock_50;
      interface deleteme_unused_clock3 = mgmtClock;
      interface deleteme_unused_reset = defaultReset;
   endinterface
endmodule

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

import Pipe::*;
import MemTypes::*;
import Ethernet::*;
import PacketBuffer::*;
import AlteraMacWrap::*;
import EthMac::*;
import EthPhy::*;
import AlteraEthPhy::*;
import DE5Pins::*;

interface TestIndication;
   method Action done(Bit#(32) matchCount);
endinterface

interface TestRequest;
   method Action writePacketData(Vector#(2, Bit#(64)) data, Vector#(2, Bit#(8)) mask, Bit#(1) sop, Bit#(1) eop);
endinterface

interface Test;
   interface TestRequest request;
   interface `PinType pins;
endinterface

module mkTest#(TestIndication indication) (Test);
   let verbose = True;
   Clock defaultClock <- exposeCurrentClock();
   Reset defaultReset <- exposeCurrentReset();

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

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

   Reg#(Bit#(32)) cycle <- mkReg(0, clocked_by txClock, reset_by txReset);

   Gearbox#(2, 1, PacketDataT#(64)) fifoTxData <- mkNto1Gearbox(txClock, txReset, txClock, txReset);

   PacketBuffer buff <- mkPacketBuffer();
   EthPhyIfc phys <- mkAlteraEthPhy(mgmtClock, phyClock, txClock, defaultReset, clocked_by mgmtClock, reset_by mgmtReset);
   DtpPhyIfc#(1) dtpPhy <- mkEthPhy(mgmtClock, txClock, phyClock, clocked_by mgmtClock, reset_by mgmtReset);

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

   SyncFIFOIfc#(EtherData) tx_fifo <- mkSyncFIFO(5, defaultClock, defaultReset, txClock);

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

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

   mkConnection(dtpMac.tx, toPut(dtpPhy.tx[0]));
   mkConnection(toGet(dtpPhy.rx[0]), dtpMac.rx);

   rule readDataStart;
      let pktLen <- buff.readServer.readLen.get;
      if (verbose) $display(fshow(" read packt ") + fshow(pktLen));
      buff.readServer.readReq.put(EtherReq{len: truncate(pktLen)});
   endrule

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

   rule cross_clocking;
      let v <- buff.readServer.readData.get;
      tx_fifo.enq(v);
   endrule

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

   rule process_outgoing_packet;
      let data = fifoTxData.first; fifoTxData.deq;
      let temp = head(data);
      if (temp.mask != 0) begin
         if (verbose) $display("tx data %h", temp.data);
         mac[0].packet_tx.put(temp);
      end
   endrule

   rule rx_packet;
      let v <- mac[1].packet_rx.get();
      $display("rx data %h", v.data);
   endrule

   interface TestRequest request;
      method Action writePacketData(Vector#(2, Bit#(64)) data, Vector#(2, Bit#(8)) mask, Bit#(1) sop, Bit#(1) eop);
         EtherData beat = defaultValue;
         beat.data = pack(reverse(data));
         beat.mask = pack(reverse(mask));
         beat.sop = unpack(sop);
         beat.eop = unpack(eop);
         buff.writeServer.writeData.put(beat);
      endmethod
   endinterface
   interface `PinType pins;
      method Action osc_50(Bit#(1) b3d, Bit#(1) b4a, Bit#(1) b4d, Bit#(1) b7a, Bit#(1) b7d, Bit#(1) b8a, Bit#(1) b8d);
         clk_50_wire <= b4a;
      endmethod
      method Vector#(4, Bit#(1)) serial_tx_data;
         let v = append(dtpPhy.serial_tx, phys.serial_tx);
         return v;
      endmethod
      method Action serial_rx (Vector#(4, Bit#(1)) v);
         phys.serial_rx(takeAt(0, v));
         dtpPhy.serial_rx(takeAt(3, v));
      endmethod
      method Action sfp(Bit#(1) refclk);
         clk_644_wire <= refclk;
      endmethod
      interface i2c = clocks.i2c;
      interface led = leds.led_out;
      interface led_bracket = leds.led_out;
      interface sfpctrl = sfpctrl;
      interface buttons = buttons.pins;
      interface deleteme_unused_clock = defaultClock;
      interface deleteme_unused_clock2 = clocks.clock_50;
      interface deleteme_unused_clock3 = mgmtClock;
      interface deleteme_unused_reset = defaultReset;
   endinterface
endmodule


256 tiles

256 tiles

import GetPut::*;
import Clocks::*;
import Vector::*;
import BuildVector::*;
import FIFO::*;
import FIFOF::*;
import GetPut::*;
import Connectable::*;

import Pipe::*;
import HostInterface::*;
import Dsp48E1::*;
import InnerProdInterface::*;
import ConnectalBramFifo::*;

typedef 256 NumTiles;
typedef 16 NumTilesPerMacro;
typedef TDiv#(NumTiles,NumTilesPerMacro) NumMacroTiles;
typedef Tuple2#(Bit#(TLog#(NumTilesPerMacro)),TileRequest) MacroTileRequest;

typedef Tuple4#(Int#(16),Int#(16),Bool,Bool) TileRequest;
typedef Tuple2#(Int#(16),Int#(16))           TileResponse;

interface InnerProdSynth;
   interface InnerProdRequest request;
   interface Get#(TileResponse)   response;
endinterface

interface InnerProd;
   interface InnerProdRequest request;
endinterface

interface InnerProdTile;
   interface PipeIn#(TileRequest) request;
   interface PipeOut#(TileResponse) response;
endinterface

function PipeOut#(TileResponse) getTileResponsePipe(InnerProdTile tile); return tile.response; endfunction

(* synthesize *)
module mkInnerProdTile#(Int#(16) tile)(InnerProdTile);

   let dsp <- mkDsp48E1();
   let defaultClock <- exposeCurrentClock();
   let defaultReset <- exposeCurrentReset();

   FIFOF#(Tuple4#(Int#(16),Int#(16),Bool,Bool)) reqFifo <- mkDualClockBramFIFOF(defaultClock, defaultReset, defaultClock, defaultReset);
   FIFOF#(Int#(16)) responseFifo <- mkFIFOF(); //mkDualClockBramFIFOF(defaultClock, defaultReset, defaultClock, defaultReset);

   rule request_rule;
      let req <- toGet(reqFifo).get();
      match { .a, .b, .first, .last } = req;
      dsp.a(extend(pack(a)));
      dsp.b(extend(pack(b)));
      dsp.c(0);
      dsp.d(0);
      let opmode = 7'h25;
      if (first) opmode = 7'h05;
      dsp.opmode(opmode);
      dsp.inmode(0);
      dsp.alumode(0);
      dsp.last(pack(last));
   endrule

   rule responseRule;
      $display("InnerProdTile %d response.get %h", tile, dsp.p());
      responseFifo.enq(unpack(dsp.p()[23:8]));
   endrule

   function TileResponse addTileNumber(Int#(16) v); return tuple2(tile, v); endfunction

   interface PipeIn request = toPipeIn(reqFifo);
   interface PipeOut response = mapPipe(addTileNumber, toPipeOut(responseFifo));
endmodule

interface ReqPipes#(numeric type numPipes, type reqType);
   interface PipeIn#(Tuple2#(Bit#(TLog#(numPipes)),reqType)) inPipe;
   interface Vector#(numPipes, PipeOut#(reqType))            outPipes;
endinterface

module mkRequestPipes(ReqPipes#(numPipes,reqType))
   provisos (FunnelPipesPipelined#(1, numPipes, reqType, 2),
	     Bits#(Tuple2#(Bit#(TLog#(numPipes)), reqType), a__),
	     Add#(1, c__, a__)
	     );
   FIFOF#(Tuple2#(Bit#(TLog#(numPipes)),reqType)) syncIn <- mkFIFOF();

   PipeOut#(Tuple2#(Bit#(TLog#(numPipes)),reqType))              reqPipe = toPipeOut(syncIn);
   Vector#(1, PipeOut#(Tuple2#(Bit#(TLog#(numPipes)),reqType))) reqPipe1 = vec(reqPipe);
   UnFunnelPipe#(1,numPipes,reqType,2)                  unfunnelReqPipes <- mkUnFunnelPipesPipelined(reqPipe1);

   interface PipeIn inPipe = toPipeIn(syncIn);
   interface Vector outPipes = unfunnelReqPipes;
endmodule

interface ResponsePipes#(numeric type numPipes);
   interface Vector#(numPipes,PipeIn#(TileResponse)) inPipes;
   interface PipeOut#(TileResponse)                  outPipe;
endinterface

module mkResponsePipes(ResponsePipes#(numPipes))
   provisos (FunnelPipesPipelined#(1, numPipes, TileResponse, 2));

   Vector#(numPipes, FIFOF#(TileResponse))                fifos <- replicateM(mkFIFOF);
   Vector#(numPipes, PipeOut#(TileResponse))      responsePipes = map(toPipeOut, fifos);
   FunnelPipe#(1,numPipes,TileResponse,2) funnelResponsePipe <- mkFunnelPipesPipelined(responsePipes);

   interface Vector  inPipes = map(toPipeIn, fifos);
   interface PipeOut outPipe = funnelResponsePipe[0];
endmodule

interface MacroTile;
   interface PipeIn#(MacroTileRequest) inPipe;
   interface PipeOut#(TileResponse) outPipe;
endinterface

(* synthesize *)
module mkRequestPipesMTSynth(ReqPipes#(NumTilesPerMacro,TileRequest));
   let rp <- mkRequestPipes();
   return rp;
endmodule

(* synthesize *)
module mkResponsePipesMTSynth(ResponsePipes#(NumTilesPerMacro));
   let op <- mkResponsePipes();
   return op;
endmodule

(* synthesize *)
module mkMacroTile#(Int#(16) mt)(MacroTile);
   ReqPipes#(NumTilesPerMacro,TileRequest) rp <- mkRequestPipesMTSynth();
   ResponsePipes#(NumTilesPerMacro) op <- mkResponsePipesMTSynth();

   for (Integer t = 0; t < valueOf(NumTilesPerMacro); t = t + 1) begin
      let tile <- mkInnerProdTile(mt * fromInteger(valueOf(NumTilesPerMacro)) + fromInteger(t));
      mkConnection(rp.outPipes[t], tile.request);
      mkConnection(tile.response, op.inPipes[t]);
   end

   FIFOF#(TileResponse) responseFifo <- mkSizedFIFOF(valueOf(NumTilesPerMacro));
   rule responseRule;
      let tr <- toGet(op.outPipe).get();
      $display("responseFifo: mt=%d t=%d v=%h", mt, tpl_1(tr), tpl_2(tr));
      responseFifo.enq(tr);
   endrule

   interface PipeIn inPipe = rp.inPipe;
   interface PipeOut outPipe = toPipeOut(responseFifo); //op.outPipe;
endmodule

(* synthesize *)
module mkRequestPipesSynth(ReqPipes#(NumMacroTiles,MacroTileRequest));
   let rp <- mkRequestPipes();
   return rp;
endmodule

(* synthesize *)
module mkResponsePipesSynth(ResponsePipes#(NumMacroTiles));
   let op <- mkResponsePipes();
   return op;
endmodule

(* synthesize *)
module mkInnerProdSynth#(Clock derivedClock)(InnerProdSynth);
   let defaultClock <- exposeCurrentClock;
   let defaultReset <- exposeCurrentReset;

   let derivedReset <- mkAsyncReset(2, defaultReset, derivedClock);

   let optionalReset = derivedReset; // noReset

   FIFOF#(Tuple2#(Bit#(TLog#(NumMacroTiles)),MacroTileRequest)) inputFifo <- mkDualClockBramFIFOF(defaultClock, defaultReset, derivedClock, derivedReset);
   FIFOF#(TileResponse) bramFifo <- mkDualClockBramFIFOF(derivedClock, derivedReset, defaultClock, defaultReset, clocked_by derivedClock, reset_by derivedReset);

   Reg#(Bit#(32)) cycles <- mkReg(0, clocked_by derivedClock, reset_by derivedReset);
   rule cyclesRule;
      cycles <= cycles+1;
   endrule

   ReqPipes#(NumMacroTiles,MacroTileRequest) rp <- mkRequestPipesSynth(clocked_by derivedClock, reset_by derivedReset);
   ResponsePipes#(NumMacroTiles) op <- mkResponsePipesSynth(clocked_by derivedClock, reset_by derivedReset);

   for (Integer mt = 0; mt < valueOf(NumMacroTiles); mt = mt + 1) begin
      let mtReset <- mkSyncReset(2, derivedReset, derivedClock);
      let macroTile <- mkMacroTile(fromInteger(mt), clocked_by derivedClock, reset_by mtReset);
      mkConnection(rp.outPipes[mt], macroTile.inPipe, clocked_by derivedClock, reset_by mtReset);
      mkConnection(macroTile.outPipe, op.inPipes[mt], clocked_by derivedClock, reset_by mtReset);
   end

   mkConnection(toPipeOut(inputFifo), rp.inPipe, clocked_by derivedClock, reset_by derivedReset);
   mkConnection(op.outPipe, toPipeIn(bramFifo), clocked_by derivedClock, reset_by derivedReset);

   Reg#(Bit#(TLog#(NumTilesPerMacro))) tReg <- mkReg(0);
   Reg#(Bit#(TLog#(NumMacroTiles))) mReg <- mkReg(0);
   Wire#(Bool) bWire <- mkDWire(False);
   rule foo if (bWire);
      $display("m=%d t=%d", mReg, tReg);
   endrule

   interface InnerProdRequest request;
      method Action innerProd(Bit#(16) tile, Bit#(16) a, Bit#(16) b, Bool first, Bool last);
	 Bit#(TLog#(NumTilesPerMacro)) t = truncate(tile);
	 Bit#(TLog#(NumMacroTiles)) m = truncate(tile >> valueOf(TLog#(NumTilesPerMacro)));
	 tReg <= t;
	 mReg <= m;
	 bWire <= True;
	 $display("request.innerProd m=%d t=%d a=%h b=%h first=%d last=%d", m, t, a, b, first, last);
	 inputFifo.enq(tuple2(m, tuple2(t, tuple4(unpack(a),unpack(b),first,last))));
      endmethod
      method Action start();
      endmethod
      method Action finish();
	 $dumpflush();
	 $finish();
      endmethod
   endinterface
   interface Get response = toGet(bramFifo);
endmodule

module mkInnerProd#(
`ifdef IMPORT_HOSTIF
		    HostInterface host,
`endif
		    InnerProdIndication ind)(InnerProd);

   let defaultClock <- exposeCurrentClock;
   let defaultReset <- exposeCurrentReset;
`ifdef IMPORT_HOSTIF
   let derivedClock = host.derivedClock;
`else
   let derivedClock = defaultClock;
`endif

   let ip <- mkInnerProdSynth(derivedClock);
   rule indRule;
      match { .t, .v } <- ip.response.get();
      $display("indRule v=%x %d", t, v);
      ind.innerProd(pack(t), pack(v));
   endrule

   interface InnerProdRequest request = ip.request;
endmodule

import GetPut::*;
import Clocks::*;
import Vector::*;
import BuildVector::*;
import FIFO::*;
import FIFOF::*;
import GetPut::*;
import Connectable::*;

import Pipe::*;
import HostInterface::*;
import Dsp48E1::*;
import InnerProdInterface::*;
import ConnectalBramFifo::*;

typedef 64 NumTiles;
typedef 64 NumTilesPerMacro;
typedef TDiv#(NumTiles,NumTilesPerMacro) NumMacroTiles;
typedef Tuple2#(Bit#(TLog#(NumTilesPerMacro)),TileRequest) MacroTileRequest;

typedef Tuple4#(Int#(16),Int#(16),Bool,Bool) TileRequest;
typedef Tuple2#(Int#(16),Int#(16))           TileResponse;

interface InnerProdSynth;
   interface InnerProdRequest request;
   interface Get#(TileResponse)   response;
endinterface

interface InnerProd;
   interface InnerProdRequest request;
endinterface

interface InnerProdTile;
   interface PipeIn#(TileRequest) request;
   interface PipeOut#(TileResponse) response;
endinterface

function PipeOut#(TileResponse) getTileResponsePipe(InnerProdTile tile); return tile.response; endfunction

(* synthesize *)
module mkInnerProdTile#(Int#(16) tile)(InnerProdTile);

   let dsp <- mkDsp48E1();
   let defaultClock <- exposeCurrentClock();
   let defaultReset <- exposeCurrentReset();

   FIFOF#(Tuple4#(Int#(16),Int#(16),Bool,Bool)) reqFifo <- mkDualClockBramFIFOF(defaultClock, defaultReset, defaultClock, defaultReset);
   FIFOF#(Int#(16)) responseFifo <- mkFIFOF(); //mkDualClockBramFIFOF(defaultClock, defaultReset, defaultClock, defaultReset);

   rule request_rule;
      let req <- toGet(reqFifo).get();
      match { .a, .b, .first, .last } = req;
      dsp.a(extend(pack(a)));
      dsp.b(extend(pack(b)));
      dsp.c(0);
      dsp.d(0);
      let opmode = 7'h25;
      if (first) opmode = 7'h05;
      dsp.opmode(opmode);
      dsp.inmode(0);
      dsp.alumode(0);
      dsp.last(pack(last));
   endrule

   rule responseRule;
      $display("InnerProdTile %d response.get %h", tile, dsp.p());
      responseFifo.enq(unpack(dsp.p()[23:8]));
   endrule

   function TileResponse addTileNumber(Int#(16) v); return tuple2(tile, v); endfunction

   interface PipeIn request = toPipeIn(reqFifo);
   interface PipeOut response = mapPipe(addTileNumber, toPipeOut(responseFifo));
endmodule

interface ReqPipes#(numeric type numPipes, type reqType);
   interface PipeIn#(Tuple2#(Bit#(TLog#(numPipes)),reqType)) inPipe;
   interface Vector#(numPipes, PipeOut#(reqType))            outPipes;
endinterface

module mkRequestPipes(ReqPipes#(numPipes,reqType))
   provisos (FunnelPipesPipelined#(1, numPipes, reqType, 2),
	     Bits#(Tuple2#(Bit#(TLog#(numPipes)), reqType), a__),
	     Add#(1, c__, a__)
	     );
   FIFOF#(Tuple2#(Bit#(TLog#(numPipes)),reqType)) syncIn <- mkFIFOF();

   PipeOut#(Tuple2#(Bit#(TLog#(numPipes)),reqType))              reqPipe = toPipeOut(syncIn);
   Vector#(1, PipeOut#(Tuple2#(Bit#(TLog#(numPipes)),reqType))) reqPipe1 = vec(reqPipe);
   UnFunnelPipe#(1,numPipes,reqType,2)                  unfunnelReqPipes <- mkUnFunnelPipesPipelined(reqPipe1);

   interface PipeIn inPipe = toPipeIn(syncIn);
   interface Vector outPipes = unfunnelReqPipes;
endmodule

interface ResponsePipes#(numeric type numPipes);
   interface Vector#(numPipes,PipeIn#(TileResponse)) inPipes;
   interface PipeOut#(TileResponse)                  outPipe;
endinterface

module mkResponsePipes(ResponsePipes#(numPipes))
   provisos (FunnelPipesPipelined#(1, numPipes, TileResponse, 3));

   Vector#(numPipes, FIFOF#(TileResponse))                fifos <- replicateM(mkFIFOF);
   Vector#(numPipes, PipeOut#(TileResponse))      responsePipes = map(toPipeOut, fifos);
   FunnelPipe#(1,numPipes,TileResponse,3) funnelResponsePipe <- mkFunnelPipesPipelined(responsePipes);

   interface Vector  inPipes = map(toPipeIn, fifos);
   interface PipeOut outPipe = funnelResponsePipe[0];
endmodule

interface MacroTile;
   interface PipeIn#(MacroTileRequest) inPipe;
   interface PipeOut#(TileResponse) outPipe;
endinterface

(* synthesize *)
module mkRequestPipesMTSynth(ReqPipes#(NumTilesPerMacro,TileRequest));
   let rp <- mkRequestPipes();
   return rp;
endmodule

(* synthesize *)
module mkResponsePipesMTSynth(ResponsePipes#(NumTilesPerMacro));
   let op <- mkResponsePipes();
   return op;
endmodule

(* synthesize *)
module mkMacroTile#(Int#(16) mt)(MacroTile);
   ReqPipes#(NumTilesPerMacro,TileRequest) rp <- mkRequestPipesMTSynth();
   ResponsePipes#(NumTilesPerMacro) op <- mkResponsePipesMTSynth();

   for (Integer t = 0; t < valueOf(NumTilesPerMacro); t = t + 1) begin
      let tile <- mkInnerProdTile(mt * fromInteger(valueOf(NumTilesPerMacro)) + fromInteger(t));
      mkConnection(rp.outPipes[t], tile.request);
      mkConnection(tile.response, op.inPipes[t]);
   end

   FIFOF#(TileResponse) responseFifo <- mkSizedFIFOF(valueOf(NumTilesPerMacro));
   rule responseRule;
      let tr <- toGet(op.outPipe).get();
      $display("responseFifo: mt=%d t=%d v=%h", mt, tpl_1(tr), tpl_2(tr));
      responseFifo.enq(tr);
   endrule

   interface PipeIn inPipe = rp.inPipe;
   interface PipeOut outPipe = toPipeOut(responseFifo); //op.outPipe;
endmodule

(* synthesize *)
module mkRequestPipesSynth(ReqPipes#(NumMacroTiles,MacroTileRequest));
   let rp <- mkRequestPipes();
   return rp;
endmodule

(* synthesize *)
module mkResponsePipesSynth(ResponsePipes#(NumMacroTiles));
   let op <- mkResponsePipes();
   return op;
endmodule

(* synthesize *)
module mkInnerProdSynth#(Clock derivedClock)(InnerProdSynth);
   let defaultClock <- exposeCurrentClock;
   let defaultReset <- exposeCurrentReset;

   let derivedReset <- mkAsyncReset(2, defaultReset, derivedClock);

   let optionalReset = derivedReset; // noReset

   FIFOF#(Tuple2#(Bit#(TLog#(NumMacroTiles)),MacroTileRequest)) inputFifo <- mkDualClockBramFIFOF(defaultClock, defaultReset, derivedClock, derivedReset);
   FIFOF#(TileResponse) bramFifo <- mkDualClockBramFIFOF(derivedClock, derivedReset, defaultClock, defaultReset, clocked_by derivedClock, reset_by derivedReset);

   Reg#(Bit#(32)) cycles <- mkReg(0, clocked_by derivedClock, reset_by derivedReset);
   rule cyclesRule;
      cycles <= cycles+1;
   endrule

   ReqPipes#(NumMacroTiles,MacroTileRequest) rp <- mkRequestPipesSynth(clocked_by derivedClock, reset_by derivedReset);
   ResponsePipes#(NumMacroTiles) op <- mkResponsePipesSynth(clocked_by derivedClock, reset_by derivedReset);

   for (Integer mt = 0; mt < valueOf(NumMacroTiles); mt = mt + 1) begin
      let mtReset <- mkSyncReset(2, derivedReset, derivedClock);
      let macroTile <- mkMacroTile(fromInteger(mt), clocked_by derivedClock, reset_by mtReset);
      mkConnection(rp.outPipes[mt], macroTile.inPipe, clocked_by derivedClock, reset_by mtReset);
      mkConnection(macroTile.outPipe, op.inPipes[mt], clocked_by derivedClock, reset_by mtReset);
   end

   mkConnection(toPipeOut(inputFifo), rp.inPipe, clocked_by derivedClock, reset_by derivedReset);
   mkConnection(op.outPipe, toPipeIn(bramFifo), clocked_by derivedClock, reset_by derivedReset);

   Reg#(Bit#(TLog#(NumTilesPerMacro))) tReg <- mkReg(0);
   Reg#(Bit#(TLog#(NumMacroTiles))) mReg <- mkReg(0);
   Wire#(Bool) bWire <- mkDWire(False);
   rule foo if (bWire);
      $display("m=%d t=%d", mReg, tReg);
   endrule

   interface InnerProdRequest request;
      method Action innerProd(Bit#(16) tile, Bit#(16) a, Bit#(16) b, Bool first, Bool last);
	 Bit#(TLog#(NumTilesPerMacro)) t = truncate(tile);
	 Bit#(TLog#(NumMacroTiles)) m = truncate(tile >> valueOf(TLog#(NumTilesPerMacro)));
	 tReg <= t;
	 mReg <= m;
	 bWire <= True;
	 $display("request.innerProd m=%d t=%d a=%h b=%h first=%d last=%d", m, t, a, b, first, last);
	 inputFifo.enq(tuple2(m, tuple2(t, tuple4(unpack(a),unpack(b),first,last))));
      endmethod
      method Action start();
      endmethod
      method Action finish();
	 $dumpflush();
	 $finish();
      endmethod
   endinterface
   interface Get response = toGet(bramFifo);
endmodule

module mkInnerProd#(
`ifdef IMPORT_HOSTIF
		    HostInterface host,
`endif
		    InnerProdIndication ind)(InnerProd);

   let defaultClock <- exposeCurrentClock;
   let defaultReset <- exposeCurrentReset;
`ifdef IMPORT_HOSTIF
   let derivedClock = host.derivedClock;
`else
   let derivedClock = defaultClock;
`endif

   let ip <- mkInnerProdSynth(derivedClock);
   rule indRule;
      match { .t, .v } <- ip.response.get();
      $display("indRule v=%x %d", t, v);
      ind.innerProd(pack(t), pack(v));
   endrule

   interface InnerProdRequest request = ip.request;
endmodule


fix syntax

fix syntax

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

interface FibIndication;
    method Action fibresult(Bit#(32) v);
endinterface

interface FibRequest;
   method Action fib(Bit#(32) v);
endinterface

module mkFibRequest#(FibIndication indication)(FibRequest);

   /* stack frame */
   Reg#(Bit#(16)) fibn <- mkReg(0);
   Reg#(Bit#(16)) fibtmp1 <- mkReg(0);
   Reg#(Bit#(16)) fibstate <- mkReg(0);

   /* function variables that do not need to be saved or restored */
   Reg#(Bit#(16)) fibresult <- mkReg(0);

   typedef enum {fibstateidle, fibstate1, fibstate2, fibstate3, fibstatecomplete} fsstate
   deriving (Eq, Bits);

   /* offsets in stack frame */
   Bits#(2) fsoffsetn = 0;
   Bits#(2) fsoffsettmp1 = 1;
   Bits#(2) fsoffsetnext = 2;

   Stack#(128, 3, Bit#(16)) stack <- mkStack();

   /* experiment: recursive fibonnaci
    * fib(n):
    *   int tmp1, tmp2;
    *   if n == 0 return 1  // fibstate1
    *   if n == 1 return 1
    *   tmp1 = fib(n-1)
    *   tmp2 = fib(n-2      // fibstate2
    *   return tmp1 + tmp2  // fibstate3
    *
    * with explicit stack:
    * struct fsf {
    *   int level;
    *   int tmp1;
    *   int n;
    *   int next_state;
    * } stack[N]
    *
    */

   function Action callfib(Bit#(16) arg, Bit#(6) returnto);
      stack.store(fsoffsetn, fibn);
      stack.store(fsoffsettmp1, tmp1);
      stack.store(fsoffsetnext, returnto);
      stack.push();
      fibn <= arg;
      fibstate <= fibstate1;
   endfunction

   function Action fibreturn(Bit#(16) returnval);
      fsresult <= returnval;
      stack.pop();
      fibn <= stack.load(fsoffsetn);
      fibtmp1 <= stack.load(fsoffsettmp1);
      fibstate <= stack.load(fsoffsetnext);
   endfunction

   rule fib1 (fibstate == fibstate1);
     if ((fibn == 0)) || (fibn == 1))
	begin
	   fibreturn(1);
	end
     else
	begin
	   callfib(fibn - 1, fibstate2);
	end
     endrule

   rule fib2 (fibstate == fibstate2);
      callfib(fibn - 2, fibstate3);
   endrule

   rule fib3 (fibstate == fibstate3);
      fibreturn(fibtmp1 + fibresult);
   endrule;

   rule fibcomplete (fibstate == fibstatecomplete)
      $display("fib completion");
      indication.fibresult(zeroExtend(fibresult));
      fibstate <= fibidle;
   endrule

   method Action fib(Bit#(32) v);
      $display("request fib");
      fibn <= truncate(v);
      callfib(truncate(v), fibstatecomplete);
   endmethod

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

interface FibIndication;
    method Action fibresult(Bit#(32) v);
endinterface

interface FibRequest;
   method Action fib(Bit#(32) v);
endinterface

module mkFibRequest#(FibIndication indication)(FibRequest);

   /* stack frame */
   Reg#(Bit#(16)) fibn <- mkReg(0);
   Reg#(Bit#(16)) fibtmp1 <- mkReg(0);
   Reg#(Bit#(16)) fibstate <- mkReg(0);

   /* function variables that do not need to be saved or restored */
   Reg#(Bit#(16)) fibresult <- mkReg(0);

   typedef enum {fibstateidle, fibstate1, fibstate2, fibstate3, fibstatecomplete} fsstate
   deriving (Eq, Bits);

   /* offsets in stack frame */
   Bits#(2) fsoffsetn = 0;
   Bits#(2) fsoffsettmp1 = 1;
   Bits#(2) fsoffsetnext = 2;

   Stack#(128, 3, Bit#(16)) stack <- mkStack();

   /* experiment: recursive fibonnaci
    * fib(n):
    *   int tmp1, tmp2;
    *   if n == 0 return 1  // fibstate1
    *   if n == 1 return 1
    *   tmp1 = fib(n-1)
    *   tmp2 = fib(n-2      // fibstate2
    *   return tmp1 + tmp2  // fibstate3
    *
    * with explicit stack:
    * struct fsf {
    *   int level;
    *   int tmp1;
    *   int n;
    *   int next_state;
    * } stack[N]
    *
    */

   function Action callfib(Bit#(16) arg, Bit#(6) returnto);
      stack.store(fsoffsetn, fibn);
      stack.store(fsoffsettmp1, tmp1);
      stack.store(fsoffsetnext, returnto);
      stack.push();
      fibn <= arg;
      fibstate <= fibstate1;
   endfunction

   function Action fibreturn(Bit#(16) returnval);
      fsresult <= returnval;
      stack.pop();
      fibn <= stack.load(fsoffsetn);
      fibtmp1 <= stack.load(fsoffsettmp1);
      fibstate <= stack.load(fsoffsetnext);
   endfunction

  rule fib1 (fibstate == fs1):
     if ((fibn == 0)) || (fibn == 1))
	begin
	   fibreturn(1);
	end
     else
	begin
	   callfib(fibn - 1, fibstate2);
	end
     endrule

   rule fib2 (fibstate == fibstate2):
      callfib(fibn - 2, fibstate3);
   endrule

   rule fib3 (fibstate == fibstate3);
      fibreturn(fibtmp1 + fibresult);
   endrule;

   rule fibcomplete (fibstate == fibstatecomplete)
      $display("fib completion");
      indication.fibresult(zeroExtend(fibresult));
      fibstate <= fibidle;
   endrule

   method Action fib(Bit#(32) v);
      $display("request fib");
      fibn <= truncate(v);
      callfib(truncate(v), fibstatecomplete);
   endmethod

endmodule


comment

comment

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

// bsv libraries
import Vector::*;

// Connectal libraries
import CtrlMux::*;
import Portal::*;
import Leds::*;
import MemTypes::*;
import MemPortal::*;
import HostInterface::*;

// generated by tool
import LedControllerRequest::*;
import SwitchRequest::*;
import SwitchIndication::*;

// defined by user
import Controller::*;
import SwitchPins::*;

module mkConnectalTop(ConnectalTop#(PhysAddrWidth,DataBusWidth,SwitchPins,0));

   // instantiate user portals
   SwitchIndicationProxy switchIndicationProxy <- mkSwitchIndicationProxy(SwitchIndicationPortal);
   Controller controller <- mkControllerRequest(switchIndicationProxy.ifc);

   LedControllerRequestWrapper ledControllerRequestWrapper <- mkLedControllerRequestWrapper(LedControllerRequestPortal,controller.ledRequest);
   SwitchRequestWrapper switchRequestWrapper <- mkSwitchRequestWrapper(SwitchRequestPortal,controller.switchRequest);

   Vector#(3,StdPortal) portals;
   portals[0] = ledControllerRequestWrapper.portalIfc;
   portals[1] = switchRequestWrapper.portalIfc;
   portals[2] = switchIndicationProxy.portalIfc;
   let ctrl_mux <- mkSlaveMux(portals);

   interface interrupt = getInterruptVector(portals);
   interface slave = ctrl_mux;
   interface masters = nil;
   interface leds = controller.leds;
   interface pins = controller.switchPins;

endmodule : mkConnectalTop

export SwitchPins::*;
export mkConnectalTop;

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

// bsv libraries
import Vector::*;

// portz libraries
import CtrlMux::*;
import Portal::*;
import Leds::*;
import MemTypes::*;
import MemPortal::*;
import HostInterface::*;

// generated by tool
import LedControllerRequest::*;
import SwitchRequest::*;
import SwitchIndication::*;

// defined by user
import Controller::*;
import SwitchPins::*;

module mkConnectalTop(ConnectalTop#(PhysAddrWidth,DataBusWidth,SwitchPins,0));

   // instantiate user portals
   SwitchIndicationProxy switchIndicationProxy <- mkSwitchIndicationProxy(SwitchIndicationPortal);
   Controller controller <- mkControllerRequest(switchIndicationProxy.ifc);

   LedControllerRequestWrapper ledControllerRequestWrapper <- mkLedControllerRequestWrapper(LedControllerRequestPortal,controller.ledRequest);
   SwitchRequestWrapper switchRequestWrapper <- mkSwitchRequestWrapper(SwitchRequestPortal,controller.switchRequest);

   Vector#(3,StdPortal) portals;
   portals[0] = ledControllerRequestWrapper.portalIfc;
   portals[1] = switchRequestWrapper.portalIfc;
   portals[2] = switchIndicationProxy.portalIfc;
   let ctrl_mux <- mkSlaveMux(portals);

   interface interrupt = getInterruptVector(portals);
   interface slave = ctrl_mux;
   interface masters = nil;
   interface leds = controller.leds;
   interface pins = controller.switchPins;

endmodule : mkConnectalTop

export SwitchPins::*;
export mkConnectalTop;


Added bus width 128 for BsimRDMA

Added bus width 128 for BsimRDMA

Change-Id: I9b799931361cb9519a70a71f509170c756441759

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

// BSV Libraries
import FIFOF::*;
import Vector::*;
import GetPutF::*;
import ClientServer::*;
import BRAMFIFO::*;
import BRAM::*;

// XBSV Libraries
import PortalMemory::*;
import PortalRMemory::*;
import Adapter::*;

import "BDPI" function Action pareff(Bit#(32) handle, Bit#(32) size);
import "BDPI" function Action init_pareff();
import "BDPI" function Action write_pareff32(Bit#(32) handle, Bit#(32) addr, Bit#(32) v);
import "BDPI" function Action write_pareff64(Bit#(32) handle, Bit#(32) addr, Bit#(64) v);
import "BDPI" function ActionValue#(Bit#(32)) read_pareff32(Bit#(32) handle, Bit#(32) addr);
import "BDPI" function ActionValue#(Bit#(64)) read_pareff64(Bit#(32) handle, Bit#(32) addr);

interface BsimRdmaReadWrite#(numeric type dsz);
   method Action write_pareff(Bit#(32) handle, Bit#(32) addr, Bit#(dsz) v);
   method ActionValue#(Bit#(dsz)) read_pareff(Bit#(32) handle, Bit#(32) addr);
endinterface

typeclass SelectBsimRdmaReadWrite#(numeric type dsz);
   module selectBsimRdmaReadWrite(BsimRdmaReadWrite#(dsz) ifc);
endtypeclass

instance SelectBsimRdmaReadWrite#(32);
   module selectBsimRdmaReadWrite(BsimRdmaReadWrite#(32) ifc);
       method Action write_pareff(Bit#(32) handle, Bit#(32) addr, Bit#(32) v);
	  write_pareff32(handle, addr, v);
       endmethod
       method ActionValue#(Bit#(32)) read_pareff(Bit#(32) handle, Bit#(32) addr);
	  let v <- read_pareff32(handle, addr);
	  return v;
       endmethod
   endmodule
endinstance
instance SelectBsimRdmaReadWrite#(64);
   module selectBsimRdmaReadWrite(BsimRdmaReadWrite#(64) ifc);
       method Action write_pareff(Bit#(32) handle, Bit#(32) addr, Bit#(64) v);
	  write_pareff64(handle, addr, v);
       endmethod
       method ActionValue#(Bit#(64)) read_pareff(Bit#(32) handle, Bit#(32) addr);
	  let v <- read_pareff64(handle, addr);
	  return v;
       endmethod
   endmodule
endinstance
instance SelectBsimRdmaReadWrite#(128);
   module selectBsimRdmaReadWrite(BsimRdmaReadWrite#(128) ifc);
       method Action write_pareff(Bit#(32) handle, Bit#(32) addr, Bit#(128) v);
	  write_pareff64(handle, addr, v[63:0]);
	  write_pareff64(handle, addr+8, v[127:64]);
       endmethod
       method ActionValue#(Bit#(128)) read_pareff(Bit#(32) handle, Bit#(32) addr);
	  let v0 <- read_pareff64(handle, addr);
	  let v1 <- read_pareff64(handle, addr+8);
	  return {v1,v0};
       endmethod
   endmodule
endinstance

//
// @brief DMA server for use in Bluesim
//
// @param dsz Number of bits in the data bus
//
interface BsimDMAServer#(numeric type dsz);
   interface DMARequest request;
endinterface

module mkBsimDMAReadInternal#(Vector#(numReadClients, DMAReadClient#(dsz)) readClients)(DMARead)
      provisos (SelectBsimRdmaReadWrite#(dsz));

   let dsz = valueOf(dsz);
   let rw <- selectBsimRdmaReadWrite();

   Reg#(DmaMemHandle)     handleReg <- mkReg(0);
   Reg#(Bit#(DmaAddrSize))  addrReg <- mkReg(0);
   Reg#(Bit#(8))         burstReg <- mkReg(0);
   Reg#(Bit#(8))           tagReg <- mkReg(0);
   Reg#(DmaChannelId)  activeChan <- mkReg(0);
   Reg#(DmaChannelId)   selectReg <- mkReg(0);

   rule incSelectReg;
      let s = selectReg+1;
      if (s == fromInteger(valueOf(numReadClients)))
	 s = 0;
      selectReg <= s;
   endrule

   rule loadClient if (burstReg == 0 && readClients[selectReg].readData.notFull());
      activeChan <= selectReg;
      let req <- readClients[selectReg].readReq.get();
      //$display("dmaread.loadClient activeChan=%d handle=%h addr=%h burst=%h", selectReg, req.handle, req.address, req.burstLen);
      handleReg <= req.handle;
      addrReg <= req.address;
      burstReg <= req.burstLen;
      tagReg <= req.tag;
   endrule

   rule readData if (burstReg > 0);
      addrReg <= addrReg+fromInteger(valueOf(TDiv#(dsz,8)));
      burstReg <= burstReg-1;
      Bit#(32) addr = extend(addrReg);
      Bit#(dsz) v <- rw.read_pareff(handleReg, addr);
      //$display("dmaread.readData activeChan=%d handle=%h addr=%h burst=%h v=%h", activeChan, handleReg, addrReg, burstReg, v);
      readClients[activeChan].readData.put(DMAData { data: v, tag: tagReg});
   endrule

   method ActionValue#(DmaDbgRec) dbg();
      return ?;
   endmethod

endmodule

module mkBsimDMAWriteInternal#(Vector#(numWriteClients, DMAWriteClient#(dsz)) writeClients)(DMAWrite)
      provisos (SelectBsimRdmaReadWrite#(dsz));

   let dsz = valueOf(dsz);
   let rw <- selectBsimRdmaReadWrite();

   Reg#(DmaMemHandle)   handleReg <- mkReg(0);
   Reg#(Bit#(DmaAddrSize)) addrReg <- mkReg(0);
   Reg#(Bit#(8))         burstReg <- mkReg(0);
   Reg#(Bit#(8))           tagReg <- mkReg(0);
   Reg#(DmaChannelId)  activeChan <- mkReg(0);
   Reg#(DmaChannelId)   selectReg <- mkReg(0);

   rule incSelectReg;
      let s = selectReg+1;
      if (s == fromInteger(valueOf(numWriteClients)))
	 s = 0;
      selectReg <= s;
   endrule

   rule loadClient if (burstReg == 0);
      activeChan <= selectReg;
      let req   <- writeClients[selectReg].writeReq.get();
      //$display("dmawrite.loadClient activeChan=%d handle=%h addr=%h burst=%h", selectReg, req.handle, req.address, req.burstLen);
      handleReg   <= req.handle;
      addrReg   <= req.address;
      burstReg  <= req.burstLen;
      tagReg    <= req.tag;
   endrule

   rule writeData if (burstReg > 0);
      addrReg <= addrReg+fromInteger(valueOf(TDiv#(dsz,8)));
      let v <- writeClients[activeChan].writeData.get();
      if (v.tag != tagReg) begin
	 //$display("BsimWriteData tag mismatch %h expected %h", v.tag, tagReg);
      end
      if (burstReg == 1)
	 writeClients[activeChan].writeDone.put(v.tag);
      burstReg <= burstReg-1;
      //$display("writeData activeChan=%d handle=%h addr=%h", activeChan, handleReg, addrReg);
      Bit#(32) addr = extend(addrReg);
      rw.write_pareff(handleReg, addr, v.data);
   endrule

   method ActionValue#(DmaDbgRec) dbg();
      return ?;
   endmethod

endmodule

//
// @brief Creates a DMA controller for read and write clients
//
// @param dmaIndication Interface for notifying software
// @param readClients The read clients.
// @param writeClients The writeclients.
//
module mkBsimDMAServer#(DMAIndication dmaIndication,
			Vector#(numReadClients, DMAReadClient#(dsz)) readClients,
			Vector#(numWriteClients, DMAWriteClient#(dsz)) writeClients)
   (BsimDMAServer#(dsz))
   provisos (SelectBsimRdmaReadWrite#(dsz));

   Reg#(Bool) inited <- mkReg(False);

   DMARead reader;
   if (valueOf(numReadClients) > 0)
      reader <- mkBsimDMAReadInternal(readClients);
   else
      reader = (interface DMARead;
		   method ActionValue#(DmaDbgRec) dbg();
		      return ?;
		   endmethod
		endinterface);

   DMAWrite writer;
   if (valueOf(numWriteClients) > 0)
      writer <- mkBsimDMAWriteInternal(writeClients);
   else
      writer = (interface DMAWrite;
		    method ActionValue#(DmaDbgRec) dbg();
		        return ?;
		    endmethod
		endinterface);

   rule initialize(!inited);
      inited <= True;
      init_pareff();
   endrule

   interface DMARequest request;
      method Action getStateDbg(ChannelType rc);
	 let rv = ?;
	 if (rc == Read)
	    rv <- reader.dbg;
	 if (rc == Write)
	    rv <- writer.dbg;
	 dmaIndication.reportStateDbg(rv);
      endmethod
      method Action paref(Bit#(32) handle, Bit#(32) size);
	 pareff(handle, size);
	 dmaIndication.parefResp(handle);
      endmethod
   endinterface
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.

// BSV Libraries
import FIFOF::*;
import Vector::*;
import GetPutF::*;
import ClientServer::*;
import BRAMFIFO::*;
import BRAM::*;

// XBSV Libraries
import PortalMemory::*;
import PortalRMemory::*;
import Adapter::*;

import "BDPI" function Action pareff(Bit#(32) handle, Bit#(32) size);
import "BDPI" function Action init_pareff();
import "BDPI" function Action write_pareff32(Bit#(32) handle, Bit#(32) addr, Bit#(32) v);
import "BDPI" function Action write_pareff64(Bit#(32) handle, Bit#(32) addr, Bit#(64) v);
import "BDPI" function ActionValue#(Bit#(32)) read_pareff32(Bit#(32) handle, Bit#(32) addr);
import "BDPI" function ActionValue#(Bit#(64)) read_pareff64(Bit#(32) handle, Bit#(32) addr);

interface BsimRdmaReadWrite#(numeric type dsz);
   method Action write_pareff(Bit#(32) handle, Bit#(32) addr, Bit#(dsz) v);
   method ActionValue#(Bit#(dsz)) read_pareff(Bit#(32) handle, Bit#(32) addr);
endinterface

typeclass SelectBsimRdmaReadWrite#(numeric type dsz);
   module selectBsimRdmaReadWrite(BsimRdmaReadWrite#(dsz) ifc);
endtypeclass

instance SelectBsimRdmaReadWrite#(32);
   module selectBsimRdmaReadWrite(BsimRdmaReadWrite#(32) ifc);
       method Action write_pareff(Bit#(32) handle, Bit#(32) addr, Bit#(32) v);
	  write_pareff32(handle, addr, v);
       endmethod
       method ActionValue#(Bit#(32)) read_pareff(Bit#(32) handle, Bit#(32) addr);
	  let v <- read_pareff32(handle, addr);
	  return v;
       endmethod
   endmodule
endinstance
instance SelectBsimRdmaReadWrite#(64);
   module selectBsimRdmaReadWrite(BsimRdmaReadWrite#(64) ifc);
       method Action write_pareff(Bit#(32) handle, Bit#(32) addr, Bit#(64) v);
	  write_pareff64(handle, addr, v);
       endmethod
       method ActionValue#(Bit#(64)) read_pareff(Bit#(32) handle, Bit#(32) addr);
	  let v <- read_pareff64(handle, addr);
	  return v;
       endmethod
   endmodule
endinstance

//
// @brief DMA server for use in Bluesim
//
// @param dsz Number of bits in the data bus
//
interface BsimDMAServer#(numeric type dsz);
   interface DMARequest request;
endinterface

module mkBsimDMAReadInternal#(Vector#(numReadClients, DMAReadClient#(dsz)) readClients)(DMARead)
      provisos (SelectBsimRdmaReadWrite#(dsz));

   let dsz = valueOf(dsz);
   let rw <- selectBsimRdmaReadWrite();

   Reg#(DmaMemHandle)     handleReg <- mkReg(0);
   Reg#(Bit#(DmaAddrSize))  addrReg <- mkReg(0);
   Reg#(Bit#(8))         burstReg <- mkReg(0);
   Reg#(Bit#(8))           tagReg <- mkReg(0);
   Reg#(DmaChannelId)  activeChan <- mkReg(0);
   Reg#(DmaChannelId)   selectReg <- mkReg(0);

   rule incSelectReg;
      let s = selectReg+1;
      if (s == fromInteger(valueOf(numReadClients)))
	 s = 0;
      selectReg <= s;
   endrule

   rule loadClient if (burstReg == 0 && readClients[selectReg].readData.notFull());
      activeChan <= selectReg;
      let req <- readClients[selectReg].readReq.get();
      //$display("dmaread.loadClient activeChan=%d handle=%h addr=%h burst=%h", selectReg, req.handle, req.address, req.burstLen);
      handleReg <= req.handle;
      addrReg <= req.address;
      burstReg <= req.burstLen;
      tagReg <= req.tag;
   endrule

   rule readData if (burstReg > 0);
      addrReg <= addrReg+fromInteger(valueOf(TDiv#(dsz,8)));
      burstReg <= burstReg-1;
      Bit#(32) addr = extend(addrReg);
      Bit#(dsz) v <- rw.read_pareff(handleReg, addr);
      //$display("dmaread.readData activeChan=%d handle=%h addr=%h burst=%h v=%h", activeChan, handleReg, addrReg, burstReg, v);
      readClients[activeChan].readData.put(DMAData { data: v, tag: tagReg});
   endrule

   method ActionValue#(DmaDbgRec) dbg();
      return ?;
   endmethod

endmodule

module mkBsimDMAWriteInternal#(Vector#(numWriteClients, DMAWriteClient#(dsz)) writeClients)(DMAWrite)
      provisos (SelectBsimRdmaReadWrite#(dsz));

   let dsz = valueOf(dsz);
   let rw <- selectBsimRdmaReadWrite();

   Reg#(DmaMemHandle)   handleReg <- mkReg(0);
   Reg#(Bit#(DmaAddrSize)) addrReg <- mkReg(0);
   Reg#(Bit#(8))         burstReg <- mkReg(0);
   Reg#(Bit#(8))           tagReg <- mkReg(0);
   Reg#(DmaChannelId)  activeChan <- mkReg(0);
   Reg#(DmaChannelId)   selectReg <- mkReg(0);

   rule incSelectReg;
      let s = selectReg+1;
      if (s == fromInteger(valueOf(numWriteClients)))
	 s = 0;
      selectReg <= s;
   endrule

   rule loadClient if (burstReg == 0);
      activeChan <= selectReg;
      let req   <- writeClients[selectReg].writeReq.get();
      //$display("dmawrite.loadClient activeChan=%d handle=%h addr=%h burst=%h", selectReg, req.handle, req.address, req.burstLen);
      handleReg   <= req.handle;
      addrReg   <= req.address;
      burstReg  <= req.burstLen;
      tagReg    <= req.tag;
   endrule

   rule writeData if (burstReg > 0);
      addrReg <= addrReg+fromInteger(valueOf(TDiv#(dsz,8)));
      let v <- writeClients[activeChan].writeData.get();
      if (v.tag != tagReg) begin
	 //$display("BsimWriteData tag mismatch %h expected %h", v.tag, tagReg);
      end
      if (burstReg == 1)
	 writeClients[activeChan].writeDone.put(v.tag);
      burstReg <= burstReg-1;
      //$display("writeData activeChan=%d handle=%h addr=%h", activeChan, handleReg, addrReg);
      Bit#(32) addr = extend(addrReg);
      rw.write_pareff(handleReg, addr, v.data);
   endrule

   method ActionValue#(DmaDbgRec) dbg();
      return ?;
   endmethod

endmodule

//
// @brief Creates a DMA controller for read and write clients
//
// @param dmaIndication Interface for notifying software
// @param readClients The read clients.
// @param writeClients The writeclients.
//
module mkBsimDMAServer#(DMAIndication dmaIndication,
			Vector#(numReadClients, DMAReadClient#(dsz)) readClients,
			Vector#(numWriteClients, DMAWriteClient#(dsz)) writeClients)
   (BsimDMAServer#(dsz))
   provisos (SelectBsimRdmaReadWrite#(dsz));

   Reg#(Bool) inited <- mkReg(False);

   DMARead reader;
   if (valueOf(numReadClients) > 0)
      reader <- mkBsimDMAReadInternal(readClients);
   else
      reader = (interface DMARead;
		   method ActionValue#(DmaDbgRec) dbg();
		      return ?;
		   endmethod
		endinterface);

   DMAWrite writer;
   if (valueOf(numWriteClients) > 0)
      writer <- mkBsimDMAWriteInternal(writeClients);
   else
      writer = (interface DMAWrite;
		    method ActionValue#(DmaDbgRec) dbg();
		        return ?;
		    endmethod
		endinterface);

   rule initialize(!inited);
      inited <= True;
      init_pareff();
   endrule

   interface DMARequest request;
      method Action getStateDbg(ChannelType rc);
	 let rv = ?;
	 if (rc == Read)
	    rv <- reader.dbg;
	 if (rc == Write)
	    rv <- writer.dbg;
	 dmaIndication.reportStateDbg(rv);
      endmethod
      method Action paref(Bit#(32) handle, Bit#(32) size);
	 pareff(handle, size);
	 dmaIndication.parefResp(handle);
      endmethod
   endinterface
endmodule


Added a Gearbox to mkBRAMWriteClient

Added a Gearbox to mkBRAMWriteClient

Change-Id: I2c2f6235f67e4f51e1727786361358edaea99a2e

// 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 BRAM::*;
import FIFO::*;
import Vector::*;
import Gearbox::*;
import FIFOF::*;
import SpecialFIFOs::*;

import BRAMFIFOFLevel::*;
import GetPutF::*;
import Dma::*;
import MemreadEngine::*;
import MemwriteEngine::*;

interface BRAMReadClient#(type bramIdx, numeric type busWidth);
   method Action start(DmaPointer h, Bit#(DmaOffsetSize) rbase, bramIdx num, bramIdx wbase);
   method ActionValue#(Bool) finish();
   interface DmaReadClient#(busWidth) dmaClient;
endinterface

interface BRAMWriteClient#(type bramIdx, numeric type busWidth);
   method Action start(DmaPointer h, Bit#(DmaOffsetSize) rbase, bramIdx num, bramIdx wbase);
   method ActionValue#(Bool) finish();
   interface DmaWriteClient#(busWidth) dmaClient;
endinterface

module mkBRAMReadClient#(BRAMServer#(bramIdx,d) br)(BRAMReadClient#(bramIdx,busWidth))
   provisos(Bits#(d,dsz),
	    Div#(busWidth,dsz,nd),
	    Mul#(nd,dsz,busWidth),
	    Add#(1,a__,nd),
	    Eq#(bramIdx),
	    Ord#(bramIdx),
	    Arith#(bramIdx),
	    Bits#(bramIdx,b__));

   Clock clk <- exposeCurrentClock;
   Reset rst <- exposeCurrentReset;

   FIFO#(void) f <- mkSizedFIFO(1);
   Gearbox#(nd,1,d) gb <- mkNto1Gearbox(clk,rst,clk,rst);
   Reg#(bramIdx) i <- mkReg(0);
   Reg#(bramIdx) j <- mkReg(0);
   Reg#(bramIdx) n <- mkReg(0);
   Reg#(bramIdx) wbase <- mkReg(0);
   Reg#(DmaPointer) ptr <- mkReg(0);
   Reg#(Bit#(DmaOffsetSize)) roff <- mkReg(0);
   Reg#(Bit#(DmaOffsetSize)) rbase <- mkReg(0);

   let readFifo <- mkFIFOF;
   MemreadEngine#(busWidth) re <- mkMemreadEngine(readFifo);
   let bus_width_in_bytes = fromInteger(valueOf(busWidth)/8);

   rule loadReq(i < n);
      //$display("mkBRAMReadClient::loadReq ptr=%d %d %d", ptr, roff+rbase, bus_width_in_bytes);
      re.start(ptr, roff + rbase, bus_width_in_bytes, bus_width_in_bytes);
      i <= i+fromInteger(valueOf(nd));
      roff <= roff+bus_width_in_bytes;
   endrule

   rule loadResp;
      let __x <- re.finish;
      readFifo.deq;
      let rv = readFifo.first;
      Vector#(nd,d) rvv = unpack(rv);
      gb.enq(rvv);
      //$display("mkBRAMReadClient::loadResp ptr=%d", ptr);
   endrule

   rule load(j < n);
      br.request.put(BRAMRequest{write:True, responseOnWrite:False, address:j+wbase, datain:gb.first[0]});
      gb.deq;
      j <= j+1;
      if (j+1 == n)
	 f.enq(?);
      //$display("mkBRAMReadClient::load ptr=%d", ptr);
   endrule

   rule discard(j >= n);
      gb.deq;
      //$display("mkBRAMReadClient::discard ptr=%d", ptr);
   endrule

   method Action start(DmaPointer h, Bit#(DmaOffsetSize) rb, bramIdx num, bramIdx wb);
      $display("mkBRAMReadClient::start(%h, %h, %h %h)", h, wb, num, rb);
      i <= 0;
      j <= 0;
      n <= num;
      ptr <= h;
      roff <= 0;
      rbase <= rb;
      wbase <= wb;
   endmethod

   method ActionValue#(Bool) finish();
      f.deq;
      return True;
   endmethod

   interface dmaClient = re.dmaClient;

endmodule

module mkBRAMWriteClient#(BRAMServer#(bramIdx,d) br)(BRAMWriteClient#(bramIdx,busWidth))

   provisos(Bits#(d,dsz),
	    Div#(busWidth,dsz,nd),
	    Mul#(nd,dsz,busWidth),
	    Add#(1,a__,nd),
	    Add#(1, b__, TMul#(2, nd)),
	    Add#(nd, c__, TMul#(2, nd)),
	    Eq#(bramIdx),
	    Bits#(bramIdx, d__),
	    Ord#(bramIdx),
	    Arith#(bramIdx));

   Clock clk <- exposeCurrentClock;
   Reset rst <- exposeCurrentReset;

   FIFO#(void) f <- mkSizedFIFO(1);
   Reg#(bramIdx) n <- mkReg(0);
   Reg#(bramIdx) i <- mkReg(0);
   Reg#(bramIdx) j <- mkReg(0);
   Reg#(bramIdx) rbase <- mkReg(0);
   Reg#(DmaPointer) ptr <- mkReg(0);
   Reg#(Bit#(DmaOffsetSize)) woff <- mkReg(0);
   Reg#(Bit#(DmaOffsetSize)) wbase <- mkReg(0);
   Gearbox#(1,nd,Bit#(dsz)) gb <- mk1toNGearbox(clk,rst,clk,rst);

   FIFOF#(Bit#(busWidth)) writeFifo = (interface FIFOF;
				       method Bit#(busWidth) first(); return pack(gb.first); endmethod
				       method Bool notEmpty(); return gb.notEmpty(); endmethod
				       endinterface);
   MemwriteEngine#(busWidth) we <- mkMemwriteEngine(writeFifo);
   let bus_width_in_bytes = fromInteger(valueOf(busWidth)/8);

   rule bramReq(j < n);
      br.request.put(BRAMRequest{write:False, responseOnWrite:False, address:j+rbase, datain:?});
      j <= j+1;
   endrule

   rule bramResp;
      d rv <- br.response.get;
      gb.enq(cons(pack(rv), nil));
   endrule

   rule loadReq(i < n);
      we.start(ptr, woff + wbase, bus_width_in_bytes, bus_width_in_bytes);
      i <= i+1;
      woff <= woff+bus_width_in_bytes;
   endrule

   rule loadResp;
      let __x <- we.finish;
      if (i == n)
	 f.enq(?);
   endrule

   method Action start(DmaPointer h, Bit#(DmaOffsetSize) wb, bramIdx num, bramIdx rb);
      //$display("mkBRAMWriteClient::start(%h, %h, %h %h)", h, wb, num, rb);
      i <= 0;
      j <= 0;
      n <= num;
      ptr <= h;
      rbase <= rb;
      wbase <= wb;
      woff <= 0;
   endmethod

   method ActionValue#(Bool) finish();
      f.deq;
      return True;
   endmethod

   interface dmaClient = we.dmaClient;

endmodule

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

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

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

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

import BRAM::*;
import FIFO::*;
import Vector::*;
import Gearbox::*;
import FIFOF::*;
import SpecialFIFOs::*;

import BRAMFIFOFLevel::*;
import GetPutF::*;
import Dma::*;
import MemreadEngine::*;
import MemwriteEngine::*;

interface BRAMReadClient#(type bramIdx, numeric type busWidth);
   method Action start(DmaPointer h, Bit#(DmaOffsetSize) rbase, bramIdx num, bramIdx wbase);
   method ActionValue#(Bool) finish();
   interface DmaReadClient#(busWidth) dmaClient;
endinterface

interface BRAMWriteClient#(type bramIdx, numeric type busWidth);
   method Action start(DmaPointer h, Bit#(DmaOffsetSize) rbase, bramIdx num, bramIdx wbase);
   method ActionValue#(Bool) finish();
   interface DmaWriteClient#(busWidth) dmaClient;
endinterface

module mkBRAMReadClient#(BRAMServer#(bramIdx,d) br)(BRAMReadClient#(bramIdx,busWidth))
   provisos(Bits#(d,dsz),
	    Div#(busWidth,dsz,nd),
	    Mul#(nd,dsz,busWidth),
	    Add#(1,a__,nd),
	    Eq#(bramIdx),
	    Ord#(bramIdx),
	    Arith#(bramIdx),
	    Bits#(bramIdx,b__));

   Clock clk <- exposeCurrentClock;
   Reset rst <- exposeCurrentReset;

   FIFO#(void) f <- mkSizedFIFO(1);
   Gearbox#(nd,1,d) gb <- mkNto1Gearbox(clk,rst,clk,rst);
   Reg#(bramIdx) i <- mkReg(0);
   Reg#(bramIdx) j <- mkReg(0);
   Reg#(bramIdx) n <- mkReg(0);
   Reg#(bramIdx) wbase <- mkReg(0);
   Reg#(DmaPointer) ptr <- mkReg(0);
   Reg#(Bit#(DmaOffsetSize)) roff <- mkReg(0);
   Reg#(Bit#(DmaOffsetSize)) rbase <- mkReg(0);

   let readFifo <- mkFIFOF;
   MemreadEngine#(busWidth) re <- mkMemreadEngine(readFifo);
   let bus_width_in_bytes = fromInteger(valueOf(busWidth)/8);

   rule loadReq(i < n);
      //$display("mkBRAMReadClient::loadReq ptr=%d %d %d", ptr, roff+rbase, bus_width_in_bytes);
      re.start(ptr, roff + rbase, bus_width_in_bytes, bus_width_in_bytes);
      i <= i+fromInteger(valueOf(nd));
      roff <= roff+bus_width_in_bytes;
   endrule

   rule loadResp;
      let __x <- re.finish;
      readFifo.deq;
      let rv = readFifo.first;
      Vector#(nd,d) rvv = unpack(rv);
      gb.enq(rvv);
      //$display("mkBRAMReadClient::loadResp ptr=%d", ptr);
   endrule

   rule load(j < n);
      br.request.put(BRAMRequest{write:True, responseOnWrite:False, address:j+wbase, datain:gb.first[0]});
      gb.deq;
      j <= j+1;
      if (j+1 == n)
	 f.enq(?);
      //$display("mkBRAMReadClient::load ptr=%d", ptr);
   endrule

   rule discard(j >= n);
      gb.deq;
      //$display("mkBRAMReadClient::discard ptr=%d", ptr);
   endrule

   method Action start(DmaPointer h, Bit#(DmaOffsetSize) rb, bramIdx num, bramIdx wb);
      $display("mkBRAMReadClient::start(%h, %h, %h %h)", h, wb, num, rb);
      i <= 0;
      j <= 0;
      n <= num;
      ptr <= h;
      roff <= 0;
      rbase <= rb;
      wbase <= wb;
   endmethod

   method ActionValue#(Bool) finish();
      f.deq;
      return True;
   endmethod

   interface dmaClient = re.dmaClient;

endmodule

module mkBRAMWriteClient#(BRAMServer#(bramIdx,Bit#(busWidth)) br)(BRAMWriteClient#(bramIdx,busWidth))

   provisos(Eq#(bramIdx),
	    Bits#(bramIdx, a__),
	    Ord#(bramIdx),
	    Arith#(bramIdx));

   FIFO#(void) f <- mkSizedFIFO(1);
   Reg#(bramIdx) n <- mkReg(0);
   Reg#(bramIdx) i <- mkReg(0);
   Reg#(bramIdx) j <- mkReg(0);
   Reg#(bramIdx) rbase <- mkReg(0);
   Reg#(DmaPointer) ptr <- mkReg(0);
   Reg#(Bit#(DmaOffsetSize)) woff <- mkReg(0);
   Reg#(Bit#(DmaOffsetSize)) wbase <- mkReg(0);

   let writeFifo <- mkFIFOF;
   MemwriteEngine#(busWidth) we <- mkMemwriteEngine(writeFifo);
   let bus_width_in_bytes = fromInteger(valueOf(busWidth)/8);

   rule bramReq(j < n);
      br.request.put(BRAMRequest{write:False, responseOnWrite:False, address:j+rbase, datain:?});
      j <= j+1;
   endrule

   rule bramResp;
      let rv <- br.response.get;
      writeFifo.enq(rv);
   endrule

   rule loadReq(i < n);
      we.start(ptr, woff + wbase, bus_width_in_bytes, bus_width_in_bytes);
      i <= i+1;
      woff <= woff+bus_width_in_bytes;
   endrule

   rule loadResp;
      let __x <- we.finish;
      if (i == n)
	 f.enq(?);
   endrule

   method Action start(DmaPointer h, Bit#(DmaOffsetSize) wb, bramIdx num, bramIdx rb);
      //$display("mkBRAMWriteClient::start(%h, %h, %h %h)", h, wb, num, rb);
      i <= 0;
      j <= 0;
      n <= num;
      ptr <= h;
      rbase <= rb;
      wbase <= wb;
      woff <= 0;
   endmethod

   method ActionValue#(Bool) finish();
      f.deq;
      return True;
   endmethod

   interface dmaClient = we.dmaClient;

endmodule