added Connectable#(PipeOut#(a),PipeIn#(a))

Change-Id: I9b30f96e755699e74e94f510bdf35a8c3fa6e1a7

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

interface PipeIn#(type a);
   method Action enq(a v);
   method Bool notFull();
endinterface

interface PipeOut#(type a);
   method a first();
   method Action deq();
   method Bool notEmpty();
endinterface

typeclass ToPipeIn#(type a, type b);
   function PipeIn#(a) toPipeIn(b in);
endtypeclass

typeclass ToPipeOut#(type a, type b);
   function PipeOut#(a) toPipeOut(b in);
endtypeclass

typeclass MkPipeOut#(type a, type b);
   module mkPipeOut#(b in)(PipeOut#(a));
endtypeclass

instance ToPipeIn#(a, FIFOF#(a));
   function PipeIn#(a) toPipeIn(FIFOF#(a) in);
      return (interface PipeIn#(a);
		 method enq = in.enq;
		 method notFull = in.notFull;
	      endinterface);
   endfunction
endinstance

instance ToPipeOut#(a, Reg#(a));
   function PipeOut#(a) toPipeOut(Reg#(a) in);
      return (interface PipeOut#(a);
		 method first(); return in; endmethod
		 method Action deq(); endmethod
		 method Bool notEmpty(); return False; endmethod
	      endinterface);
   endfunction
endinstance

instance ToPipeOut#(a, FIFOF#(a));
   function PipeOut#(a) toPipeOut(FIFOF#(a) in);
      return (interface PipeOut#(a);
		 method first = in.first;
		 method deq = in.deq;
		 method notEmpty = in.notEmpty;
	      endinterface);
   endfunction
endinstance

instance ToPipeOut#(Vector#(n,a), MIMO#(k,n,sz,a));
   function PipeOut#(Vector#(n,a)) toPipeOut(MIMO#(k,n,sz,a) in);
      return (interface PipeOut#(a);
		 method first = in.first;
		 method Action deq() if (in.deqReadyN(fromInteger(valueOf(n))));
		    in.deq(fromInteger(valueOf(n)));
		 endmethod
		 method Bool notEmpty();
		    return in.deqReadyN(fromInteger(valueOf(n)));
		 endmethod
	      endinterface);
   endfunction
endinstance

instance MkPipeOut#(a, Get#(a))
   provisos (Bits#(a, asz));
   module mkPipeOut#(Get#(a) in)(PipeOut#(a));
      FIFOF#(a) fifo <- mkFIFOF();
      rule connect;
	 let v <- in.get();
	 fifo.enq(v);
      endrule
      return toPipeOut(fifo);
   endmodule
endinstance

instance ToGet #(PipeOut #(a), a);
   function Get #(a) toGet (PipeOut #(a) po);
      return (interface Get;
                 method ActionValue #(a) get ();
                    po.deq ();
                    return po.first ();
                 endmethod
              endinterface);
   endfunction
endinstance

instance Connectable#(PipeOut#(a),Put#(a));
   module mkConnection#(PipeOut#(a) in, Put#(a) out)(Empty);
      rule connect;
	 let v = in.first;
	 in.deq();
	 out.put(v);
      endrule
   endmodule
endinstance

instance Connectable#(PipeOut#(a),PipeIn#(a));
   module mkConnection#(PipeOut#(a) in, PipeIn#(a) out)(Empty);
      rule connect;
	 let v = in.first;
	 in.deq();
	 out.enq(v);
      endrule
   endmodule
endinstance

function PipeOut#(a) unvectorPipeOut(PipeOut#(Vector#(1,a)) in);
   return (interface PipeOut#(a);
	      method first = in.first[0];
	      method deq = in.deq;
	      method notEmpty = in.notEmpty;
	   endinterface);
endfunction

function PipeOut#(Tuple2#(a,b)) zipPipeOut(PipeOut#(a) ina, PipeOut#(b) inb);
      return (interface PipeOut#(Tuple2#(a,b));
		 method Tuple2#(a,b) first(); return tuple2(ina.first, inb.first); endmethod
		 method Action deq(); ina.deq(); inb.deq(); endmethod
		 method Bool notEmpty(); return ina.notEmpty() && inb.notEmpty(); endmethod
	      endinterface);
   endfunction

module mkFunnel#(PipeOut#(Vector#(mk,a)) in)(PipeOut#(Vector#(m, a)))
   provisos (Mul#(m, k, mk),
	     Bits#(a, asz),
	     Add#(a__, TMul#(asz, m), TMul#(asz, mk)),
	     Add#(1, b__, asz),
	     Add#(2, c__, mk),
	     Add#(d__, m, mk),
	     Add#(asz, m, e__),
	     Add#(asz, mk, f__));
   let m = fromInteger(valueOf(m));
   let mk = fromInteger(valueOf(mk));

   MIMOConfiguration cfg = defaultValue();
   MIMO#(mk, m, mk, a) mimo <- mkMIMO(cfg);
   rule consumer if (mimo.enqReadyN(mk));
      Vector#(mk, a) v = in.first();
      in.deq();
      mimo.enq(mk, v);
   endrule

   method Vector#(m, a) first() if (mimo.deqReadyN(m));
      return mimo.first();
   endmethod
   method Action deq() if (mimo.deqReadyN(m));
      mimo.deq(m);
   endmethod
   method notEmpty();
      return mimo.deqReadyN(m);
   endmethod
endmodule

module mkFunnel1#(PipeOut#(Vector#(k,a)) in)(PipeOut#(a))
   provisos (Bits#(a, asz), Log#(k,ksz));

   Reg#(Bit#(ksz)) selector <- mkReg(0);

   method a first();
      return in.first[selector];
   endmethod
   method Action deq();
      if (selector == fromInteger(valueOf(k)-1)) begin
	 in.deq();
	 selector <= 0;
      end
      else
	 selector <= selector + 1;
   endmethod
   method notEmpty();
      return in.notEmpty();
   endmethod
endmodule

typedef Vector#(k,PipeOut#(a)) FunnelPipe#(numeric type k, type a, numeric type bitsPerCycle);

// this relies on the fact that dead-code will remove unused fifo instantiations
// if you are paranoid, your module will look like mkUnFunnel1PipesPipelined
module mkFunnel1PipesPipelined#(Vector#(k,PipeOut#(a)) in) (FunnelPipe#(1,a,bpc))
   provisos (Log#(k, logk),
	     Bits#(a,a__),
	     Div#(logk,bpc,stages));
   Vector#(stages, Vector#(k, FIFOF#(a))) buffs  <- replicateM(replicateM(mkSizedFIFOF(1)));
   Vector#(TAdd#(stages,1), Vector#(k, PipeOut#(a))) infss = append(map(map(toPipeOut),buffs), cons(in,nil));
   for(Integer j = valueOf(stages); j > 0; j=j-1)
      for(Integer i = 0; i < 2**(j*valueOf(bpc)) && i < valueOf(k); i=i+1)
	 mkConnection(infss[j][i], toPut(buffs[j-1][i/(2**valueOf(bpc))]));
   return cons(infss[0][0],nil);
endmodule

function PipeOut#(b) pipeSecond(PipeOut#(Tuple2#(a,b)) x) =
   (interface PipeOut;
       method b first;
	  return tpl_2(x.first);
       endmethod
       method Action deq = x.deq;
       method Bool notEmpty = x.notEmpty;
    endinterface);

module mkUnFunnel1PipesPipelined#(PipeOut#(Tuple2#(Bit#(TLog#(k)),a)) in) (FunnelPipe#(k,a,bpc))
   provisos (Log#(k, logk),
	     Bits#(a,a__),
	     Add#(1,b__,k),
	     Div#(logk,bpc,stages));
   Vector#(k, PipeOut#(Tuple2#(Bit#(logk),a))) ins  = cons(in,replicate(?));
   Vector#(k, PipeOut#(Tuple2#(Bit#(logk),a))) outs = newVector;
   for(Integer j = 0; j < valueOf(stages); j=j+1) begin
      for(Integer i = 0; i < 2**(j*valueOf(bpc)); i=i+1) begin
	 Integer bits = (j == valueOf(stages)-1) ? valueOf(logk)-(j*valueOf(bpc)) : valueOf(bpc);
	 function Bit#(bpc) sh(Bit#(bpc) x) = x<<(valueOf(bpc)-bits);
	 for(Integer l = 0; l < 2**bits; l=l+1)  begin
	    let buff <- mkSizedFIFOF(1);
	    outs[(2**bits)*i+l] = toPipeOut(buff);
	    rule xfer if(tpl_1(ins[i].first)[(valueOf(logk)-1):(valueOf(logk)-valueOf(bpc))] == sh(fromInteger(l)));
	       match{.idx, .v} <- toGet(ins[i]).get;
	       buff.enq(tuple2(idx<<valueOf(bpc), v));
	    endrule
	 end
      end
      ins = outs;
   end
   return map(pipeSecond,outs);
endmodule

module mkUnfunnel#(PipeOut#(Vector#(m,a)) in)(PipeOut#(Vector#(mk, a)))
   provisos (Mul#(m, k, mk),
	     Bits#(a, asz),
	     Add#(1, b__, asz),
	     Add#(2, c__, mk),
	     Add#(d__, m, mk),
	     Add#(asz, m, e__),
	     Add#(asz, mk, f__));
   let m = fromInteger(valueOf(m));
   let mk = fromInteger(valueOf(mk));

   MIMOConfiguration cfg = defaultValue();
   MIMO#(m, mk, mk, a) mimo <- mkMIMO(cfg);
   rule consumer if (mimo.enqReadyN(m));
      Vector#(m, a) v = in.first();
      in.deq();
      mimo.enq(m, v);
   endrule

   method Vector#(mk, a) first() if (mimo.deqReadyN(mk));
      return mimo.first();
   endmethod
   method Action deq() if (mimo.deqReadyN(mk));
      mimo.deq(mk);
   endmethod
   method notEmpty();
      return mimo.deqReadyN(mk);
   endmethod
endmodule

module mkFunnelPipes#(Vector#(mk, PipeOut#(a)) ins)(Vector#(m, PipeOut#(a)))
   provisos (Mul#(m, k, mk),
	     Bits#(a, asz),
	     Log#(k,ksz)
      );
   let k = fromInteger(valueOf(k));
   let m = fromInteger(valueOf(m));
   let mk = fromInteger(valueOf(mk));

   Vector#(m, FIFOF#(a)) fifos <- replicateM(mkFIFOF);
   for (Integer i = 0; i < m; i = i+1) begin
      Reg#(Bit#(asz)) which <- mkReg(0);
      rule consumer;
	 let index = (which << valueOf(ksz)) + fromInteger(i);
	 let v <- toGet(ins[index]).get();
	 fifos[i].enq(v);
	 which <= (which + 1) % k;
      endrule
   end

   return map(toPipeOut, fifos);
endmodule

module mkFunnelPipes1#(Vector#(k, PipeOut#(a)) ins)(PipeOut#(a))
   provisos (Bits#(a, asz),
	     Log#(k,ksz)
      );
   let k = fromInteger(valueOf(k));

   Reg#(Bit#(ksz)) selector <- mkReg(0);

   method a first();
      return ins[selector].first();
   endmethod
   method Action deq();
      ins[selector].deq();
      if (selector == fromInteger(valueOf(k)-1))
	 selector <= 0;
   else
      selector <= selector + 1;
   endmethod
   method Bool notEmpty();
      return ins[selector].notEmpty();
   endmethod
endmodule

module mkUnfunnelPipes#(Vector#(m, PipeOut#(a)) ins)(Vector#(mk, PipeOut#(a)))
   provisos (Mul#(m, k, mk),
	     Log#(k,ksz),
	     Bits#(a, asz),
	     Add#(1, b__, asz)
	     );
   let m = fromInteger(valueOf(m));
   let k = fromInteger(valueOf(k));
   let mk = fromInteger(valueOf(mk));

   Vector#(mk, FIFOF#(a)) fifos <- replicateM(mkFIFOF);
   for (Integer i = 0; i < m; i = i + 1) begin
      Reg#(Bit#(asz)) which <- mkReg(0);
      rule consumer;
	 let index = (which << valueOf(ksz)) + fromInteger(i);
	 let v <- toGet(ins[i]).get();
	 fifos[index].enq(v);
	 which <= (which + 1) % k;
      endrule
   end
   return map(toPipeOut, fifos);
endmodule

module mkRepeat#(UInt#(n) repetitions, PipeOut#(a) inpipe)(PipeOut#(a));
   Reg#(UInt#(n)) count <- mkReg(0);
   method first = inpipe.first;
   method Action deq();
      let c = count + 1;
      if (count == (repetitions - 1)) begin
	 c = 0;
	 inpipe.deq();
      end
      count <= c;
   endmethod
   method notEmpty = inpipe.notEmpty;
endmodule

module mkForkVector#(PipeOut#(a) inpipe)(Vector#(n, PipeOut#(a)))
   provisos (Bits#(a, asz));
   Vector#(n, FIFOF#(a)) fifos <- replicateM(mkFIFOF());
   rule forkelts;
      let v = inpipe.first();
      inpipe.deq;
      for (Integer i = 0; i < valueOf(n); i = i + 1) begin
	 fifos[i].enq(v);
      end
   endrule
   return map(toPipeOut, fifos);
endmodule

module mkSizedForkVector#(Integer size, PipeOut#(a) inpipe)(Vector#(n, PipeOut#(a)))
   provisos (Bits#(a, asz));
   Vector#(n, FIFOF#(a)) fifos <- replicateM(mkSizedFIFOF(size));
   rule forkelts;
      let v = inpipe.first();
      inpipe.deq;
      for (Integer i = 0; i < valueOf(n); i = i + 1) begin
	 fifos[i].enq(v);
      end
   endrule
   return map(toPipeOut, fifos);
endmodule

module mkJoin#(function c f(a av, b bv), PipeOut#(a) apipe, PipeOut#(b) bpipe)(PipeOut#(c));
   method c first();
      let av = apipe.first();
      let bv = bpipe.first();
      return f(av, bv);
   endmethod
   method Action deq();
      apipe.deq();
      bpipe.deq();
   endmethod
   method Bool notEmpty();
      return apipe.notEmpty() && bpipe.notEmpty();
   endmethod
endmodule

module mkJoinVector#(function b f(Vector#(n, a) av), Vector#(n, PipeOut#(a)) apipes)(PipeOut#(b))
   provisos (Bits#(Vector#(n,a),vasz));
   method b first();
      function a getfirst(PipeOut#(a) pipein); return pipein.first(); endfunction
      Vector#(n,a) vec = map(getfirst, apipes);
      return f(vec);
   endmethod
   method Action deq();
      function a getfirst(PipeOut#(a) pipein); return pipein.first(); endfunction
      for (Integer i = 0; i < valueOf(n); i = i + 1)
	 apipes[i].deq();
   endmethod
   method Bool notEmpty();
      function Bool getNotEmpty(PipeOut#(a) pipein); return pipein.notEmpty(); endfunction
      function Bool myand(Bool a, Bool b); return a && b; endfunction
      return foldl(myand, True, map(getNotEmpty, apipes));
   endmethod
endmodule

function PipeOut#(b) mapPipe(function b f(a av), PipeOut#(a) apipe);
   return (interface PipeOut#(b);
      method b first();
	 let av = apipe.first();
	 return f(av);
      endmethod
      method Action deq();
	 apipe.deq();
      endmethod
      method Bool notEmpty();
	 return apipe.notEmpty();
      endmethod
      endinterface);
endfunction

// buffered version of mapPipe
module mkMap#(function b f(a av), PipeOut#(a) apipe)(PipeOut#(b))
   provisos (Bits#(b,bsz));
   FIFOF#(b) fifo <- mkFIFOF();
   rule compute;
      let v <- toGet(apipe).get();
      fifo.enq(f(v));
   endrule
   return toPipeOut(fifo);
endmodule

typedef (function Module #(PipeOut #(tb)) mkPipeOut(PipeOut#(ta) ifc)) PipeOutConstructor#(type ta, type tb);

typeclass ReducePipe#( numeric type n, type a);
   module [Module] mkReducePipe (PipeOutConstructor#(Tuple2#(a,a), a) combinepipe,
				 PipeOut#(Vector#(n,a)) inpipe,
				 PipeOut#(a) ifc);
   module [Module] mkReducePipes (PipeOutConstructor#(Tuple2#(a,a), a) combinepipe,
				  Vector#(n,PipeOut#(a)) inpipe,
				  PipeOut#(a) ifc);
endtypeclass
instance ReducePipe#(1, a);
   module [Module] mkReducePipe (PipeOutConstructor#(Tuple2#(a,a), a) combinepipe,
				 PipeOut#(Vector#(1,a)) inpipe,
				 PipeOut#(a) ifc);
      let pipe = mapPipe(head, inpipe);
      return pipe;
   endmodule
   module [Module] mkReducePipes (PipeOutConstructor#(Tuple2#(a,a), a) combinepipe,
				  Vector#(1,PipeOut#(a)) inpipes,
				  PipeOut#(a) ifc);
      return inpipes[0];
   endmodule
endinstance
instance ReducePipe#(2, a);
   module [Module] mkReducePipe (PipeOutConstructor#(Tuple2#(a,a), a) combinepipe,
				 PipeOut#(Vector#(2,a)) inpipe,
				 PipeOut#(a) ifc);
      function Tuple2#(a,a) foo(Vector#(2,a) invec); return tuple2(invec[0], invec[1]); endfunction
      PipeOut#(Tuple2#(a,a)) zippipe = mapPipe(foo, inpipe);
      let pipe <- combinepipe(zippipe);
      return pipe;
   endmodule
   module [Module] mkReducePipes (PipeOutConstructor#(Tuple2#(a,a), a) combinepipe,
				  Vector#(2,PipeOut#(a)) inpipes,
				  PipeOut#(a) ifc);
      let pipe <- combinepipe(zipPipeOut(inpipes[0], inpipes[1]));
      return pipe;
   endmodule
endinstance

instance ReducePipe#(n, a)
   provisos (Add#(TDiv#(n,2), a__, n),
	     Bits#(Vector#(TDiv#(n,2), a), b__),
	     ReducePipe#(TDiv#(n,2),a));
   module [Module] mkReducePipe (PipeOutConstructor#(Tuple2#(a,a), a) combinepipe,
				 PipeOut#(Vector#(n,a)) inpipe,
				 PipeOut#(a) ifc);
      FIFOF#(Vector#(TDiv#(n,2),a)) infifo0 <- mkFIFOF;
      FIFOF#(Vector#(TDiv#(n,2),a)) infifo1 <- mkFIFOF;
      rule splitinput;
	 let v = inpipe.first();
	 inpipe.deq();
	 infifo0.enq(takeAt(0, v));
	 infifo1.enq(takeAt(valueOf(TDiv#(n,2)), v));
      endrule
      PipeOut#(Vector#(TDiv#(n,2),a)) inpipe0 = toPipeOut(infifo0);
      PipeOut#(Vector#(TDiv#(n,2),a)) inpipe1 = toPipeOut(infifo1);

      PipeOut#(a) p0 <- mkReducePipe(combinepipe, inpipe0);
      PipeOut#(a) p1 <- mkReducePipe(combinepipe, inpipe1);

      PipeOut#(a) outpipe <- combinepipe(zipPipeOut(p0, p1));
      return outpipe;
   endmodule

   module [Module] mkReducePipes (PipeOutConstructor#(Tuple2#(a,a), a) combinepipe,
				  Vector#(n, PipeOut#(a)) inpipes,
				 PipeOut#(a) ifc);
      Vector#(TDiv#(n,2),PipeOut#(a)) pipes0 = takeAt(0, inpipes);
      Vector#(TDiv#(n,2),PipeOut#(a)) pipes1 = takeAt(valueOf(TDiv#(n,2)), inpipes);

      PipeOut#(a) p0 <- mkReducePipes(combinepipe, pipes0);
      PipeOut#(a) p1 <- mkReducePipes(combinepipe, pipes1);

      PipeOut#(a) outpipe <- combinepipe(zipPipeOut(p0, p1));
      return outpipe;
   endmodule
endinstance

interface FirstLastPipe#(type a);
   interface PipeOut#(Tuple2#(Bool,Bool)) pipe;
   method Action start(a count);
endinterface

module mkFirstLastPipe(FirstLastPipe#(a))
   provisos (Bits#(a,asz), Ord#(a), Arith#(a), Eq#(a));
   Reg#(a) countReg <- mkReg(0);
   Reg#(Bool) firstReg <- mkReg(False);
   Reg#(Bool) lastReg <- mkReg(False);
   interface PipeOut pipe;
      method Tuple2#(Bool, Bool) first();
	 return tuple2(firstReg, lastReg);
      endmethod
      method Action deq() if (countReg > 0);
	 firstReg <= False;
	 let c = countReg - 1;
	 if (c == 1)
	    lastReg <= True;
	 countReg <= c;
      endmethod
      method Bool notEmpty();
	 return countReg > 0;
      endmethod
   endinterface
   method Action start(a count) if (countReg == 0);
      firstReg <= True;
      lastReg <= False;
      countReg <= count;
   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 FIFOF::*;
import GetPut::*;
import Connectable::*;
import Vector::*;
import MIMO::*;
import DefaultValue::*;

interface PipeIn#(type a);
   method Action enq(a v);
   method Bool notFull();
endinterface

interface PipeOut#(type a);
   method a first();
   method Action deq();
   method Bool notEmpty();
endinterface

typeclass ToPipeIn#(type a, type b);
   function PipeIn#(a) toPipeIn(b in);
endtypeclass

typeclass ToPipeOut#(type a, type b);
   function PipeOut#(a) toPipeOut(b in);
endtypeclass

typeclass MkPipeOut#(type a, type b);
   module mkPipeOut#(b in)(PipeOut#(a));
endtypeclass

instance ToPipeIn#(a, FIFOF#(a));
   function PipeIn#(a) toPipeIn(FIFOF#(a) in);
      return (interface PipeIn#(a);
		 method enq = in.enq;
		 method notFull = in.notFull;
	      endinterface);
   endfunction
endinstance

instance ToPipeOut#(a, Reg#(a));
   function PipeOut#(a) toPipeOut(Reg#(a) in);
      return (interface PipeOut#(a);
		 method first(); return in; endmethod
		 method Action deq(); endmethod
		 method Bool notEmpty(); return False; endmethod
	      endinterface);
   endfunction
endinstance

instance ToPipeOut#(a, FIFOF#(a));
   function PipeOut#(a) toPipeOut(FIFOF#(a) in);
      return (interface PipeOut#(a);
		 method first = in.first;
		 method deq = in.deq;
		 method notEmpty = in.notEmpty;
	      endinterface);
   endfunction
endinstance

instance ToPipeOut#(Vector#(n,a), MIMO#(k,n,sz,a));
   function PipeOut#(Vector#(n,a)) toPipeOut(MIMO#(k,n,sz,a) in);
      return (interface PipeOut#(a);
		 method first = in.first;
		 method Action deq() if (in.deqReadyN(fromInteger(valueOf(n))));
		    in.deq(fromInteger(valueOf(n)));
		 endmethod
		 method Bool notEmpty();
		    return in.deqReadyN(fromInteger(valueOf(n)));
		 endmethod
	      endinterface);
   endfunction
endinstance

instance MkPipeOut#(a, Get#(a))
   provisos (Bits#(a, asz));
   module mkPipeOut#(Get#(a) in)(PipeOut#(a));
      FIFOF#(a) fifo <- mkFIFOF();
      rule connect;
	 let v <- in.get();
	 fifo.enq(v);
      endrule
      return toPipeOut(fifo);
   endmodule
endinstance

instance ToGet #(PipeOut #(a), a);
   function Get #(a) toGet (PipeOut #(a) po);
      return (interface Get;
                 method ActionValue #(a) get ();
                    po.deq ();
                    return po.first ();
                 endmethod
              endinterface);
   endfunction
endinstance

instance Connectable#(PipeOut#(a),Put#(a));
   module mkConnection#(PipeOut#(a) in, Put#(a) out)(Empty);
      rule connect;
	 let v = in.first;
	 in.deq();
	 out.put(v);
      endrule
   endmodule
endinstance

function PipeOut#(a) unvectorPipeOut(PipeOut#(Vector#(1,a)) in);
   return (interface PipeOut#(a);
	      method first = in.first[0];
	      method deq = in.deq;
	      method notEmpty = in.notEmpty;
	   endinterface);
endfunction

function PipeOut#(Tuple2#(a,b)) zipPipeOut(PipeOut#(a) ina, PipeOut#(b) inb);
      return (interface PipeOut#(Tuple2#(a,b));
		 method Tuple2#(a,b) first(); return tuple2(ina.first, inb.first); endmethod
		 method Action deq(); ina.deq(); inb.deq(); endmethod
		 method Bool notEmpty(); return ina.notEmpty() && inb.notEmpty(); endmethod
	      endinterface);
   endfunction

module mkFunnel#(PipeOut#(Vector#(mk,a)) in)(PipeOut#(Vector#(m, a)))
   provisos (Mul#(m, k, mk),
	     Bits#(a, asz),
	     Add#(a__, TMul#(asz, m), TMul#(asz, mk)),
	     Add#(1, b__, asz),
	     Add#(2, c__, mk),
	     Add#(d__, m, mk),
	     Add#(asz, m, e__),
	     Add#(asz, mk, f__));
   let m = fromInteger(valueOf(m));
   let mk = fromInteger(valueOf(mk));

   MIMOConfiguration cfg = defaultValue();
   MIMO#(mk, m, mk, a) mimo <- mkMIMO(cfg);
   rule consumer if (mimo.enqReadyN(mk));
      Vector#(mk, a) v = in.first();
      in.deq();
      mimo.enq(mk, v);
   endrule

   method Vector#(m, a) first() if (mimo.deqReadyN(m));
      return mimo.first();
   endmethod
   method Action deq() if (mimo.deqReadyN(m));
      mimo.deq(m);
   endmethod
   method notEmpty();
      return mimo.deqReadyN(m);
   endmethod
endmodule

module mkFunnel1#(PipeOut#(Vector#(k,a)) in)(PipeOut#(a))
   provisos (Bits#(a, asz), Log#(k,ksz));

   Reg#(Bit#(ksz)) selector <- mkReg(0);

   method a first();
      return in.first[selector];
   endmethod
   method Action deq();
      if (selector == fromInteger(valueOf(k)-1)) begin
	 in.deq();
	 selector <= 0;
      end
      else
	 selector <= selector + 1;
   endmethod
   method notEmpty();
      return in.notEmpty();
   endmethod
endmodule

typedef Vector#(k,PipeOut#(a)) FunnelPipe#(numeric type k, type a, numeric type bitsPerCycle);

// this relies on the fact that dead-code will remove unused fifo instantiations
// if you are paranoid, your module will look like mkUnFunnel1PipesPipelined
module mkFunnel1PipesPipelined#(Vector#(k,PipeOut#(a)) in) (FunnelPipe#(1,a,bpc))
   provisos (Log#(k, logk),
	     Bits#(a,a__),
	     Div#(logk,bpc,stages));
   Vector#(stages, Vector#(k, FIFOF#(a))) buffs  <- replicateM(replicateM(mkSizedFIFOF(1)));
   Vector#(TAdd#(stages,1), Vector#(k, PipeOut#(a))) infss = append(map(map(toPipeOut),buffs), cons(in,nil));
   for(Integer j = valueOf(stages); j > 0; j=j-1)
      for(Integer i = 0; i < 2**(j*valueOf(bpc)) && i < valueOf(k); i=i+1)
	 mkConnection(infss[j][i], toPut(buffs[j-1][i/(2**valueOf(bpc))]));
   return cons(infss[0][0],nil);
endmodule

function PipeOut#(b) pipeSecond(PipeOut#(Tuple2#(a,b)) x) =
   (interface PipeOut;
       method b first;
	  return tpl_2(x.first);
       endmethod
       method Action deq = x.deq;
       method Bool notEmpty = x.notEmpty;
    endinterface);

module mkUnFunnel1PipesPipelined#(PipeOut#(Tuple2#(Bit#(TLog#(k)),a)) in) (FunnelPipe#(k,a,bpc))
   provisos (Log#(k, logk),
	     Bits#(a,a__),
	     Add#(1,b__,k),
	     Div#(logk,bpc,stages));
   Vector#(k, PipeOut#(Tuple2#(Bit#(logk),a))) ins  = cons(in,replicate(?));
   Vector#(k, PipeOut#(Tuple2#(Bit#(logk),a))) outs = newVector;
   for(Integer j = 0; j < valueOf(stages); j=j+1) begin
      for(Integer i = 0; i < 2**(j*valueOf(bpc)); i=i+1) begin
	 Integer bits = (j == valueOf(stages)-1) ? valueOf(logk)-(j*valueOf(bpc)) : valueOf(bpc);
	 function Bit#(bpc) sh(Bit#(bpc) x) = x<<(valueOf(bpc)-bits);
	 for(Integer l = 0; l < 2**bits; l=l+1)  begin
	    let buff <- mkSizedFIFOF(1);
	    outs[(2**bits)*i+l] = toPipeOut(buff);
	    rule xfer if(tpl_1(ins[i].first)[(valueOf(logk)-1):(valueOf(logk)-valueOf(bpc))] == sh(fromInteger(l)));
	       match{.idx, .v} <- toGet(ins[i]).get;
	       buff.enq(tuple2(idx<<valueOf(bpc), v));
	    endrule
	 end
      end
      ins = outs;
   end
   return map(pipeSecond,outs);
endmodule

module mkUnfunnel#(PipeOut#(Vector#(m,a)) in)(PipeOut#(Vector#(mk, a)))
   provisos (Mul#(m, k, mk),
	     Bits#(a, asz),
	     Add#(1, b__, asz),
	     Add#(2, c__, mk),
	     Add#(d__, m, mk),
	     Add#(asz, m, e__),
	     Add#(asz, mk, f__));
   let m = fromInteger(valueOf(m));
   let mk = fromInteger(valueOf(mk));

   MIMOConfiguration cfg = defaultValue();
   MIMO#(m, mk, mk, a) mimo <- mkMIMO(cfg);
   rule consumer if (mimo.enqReadyN(m));
      Vector#(m, a) v = in.first();
      in.deq();
      mimo.enq(m, v);
   endrule

   method Vector#(mk, a) first() if (mimo.deqReadyN(mk));
      return mimo.first();
   endmethod
   method Action deq() if (mimo.deqReadyN(mk));
      mimo.deq(mk);
   endmethod
   method notEmpty();
      return mimo.deqReadyN(mk);
   endmethod
endmodule

module mkFunnelPipes#(Vector#(mk, PipeOut#(a)) ins)(Vector#(m, PipeOut#(a)))
   provisos (Mul#(m, k, mk),
	     Bits#(a, asz),
	     Log#(k,ksz)
      );
   let k = fromInteger(valueOf(k));
   let m = fromInteger(valueOf(m));
   let mk = fromInteger(valueOf(mk));

   Vector#(m, FIFOF#(a)) fifos <- replicateM(mkFIFOF);
   for (Integer i = 0; i < m; i = i+1) begin
      Reg#(Bit#(asz)) which <- mkReg(0);
      rule consumer;
	 let index = (which << valueOf(ksz)) + fromInteger(i);
	 let v <- toGet(ins[index]).get();
	 fifos[i].enq(v);
	 which <= (which + 1) % k;
      endrule
   end

   return map(toPipeOut, fifos);
endmodule

module mkFunnelPipes1#(Vector#(k, PipeOut#(a)) ins)(PipeOut#(a))
   provisos (Bits#(a, asz),
	     Log#(k,ksz)
      );
   let k = fromInteger(valueOf(k));

   Reg#(Bit#(ksz)) selector <- mkReg(0);

   method a first();
      return ins[selector].first();
   endmethod
   method Action deq();
      ins[selector].deq();
      if (selector == fromInteger(valueOf(k)-1))
	 selector <= 0;
   else
      selector <= selector + 1;
   endmethod
   method Bool notEmpty();
      return ins[selector].notEmpty();
   endmethod
endmodule

module mkUnfunnelPipes#(Vector#(m, PipeOut#(a)) ins)(Vector#(mk, PipeOut#(a)))
   provisos (Mul#(m, k, mk),
	     Log#(k,ksz),
	     Bits#(a, asz),
	     Add#(1, b__, asz)
	     );
   let m = fromInteger(valueOf(m));
   let k = fromInteger(valueOf(k));
   let mk = fromInteger(valueOf(mk));

   Vector#(mk, FIFOF#(a)) fifos <- replicateM(mkFIFOF);
   for (Integer i = 0; i < m; i = i + 1) begin
      Reg#(Bit#(asz)) which <- mkReg(0);
      rule consumer;
	 let index = (which << valueOf(ksz)) + fromInteger(i);
	 let v <- toGet(ins[i]).get();
	 fifos[index].enq(v);
	 which <= (which + 1) % k;
      endrule
   end
   return map(toPipeOut, fifos);
endmodule

module mkRepeat#(UInt#(n) repetitions, PipeOut#(a) inpipe)(PipeOut#(a));
   Reg#(UInt#(n)) count <- mkReg(0);
   method first = inpipe.first;
   method Action deq();
      let c = count + 1;
      if (count == (repetitions - 1)) begin
	 c = 0;
	 inpipe.deq();
      end
      count <= c;
   endmethod
   method notEmpty = inpipe.notEmpty;
endmodule

module mkForkVector#(PipeOut#(a) inpipe)(Vector#(n, PipeOut#(a)))
   provisos (Bits#(a, asz));
   Vector#(n, FIFOF#(a)) fifos <- replicateM(mkFIFOF());
   rule forkelts;
      let v = inpipe.first();
      inpipe.deq;
      for (Integer i = 0; i < valueOf(n); i = i + 1) begin
	 fifos[i].enq(v);
      end
   endrule
   return map(toPipeOut, fifos);
endmodule

module mkSizedForkVector#(Integer size, PipeOut#(a) inpipe)(Vector#(n, PipeOut#(a)))
   provisos (Bits#(a, asz));
   Vector#(n, FIFOF#(a)) fifos <- replicateM(mkSizedFIFOF(size));
   rule forkelts;
      let v = inpipe.first();
      inpipe.deq;
      for (Integer i = 0; i < valueOf(n); i = i + 1) begin
	 fifos[i].enq(v);
      end
   endrule
   return map(toPipeOut, fifos);
endmodule

module mkJoin#(function c f(a av, b bv), PipeOut#(a) apipe, PipeOut#(b) bpipe)(PipeOut#(c));
   method c first();
      let av = apipe.first();
      let bv = bpipe.first();
      return f(av, bv);
   endmethod
   method Action deq();
      apipe.deq();
      bpipe.deq();
   endmethod
   method Bool notEmpty();
      return apipe.notEmpty() && bpipe.notEmpty();
   endmethod
endmodule

module mkJoinVector#(function b f(Vector#(n, a) av), Vector#(n, PipeOut#(a)) apipes)(PipeOut#(b))
   provisos (Bits#(Vector#(n,a),vasz));
   method b first();
      function a getfirst(PipeOut#(a) pipein); return pipein.first(); endfunction
      Vector#(n,a) vec = map(getfirst, apipes);
      return f(vec);
   endmethod
   method Action deq();
      function a getfirst(PipeOut#(a) pipein); return pipein.first(); endfunction
      for (Integer i = 0; i < valueOf(n); i = i + 1)
	 apipes[i].deq();
   endmethod
   method Bool notEmpty();
      function Bool getNotEmpty(PipeOut#(a) pipein); return pipein.notEmpty(); endfunction
      function Bool myand(Bool a, Bool b); return a && b; endfunction
      return foldl(myand, True, map(getNotEmpty, apipes));
   endmethod
endmodule

function PipeOut#(b) mapPipe(function b f(a av), PipeOut#(a) apipe);
   return (interface PipeOut#(b);
      method b first();
	 let av = apipe.first();
	 return f(av);
      endmethod
      method Action deq();
	 apipe.deq();
      endmethod
      method Bool notEmpty();
	 return apipe.notEmpty();
      endmethod
      endinterface);
endfunction

// buffered version of mapPipe
module mkMap#(function b f(a av), PipeOut#(a) apipe)(PipeOut#(b))
   provisos (Bits#(b,bsz));
   FIFOF#(b) fifo <- mkFIFOF();
   rule compute;
      let v <- toGet(apipe).get();
      fifo.enq(f(v));
   endrule
   return toPipeOut(fifo);
endmodule

typedef (function Module #(PipeOut #(tb)) mkPipeOut(PipeOut#(ta) ifc)) PipeOutConstructor#(type ta, type tb);

typeclass ReducePipe#( numeric type n, type a);
   module [Module] mkReducePipe (PipeOutConstructor#(Tuple2#(a,a), a) combinepipe,
				 PipeOut#(Vector#(n,a)) inpipe,
				 PipeOut#(a) ifc);
   module [Module] mkReducePipes (PipeOutConstructor#(Tuple2#(a,a), a) combinepipe,
				  Vector#(n,PipeOut#(a)) inpipe,
				  PipeOut#(a) ifc);
endtypeclass
instance ReducePipe#(1, a);
   module [Module] mkReducePipe (PipeOutConstructor#(Tuple2#(a,a), a) combinepipe,
				 PipeOut#(Vector#(1,a)) inpipe,
				 PipeOut#(a) ifc);
      let pipe = mapPipe(head, inpipe);
      return pipe;
   endmodule
   module [Module] mkReducePipes (PipeOutConstructor#(Tuple2#(a,a), a) combinepipe,
				  Vector#(1,PipeOut#(a)) inpipes,
				  PipeOut#(a) ifc);
      return inpipes[0];
   endmodule
endinstance
instance ReducePipe#(2, a);
   module [Module] mkReducePipe (PipeOutConstructor#(Tuple2#(a,a), a) combinepipe,
				 PipeOut#(Vector#(2,a)) inpipe,
				 PipeOut#(a) ifc);
      function Tuple2#(a,a) foo(Vector#(2,a) invec); return tuple2(invec[0], invec[1]); endfunction
      PipeOut#(Tuple2#(a,a)) zippipe = mapPipe(foo, inpipe);
      let pipe <- combinepipe(zippipe);
      return pipe;
   endmodule
   module [Module] mkReducePipes (PipeOutConstructor#(Tuple2#(a,a), a) combinepipe,
				  Vector#(2,PipeOut#(a)) inpipes,
				  PipeOut#(a) ifc);
      let pipe <- combinepipe(zipPipeOut(inpipes[0], inpipes[1]));
      return pipe;
   endmodule
endinstance

instance ReducePipe#(n, a)
   provisos (Add#(TDiv#(n,2), a__, n),
	     Bits#(Vector#(TDiv#(n,2), a), b__),
	     ReducePipe#(TDiv#(n,2),a));
   module [Module] mkReducePipe (PipeOutConstructor#(Tuple2#(a,a), a) combinepipe,
				 PipeOut#(Vector#(n,a)) inpipe,
				 PipeOut#(a) ifc);
      FIFOF#(Vector#(TDiv#(n,2),a)) infifo0 <- mkFIFOF;
      FIFOF#(Vector#(TDiv#(n,2),a)) infifo1 <- mkFIFOF;
      rule splitinput;
	 let v = inpipe.first();
	 inpipe.deq();
	 infifo0.enq(takeAt(0, v));
	 infifo1.enq(takeAt(valueOf(TDiv#(n,2)), v));
      endrule
      PipeOut#(Vector#(TDiv#(n,2),a)) inpipe0 = toPipeOut(infifo0);
      PipeOut#(Vector#(TDiv#(n,2),a)) inpipe1 = toPipeOut(infifo1);

      PipeOut#(a) p0 <- mkReducePipe(combinepipe, inpipe0);
      PipeOut#(a) p1 <- mkReducePipe(combinepipe, inpipe1);

      PipeOut#(a) outpipe <- combinepipe(zipPipeOut(p0, p1));
      return outpipe;
   endmodule

   module [Module] mkReducePipes (PipeOutConstructor#(Tuple2#(a,a), a) combinepipe,
				  Vector#(n, PipeOut#(a)) inpipes,
				 PipeOut#(a) ifc);
      Vector#(TDiv#(n,2),PipeOut#(a)) pipes0 = takeAt(0, inpipes);
      Vector#(TDiv#(n,2),PipeOut#(a)) pipes1 = takeAt(valueOf(TDiv#(n,2)), inpipes);

      PipeOut#(a) p0 <- mkReducePipes(combinepipe, pipes0);
      PipeOut#(a) p1 <- mkReducePipes(combinepipe, pipes1);

      PipeOut#(a) outpipe <- combinepipe(zipPipeOut(p0, p1));
      return outpipe;
   endmodule
endinstance

interface FirstLastPipe#(type a);
   interface PipeOut#(Tuple2#(Bool,Bool)) pipe;
   method Action start(a count);
endinterface

module mkFirstLastPipe(FirstLastPipe#(a))
   provisos (Bits#(a,asz), Ord#(a), Arith#(a), Eq#(a));
   Reg#(a) countReg <- mkReg(0);
   Reg#(Bool) firstReg <- mkReg(False);
   Reg#(Bool) lastReg <- mkReg(False);
   interface PipeOut pipe;
      method Tuple2#(Bool, Bool) first();
	 return tuple2(firstReg, lastReg);
      endmethod
      method Action deq() if (countReg > 0);
	 firstReg <= False;
	 let c = countReg - 1;
	 if (c == 1)
	    lastReg <= True;
	 countReg <= c;
      endmethod
      method Bool notEmpty();
	 return countReg > 0;
      endmethod
   endinterface
   method Action start(a count) if (countReg == 0);
      firstReg <= True;
      lastReg <= False;
      countReg <= count;
   endmethod
endmodule


use mkPcieDmaTop in memcpy

use mkPcieDmaTop in memcpy

// bsv libraries
import SpecialFIFOs::*;
import Vector::*;
import StmtFSM::*;
import FIFO::*;

// for PCIE
import Connectable       :: *;
import Xilinx            :: *;
import XilinxPCIE        :: *;
import Xilinx7PcieBridge :: *;
import PcieToAxiBridge   :: *;

// portz libraries
import AxiMasterSlave::*;
import Directory::*;
import CtrlMux::*;
import Portal::*;
import Leds::*;
import BlueScope::*;
import AxiRDMA::*;
import BsimRDMA::*;
import PortalMemory::*;
import PortalRMemory::*;

// generated by tool
import MemcpyRequestWrapper::*;
import BlueScopeRequestWrapper::*;
import DMARequestWrapper::*;
import MemcpyIndicationProxy::*;
import BlueScopeIndicationProxy::*;
import DMAIndicationProxy::*;

// defined by user
import Memcpy::*;

module mkPortalDmaTop(PortalDmaTop);

   DMAIndicationProxy dmaIndicationProxy <- mkDMAIndicationProxy(9);
   // dma read channel 0 is reserved for memcpy read path
   // Max burst 16
   DMAReadBuffer#(64,16) dma_stream_read_chan <- mkDMAReadBuffer();

   // dma write channel 0 is reserved for memcpy write path
   // Max burst 16
   DMAWriteBuffer#(64,16) dma_stream_write_chan <- mkDMAWriteBuffer();

   // dma read channel 1 is reserved for debug read path
   // Max burst 1 because it only reads one word at a time
   DMAReadBuffer#(64,1) dma_word_read_chan <- mkDMAReadBuffer();

   // dma write channel 1 is reserved for Bluescope output
   // Max burst 16
   DMAWriteBuffer#(64,16) dma_debug_write_chan <- mkDMAWriteBuffer();

   Vector#(2,  DMAReadClient#(64))   readClients = newVector();
   readClients[0] = dma_stream_read_chan.dmaClient;
   readClients[1] = dma_word_read_chan.dmaClient;

   Vector#(2, DMAWriteClient#(64)) writeClients = newVector();
   writeClients[0] = dma_stream_write_chan.dmaClient;
   writeClients[1] = dma_debug_write_chan.dmaClient;

`ifdef BSIM
   BsimDMAServer#(64)     dma <- mkBsimDMAServer(dmaIndicationProxy.ifc, readClients, writeClients);
`else
   Integer               numRequests = 8;
   AxiDMAServer#(64,8)   dma <- mkAxiDMAServer(dmaIndicationProxy.ifc, numRequests, readClients, writeClients);
`endif

   DMARequestWrapper dmaRequestWrapper <- mkDMARequestWrapper(1005,dma.request);

   BlueScopeIndicationProxy blueScopeIndicationProxy <- mkBlueScopeIndicationProxy(8);
   BlueScopeInternal bsi <- mkBlueScopeInternal(32, dma_debug_write_chan.dmaServer, blueScopeIndicationProxy.ifc);
   BlueScopeRequestWrapper blueScopeRequestWrapper <- mkBlueScopeRequestWrapper(1003,bsi.requestIfc);

   MemcpyIndicationProxy memcpyIndicationProxy <- mkMemcpyIndicationProxy(7);
   MemcpyRequest memcpyRequest <- mkMemcpyRequest(memcpyIndicationProxy.ifc, dma_stream_read_chan.dmaServer,
						  dma_stream_write_chan.dmaServer,
						  dma_word_read_chan.dmaServer,
						  bsi);
   MemcpyRequestWrapper memcpyRequestWrapper <- mkMemcpyRequestWrapper(1008,memcpyRequest);

   Vector#(6,StdPortal) portals;
   portals[0] = memcpyRequestWrapper.portalIfc;
   portals[1] = memcpyIndicationProxy.portalIfc;
   portals[2] = blueScopeRequestWrapper.portalIfc;
   portals[3] = blueScopeIndicationProxy.portalIfc;
   portals[4] = dmaRequestWrapper.portalIfc;
   portals[5] = dmaIndicationProxy.portalIfc;

   Directory dir <- mkDirectory(portals);
   Vector#(1,StdPortal) directories;
   directories[0] = dir.portalIfc;

   // when constructing ctrl and interrupt muxes, directories must be the first argument
   let ctrl_mux <- mkAxiSlaveMux(directories,portals);
   let interrupt_mux <- mkInterruptMux(directories,portals);
`ifndef BSIM
   let axi_master <- mkAxi3Master(dma.m_axi);
`endif

   interface ReadOnly interrupt = interrupt_mux;
   interface StdAxi3Slave ctrl = ctrl_mux;
`ifndef BSIM
   interface StdAxi3Master m_axi = axi_master;
`endif
endmodule

module mkZynqTop(PortalDmaTop);
   let top <- mkPortalDmaTop();
   return top;
endmodule

import "BDPI" function Action      initPortal(Bit#(32) d);
import "BDPI" function Bool                    writeReq();
import "BDPI" function ActionValue#(Bit#(32)) writeAddr();
import "BDPI" function ActionValue#(Bit#(32)) writeData();
import "BDPI" function Bool                     readReq();
import "BDPI" function ActionValue#(Bit#(32))  readAddr();
import "BDPI" function Action        readData(Bit#(32) d);

module mkBsimTop();
   PortalDmaTop top <- mkPortalDmaTop();
   let wf <- mkPipelineFIFO;
   let init_seq = (action
		      initPortal(0);
		      initPortal(1);
		      initPortal(2);
		      initPortal(3);
		      initPortal(4);
		      initPortal(5);
		      initPortal(6);
		      initPortal(7);
                   endaction);
   let init_fsm <- mkOnce(init_seq);
   rule init_rule;
      init_fsm.start;
   endrule
   rule wrReq (writeReq());
      let wa <- writeAddr;
      let wd <- writeData;
      top.ctrl.write.writeAddr(wa,0,0,0,0,0,0);
      wf.enq(wd);
   endrule
   rule wrData;
      wf.deq;
      top.ctrl.write.writeData(wf.first,0,0,0);
   endrule
   rule rdReq (readReq());
      let ra <- readAddr;
      top.ctrl.read.readAddr(ra,0,0,0,0,0,0);
   endrule
   rule rdResp;
      let rd <- top.ctrl.read.readData;
      readData(rd);
   endrule
endmodule

(* no_default_clock, no_default_reset *)
module [Module] mkPcieTop #(Clock pci_sys_clk_p, Clock pci_sys_clk_n,
                          Clock sys_clk_p,     Clock sys_clk_n,
                          Reset pci_sys_reset_n)
                         (VC707_FPGA);

   let contentId = 64'h4563686f;

   let top <- mkPcieDmaTop(pci_sys_clk_p, pci_sys_clk_n, sys_clk_p, sys_clk_n, pci_sys_reset_n, contentId, mkPortalDmaTop);
   return top;
endmodule: mkPcieTop

// bsv libraries
import SpecialFIFOs::*;
import Vector::*;
import StmtFSM::*;
import FIFO::*;

// for PCIE
import Connectable       :: *;
import Xilinx            :: *;
import XilinxPCIE        :: *;
import Xilinx7PcieBridge :: *;
import PcieToAxiBridge   :: *;

// portz libraries
import AxiMasterSlave::*;
import Directory::*;
import CtrlMux::*;
import Portal::*;
import Leds::*;
import BlueScope::*;
import AxiRDMA::*;
import BsimRDMA::*;
import PortalMemory::*;
import PortalRMemory::*;

// generated by tool
import MemcpyRequestWrapper::*;
import BlueScopeRequestWrapper::*;
import DMARequestWrapper::*;
import MemcpyIndicationProxy::*;
import BlueScopeIndicationProxy::*;
import DMAIndicationProxy::*;

// defined by user
import Memcpy::*;

interface AxiTop;
   interface StdAxi3Slave     ctrl;
   interface StdAxi3Master    m_axi;
   interface ReadOnly#(Bool)  interrupt;
   interface LEDS             leds;
endinterface

module mkAxiTop(Top);

   DMAIndicationProxy dmaIndicationProxy <- mkDMAIndicationProxy(9);
   // dma read channel 0 is reserved for memcpy read path
   // Max burst 16
   DMAReadBuffer#(64,16) dma_stream_read_chan <- mkDMAReadBuffer();

   // dma write channel 0 is reserved for memcpy write path
   // Max burst 16
   DMAWriteBuffer#(64,16) dma_stream_write_chan <- mkDMAWriteBuffer();

   // dma read channel 1 is reserved for debug read path
   // Max burst 1 because it only reads one word at a time
   DMAReadBuffer#(64,1) dma_word_read_chan <- mkDMAReadBuffer();

   // dma write channel 1 is reserved for Bluescope output
   // Max burst 16
   DMAWriteBuffer#(64,16) dma_debug_write_chan <- mkDMAWriteBuffer();

   Vector#(2,  DMAReadClient#(64))   readClients = newVector();
   readClients[0] = dma_stream_read_chan.dmaClient;
   readClients[1] = dma_word_read_chan.dmaClient;

   Vector#(2, DMAWriteClient#(64)) writeClients = newVector();
   writeClients[0] = dma_stream_write_chan.dmaClient;
   writeClients[1] = dma_debug_write_chan.dmaClient;

`ifdef BSIM
   BsimDMAServer#(64)     dma <- mkBsimDMAServer(dmaIndicationProxy.ifc, readClients, writeClients);
`else
   Integer               numRequests = 8;
   AxiDMAServer#(64,8)   dma <- mkAxiDMAServer(dmaIndicationProxy.ifc, numRequests, readClients, writeClients);
`endif

   DMARequestWrapper dmaRequestWrapper <- mkDMARequestWrapper(1005,dma.request);

   BlueScopeIndicationProxy blueScopeIndicationProxy <- mkBlueScopeIndicationProxy(8);
   BlueScopeInternal bsi <- mkBlueScopeInternal(32, dma_debug_write_chan.dmaServer, blueScopeIndicationProxy.ifc);
   BlueScopeRequestWrapper blueScopeRequestWrapper <- mkBlueScopeRequestWrapper(1003,bsi.requestIfc);

   MemcpyIndicationProxy memcpyIndicationProxy <- mkMemcpyIndicationProxy(7);
   MemcpyRequest memcpyRequest <- mkMemcpyRequest(memcpyIndicationProxy.ifc, dma_stream_read_chan.dmaServer,
						  dma_stream_write_chan.dmaServer,
						  dma_word_read_chan.dmaServer,
						  bsi);
   MemcpyRequestWrapper memcpyRequestWrapper <- mkMemcpyRequestWrapper(1008,memcpyRequest);

   Vector#(6,StdPortal) portals;
   portals[0] = memcpyRequestWrapper.portalIfc;
   portals[1] = memcpyIndicationProxy.portalIfc;
   portals[2] = blueScopeRequestWrapper.portalIfc;
   portals[3] = blueScopeIndicationProxy.portalIfc;
   portals[4] = dmaRequestWrapper.portalIfc;
   portals[5] = dmaIndicationProxy.portalIfc;

   Directory dir <- mkDirectory(portals);
   Vector#(1,StdPortal) directories;
   directories[0] = dir.portalIfc;

   // when constructing ctrl and interrupt muxes, directories must be the first argument
   let ctrl_mux <- mkAxiSlaveMux(directories,portals);
   let interrupt_mux <- mkInterruptMux(directories,portals);
`ifndef BSIM
   let axi_master <- mkAxi3Master(dma.m_axi);
`endif

   interface ReadOnly interrupt = interrupt_mux;
   interface StdAxi3Slave ctrl = ctrl_mux;
`ifndef BSIM
   interface StdAxi3Master m_axi = axi_master;
`endif
endmodule

module mkZynqTop(AxiTop);
   let top <- mkAxiTop();
   return top;
endmodule

import "BDPI" function Action      initPortal(Bit#(32) d);
import "BDPI" function Bool                    writeReq();
import "BDPI" function ActionValue#(Bit#(32)) writeAddr();
import "BDPI" function ActionValue#(Bit#(32)) writeData();
import "BDPI" function Bool                     readReq();
import "BDPI" function ActionValue#(Bit#(32))  readAddr();
import "BDPI" function Action        readData(Bit#(32) d);

module mkBsimTop();
   Top top <- mkZynqTop;
   let wf <- mkPipelineFIFO;
   let init_seq = (action
		      initPortal(0);
		      initPortal(1);
		      initPortal(2);
		      initPortal(3);
		      initPortal(4);
		      initPortal(5);
		      initPortal(6);
		      initPortal(7);
                   endaction);
   let init_fsm <- mkOnce(init_seq);
   rule init_rule;
      init_fsm.start;
   endrule
   rule wrReq (writeReq());
      let wa <- writeAddr;
      let wd <- writeData;
      top.ctrl.write.writeAddr(wa,0,0,0,0,0,0);
      wf.enq(wd);
   endrule
   rule wrData;
      wf.deq;
      top.ctrl.write.writeData(wf.first,0,0,0);
   endrule
   rule rdReq (readReq());
      let ra <- readAddr;
      top.ctrl.read.readAddr(ra,0,0,0,0,0,0);
   endrule
   rule rdResp;
      let rd <- top.ctrl.read.readData;
      readData(rd);
   endrule
endmodule

(* no_default_clock, no_default_reset *)
module mkPcieTop #(Clock pci_sys_clk_p, Clock pci_sys_clk_n,
                          Clock sys_clk_p,     Clock sys_clk_n,
                          Reset pci_sys_reset_n)
                         (VC707_FPGA);

   let contentId = 64'h4563686f;

   X7PcieBridgeIfc#(8) x7pcie <- mkX7PcieBridge( pci_sys_clk_p, pci_sys_clk_n, sys_clk_p, sys_clk_n, pci_sys_reset_n,
                                                 contentId );

   Reg#(Bool) interruptRequested <- mkReg(False, clocked_by x7pcie.clock125, reset_by x7pcie.reset125);

   // instantiate user portals
   let axiTop <- mkAxiTop(clocked_by x7pcie.clock125, reset_by x7pcie.reset125);
   mkConnection(x7pcie.portal0, axiTop.ctrl, clocked_by x7pcie.clock125, reset_by x7pcie.reset125);

   AxiSlaveEngine#(64,8) axiSlaveEngine <- mkAxiSlaveEngine(x7pcie.pciId(), clocked_by x7pcie.clock125, reset_by x7pcie.reset125);
   mkConnection(tpl_1(x7pcie.slave), tpl_2(axiSlaveEngine.tlps), clocked_by x7pcie.clock125, reset_by x7pcie.reset125);
   mkConnection(tpl_1(axiSlaveEngine.tlps), tpl_2(x7pcie.slave), clocked_by x7pcie.clock125, reset_by x7pcie.reset125);
   mkConnection(axiTop.m_axi, axiSlaveEngine.slave3, clocked_by x7pcie.clock125, reset_by x7pcie.reset125);

   rule requestInterrupt;
      if (axiTop.interrupt && !interruptRequested)
	 x7pcie.interrupt();
      interruptRequested <= interrupt;
   endrule

   interface pcie = x7pcie.pcie;
   //interface ddr3 = x7pcie.ddr3;
   method leds = zeroExtend({  pack(x7pcie.isCalibrated)
			     , pack(True)
			     , pack(False)
			     , pack(x7pcie.isLinkUp)
			     });

endmodule: mkPcieTop


removed Mac wrapper

removed Mac wrapper

/*
   ./importbvi.py
   -o
   ALTERA_MAC_WRAPPER.bsv
   -I
   MacWrap
   -P
   MacWrap
   -c
   p0_tx_clk_clk
   -c
   p1_tx_clk_clk
   -c
   p2_tx_clk_clk
   -c
   p3_tx_clk_clk
   -c
   p0_rx_clk_clk
   -c
   p1_rx_clk_clk
   -c
   p2_rx_clk_clk
   -c
   p3_rx_clk_clk
   -c
   mgmt_clk_clk
   -r
   mgmt_reset_reset_n
   -r
   jtag_reset_reset
   -r
   p0_tx_reset_reset_n
   -r
   p1_tx_reset_reset_n
   -r
   p2_tx_reset_reset_n
   -r
   p3_tx_reset_reset_n
   -r
   p0_rx_reset_reset_n
   -r
   p1_rx_reset_reset_n
   -r
   p2_rx_reset_reset_n
   -r
   p3_rx_reset_reset_n
   -f
   p0_tx
   -f
   p0_rx
   -f
   p1_tx
   -f
   p1_rx
   -f
   p2_tx
   -f
   p2_rx
   -f
   p3_tx
   -f
   p3_rx
   -f
   p0_xgmii
   -f
   p1_xgmii
   -f
   p2_xgmii
   -f
   p3_xgmii
   -f
   p0_link_fault
   -f
   p1_link_fault
   -f
   p2_link_fault
   -f
   p3_link_fault
   ../../out/de5/synthesis/altera_mac.v
*/

import Clocks::*;
import DefaultValue::*;
import XilinxCells::*;
import GetPut::*;

(* always_ready, always_enabled *)
interface MacwrapJtag;
    method Reset     reset_reset();
endinterface
(* always_ready, always_enabled *)
(* always_ready, always_enabled *)
interface MacwrapP0_link_fault;
    method Bit#(2)     status_data();
endinterface
(* always_ready, always_enabled *)
interface MacwrapP0_rx;
    method Bit#(64)     fifo_out_data();
    method Bit#(3)     fifo_out_empty();
    method Bit#(1)     fifo_out_endofpacket();
    method Bit#(6)     fifo_out_error();
    method Action      fifo_out_ready(Bit#(1) v);
    method Bit#(1)     fifo_out_startofpacket();
    method Bit#(1)     fifo_out_valid();
    method Bit#(40)     status_data();
    method Bit#(7)     status_error();
    method Bit#(1)     status_valid();
endinterface
(* always_ready, always_enabled *)
interface MacwrapP0_tx;
    method Action      fifo_in_data(Bit#(64) v);
    method Action      fifo_in_empty(Bit#(3) v);
    method Action      fifo_in_endofpacket(Bit#(1) v);
    method Action      fifo_in_error(Bit#(1) v);
    method Bit#(1)     fifo_in_ready();
    method Action      fifo_in_startofpacket(Bit#(1) v);
    method Action      fifo_in_valid(Bit#(1) v);
    method Bit#(40)     status_data();
    method Bit#(7)     status_error();
    method Bit#(1)     status_valid();
endinterface
(* always_ready, always_enabled *)
interface MacwrapP0_xgmii;
    method Action      rx_data(Bit#(72) v);
    method Bit#(72)     tx_data();
endinterface
(* always_ready, always_enabled *)
interface MacwrapP1_link_fault;
    method Bit#(2)     status_data();
endinterface
(* always_ready, always_enabled *)
interface MacwrapP1_rx;
    method Bit#(64)     fifo_out_data();
    method Bit#(3)     fifo_out_empty();
    method Bit#(1)     fifo_out_endofpacket();
    method Bit#(6)     fifo_out_error();
    method Action      fifo_out_ready(Bit#(1) v);
    method Bit#(1)     fifo_out_startofpacket();
    method Bit#(1)     fifo_out_valid();
    method Bit#(40)     status_data();
    method Bit#(7)     status_error();
    method Bit#(1)     status_valid();
endinterface
(* always_ready, always_enabled *)
interface MacwrapP1_tx;
    method Action      fifo_in_data(Bit#(64) v);
    method Action      fifo_in_empty(Bit#(3) v);
    method Action      fifo_in_endofpacket(Bit#(1) v);
    method Action      fifo_in_error(Bit#(1) v);
    method Bit#(1)     fifo_in_ready();
    method Action      fifo_in_startofpacket(Bit#(1) v);
    method Action      fifo_in_valid(Bit#(1) v);
    method Bit#(40)     status_data();
    method Bit#(7)     status_error();
    method Bit#(1)     status_valid();
endinterface
(* always_ready, always_enabled *)
interface MacwrapP1_xgmii;
    method Action      rx_data(Bit#(72) v);
    method Bit#(72)     tx_data();
endinterface
(* always_ready, always_enabled *)
interface MacwrapP2_link_fault;
    method Bit#(2)     status_data();
endinterface
(* always_ready, always_enabled *)
interface MacwrapP2_rx;
    method Bit#(64)     fifo_out_data();
    method Bit#(3)     fifo_out_empty();
    method Bit#(1)     fifo_out_endofpacket();
    method Bit#(6)     fifo_out_error();
    method Action      fifo_out_ready(Bit#(1) v);
    method Bit#(1)     fifo_out_startofpacket();
    method Bit#(1)     fifo_out_valid();
    method Bit#(40)     status_data();
    method Bit#(7)     status_error();
    method Bit#(1)     status_valid();
endinterface
(* always_ready, always_enabled *)
interface MacwrapP2_tx;
    method Action      fifo_in_data(Bit#(64) v);
    method Action      fifo_in_empty(Bit#(3) v);
    method Action      fifo_in_endofpacket(Bit#(1) v);
    method Action      fifo_in_error(Bit#(1) v);
    method Bit#(1)     fifo_in_ready();
    method Action      fifo_in_startofpacket(Bit#(1) v);
    method Action      fifo_in_valid(Bit#(1) v);
    method Bit#(40)     status_data();
    method Bit#(7)     status_error();
    method Bit#(1)     status_valid();
endinterface
(* always_ready, always_enabled *)
interface MacwrapP2_xgmii;
    method Action      rx_data(Bit#(72) v);
    method Bit#(72)     tx_data();
endinterface
(* always_ready, always_enabled *)
interface MacwrapP3_link_fault;
    method Bit#(2)     status_data();
endinterface
(* always_ready, always_enabled *)
interface MacwrapP3_rx;
    method Bit#(64)     fifo_out_data();
    method Bit#(3)     fifo_out_empty();
    method Bit#(1)     fifo_out_endofpacket();
    method Bit#(6)     fifo_out_error();
    method Action      fifo_out_ready(Bit#(1) v);
    method Bit#(1)     fifo_out_startofpacket();
    method Bit#(1)     fifo_out_valid();
    method Bit#(40)     status_data();
    method Bit#(7)     status_error();
    method Bit#(1)     status_valid();
endinterface
(* always_ready, always_enabled *)
interface MacwrapP3_tx;
    method Action      fifo_in_data(Bit#(64) v);
    method Action      fifo_in_empty(Bit#(3) v);
    method Action      fifo_in_endofpacket(Bit#(1) v);
    method Action      fifo_in_error(Bit#(1) v);
    method Bit#(1)     fifo_in_ready();
    method Action      fifo_in_startofpacket(Bit#(1) v);
    method Action      fifo_in_valid(Bit#(1) v);
    method Bit#(40)     status_data();
    method Bit#(7)     status_error();
    method Bit#(1)     status_valid();
endinterface
(* always_ready, always_enabled *)
interface MacwrapP3_xgmii;
    method Action      rx_data(Bit#(72) v);
    method Bit#(72)     tx_data();
endinterface
(* always_ready, always_enabled *)
interface MacWrap;
    interface MacwrapJtag     jtag;
    interface MacwrapP0_link_fault     p0_link_fault;
    interface MacwrapP0_rx     p0_rx;
    interface MacwrapP0_tx     p0_tx;
    interface MacwrapP0_xgmii     p0_xgmii;
    interface MacwrapP1_link_fault     p1_link_fault;
    interface MacwrapP1_rx     p1_rx;
    interface MacwrapP1_tx     p1_tx;
    interface MacwrapP1_xgmii     p1_xgmii;
    interface MacwrapP2_link_fault     p2_link_fault;
    interface MacwrapP2_rx     p2_rx;
    interface MacwrapP2_tx     p2_tx;
    interface MacwrapP2_xgmii     p2_xgmii;
    interface MacwrapP3_link_fault     p3_link_fault;
    interface MacwrapP3_rx     p3_rx;
    interface MacwrapP3_tx     p3_tx;
    interface MacwrapP3_xgmii     p3_xgmii;
endinterface
import "BVI" altera_mac =
module mkMacWrap#(Clock mgmt_clk_clk, Clock p0_rx_clk_clk, Clock p0_tx_clk_clk, Clock p1_rx_clk_clk, Clock p1_tx_clk_clk, Clock p2_rx_clk_clk, Clock p2_tx_clk_clk, Clock p3_rx_clk_clk, Clock p3_tx_clk_clk, Reset mgmt_clk_clk_reset, Reset mgmt_reset_reset_n, Reset p0_rx_clk_clk_reset, Reset p0_rx_reset_reset_n, Reset p0_tx_clk_clk_reset, Reset p0_tx_reset_reset_n, Reset p1_rx_clk_clk_reset, Reset p1_rx_reset_reset_n, Reset p1_tx_clk_clk_reset, Reset p1_tx_reset_reset_n, Reset p2_rx_clk_clk_reset, Reset p2_rx_reset_reset_n, Reset p2_tx_clk_clk_reset, Reset p2_tx_reset_reset_n, Reset p3_rx_clk_clk_reset, Reset p3_rx_reset_reset_n, Reset p3_tx_clk_clk_reset, Reset p3_tx_reset_reset_n)(MacWrap);
    default_clock clk();
    default_reset rst();
        input_clock mgmt_clk_clk(mgmt_clk_clk) = mgmt_clk_clk;
        input_reset mgmt_clk_clk_reset() = mgmt_clk_clk_reset; /* from clock*/
        input_reset mgmt_reset_reset_n(mgmt_reset_reset_n) = mgmt_reset_reset_n;
        input_clock p0_rx_clk_clk(p0_rx_clk_clk) = p0_rx_clk_clk;
        input_reset p0_rx_clk_clk_reset() = p0_rx_clk_clk_reset; /* from clock*/
        input_reset p0_rx_reset_reset_n(p0_rx_reset_reset_n) = p0_rx_reset_reset_n;
        input_clock p0_tx_clk_clk(p0_tx_clk_clk) = p0_tx_clk_clk;
        input_reset p0_tx_clk_clk_reset() = p0_tx_clk_clk_reset; /* from clock*/
        input_reset p0_tx_reset_reset_n(p0_tx_reset_reset_n) = p0_tx_reset_reset_n;
        input_clock p1_rx_clk_clk(p1_rx_clk_clk) = p1_rx_clk_clk;
        input_reset p1_rx_clk_clk_reset() = p1_rx_clk_clk_reset; /* from clock*/
        input_reset p1_rx_reset_reset_n(p1_rx_reset_reset_n) = p1_rx_reset_reset_n;
        input_clock p1_tx_clk_clk(p1_tx_clk_clk) = p1_tx_clk_clk;
        input_reset p1_tx_clk_clk_reset() = p1_tx_clk_clk_reset; /* from clock*/
        input_reset p1_tx_reset_reset_n(p1_tx_reset_reset_n) = p1_tx_reset_reset_n;
        input_clock p2_rx_clk_clk(p2_rx_clk_clk) = p2_rx_clk_clk;
        input_reset p2_rx_clk_clk_reset() = p2_rx_clk_clk_reset; /* from clock*/
        input_reset p2_rx_reset_reset_n(p2_rx_reset_reset_n) = p2_rx_reset_reset_n;
        input_clock p2_tx_clk_clk(p2_tx_clk_clk) = p2_tx_clk_clk;
        input_reset p2_tx_clk_clk_reset() = p2_tx_clk_clk_reset; /* from clock*/
        input_reset p2_tx_reset_reset_n(p2_tx_reset_reset_n) = p2_tx_reset_reset_n;
        input_clock p3_rx_clk_clk(p3_rx_clk_clk) = p3_rx_clk_clk;
        input_reset p3_rx_clk_clk_reset() = p3_rx_clk_clk_reset; /* from clock*/
        input_reset p3_rx_reset_reset_n(p3_rx_reset_reset_n) = p3_rx_reset_reset_n;
        input_clock p3_tx_clk_clk(p3_tx_clk_clk) = p3_tx_clk_clk;
        input_reset p3_tx_clk_clk_reset() = p3_tx_clk_clk_reset; /* from clock*/
        input_reset p3_tx_reset_reset_n(p3_tx_reset_reset_n) = p3_tx_reset_reset_n;
    interface MacwrapJtag     jtag;
        output_reset reset_reset(jtag_reset_reset);
    endinterface
    interface MacwrapP0_link_fault     p0_link_fault;
        method p0_link_fault_status_data status_data();
    endinterface
    interface MacwrapP0_rx     p0_rx;
        method p0_rx_fifo_out_data fifo_out_data() clocked_by (p0_rx_clk_clk) reset_by (p0_rx_clk_clk_reset);
        method p0_rx_fifo_out_empty fifo_out_empty() clocked_by (p0_rx_clk_clk) reset_by (p0_rx_clk_clk_reset);
        method p0_rx_fifo_out_endofpacket fifo_out_endofpacket() clocked_by (p0_rx_clk_clk) reset_by (p0_rx_clk_clk_reset);
        method p0_rx_fifo_out_error fifo_out_error() clocked_by (p0_rx_clk_clk) reset_by (p0_rx_clk_clk_reset);
        method fifo_out_ready(p0_rx_fifo_out_ready) clocked_by (p0_rx_clk_clk) reset_by (p0_rx_clk_clk_reset) enable((*inhigh*) EN_p0_rx_fifo_out_ready);
        method p0_rx_fifo_out_startofpacket fifo_out_startofpacket() clocked_by (p0_rx_clk_clk) reset_by (p0_rx_clk_clk_reset);
        method p0_rx_fifo_out_valid fifo_out_valid() clocked_by (p0_rx_clk_clk) reset_by (p0_rx_clk_clk_reset);
        method p0_rx_status_data status_data() clocked_by (p0_rx_clk_clk) reset_by (p0_rx_clk_clk_reset);
        method p0_rx_status_error status_error() clocked_by (p0_rx_clk_clk) reset_by (p0_rx_clk_clk_reset);
        method p0_rx_status_valid status_valid() clocked_by (p0_rx_clk_clk) reset_by (p0_rx_clk_clk_reset);
    endinterface
    interface MacwrapP0_tx     p0_tx;
        method fifo_in_data(p0_tx_fifo_in_data) clocked_by (p0_tx_clk_clk) reset_by (p0_tx_clk_clk_reset) enable((*inhigh*) EN_p0_tx_fifo_in_data);
        method fifo_in_empty(p0_tx_fifo_in_empty) clocked_by (p0_tx_clk_clk) reset_by (p0_tx_clk_clk_reset) enable((*inhigh*) EN_p0_tx_fifo_in_empty);
        method fifo_in_endofpacket(p0_tx_fifo_in_endofpacket) clocked_by (p0_tx_clk_clk) reset_by (p0_tx_clk_clk_reset) enable((*inhigh*) EN_p0_tx_fifo_in_endofpacket);
        method fifo_in_error(p0_tx_fifo_in_error) clocked_by (p0_tx_clk_clk) reset_by (p0_tx_clk_clk_reset) enable((*inhigh*) EN_p0_tx_fifo_in_error);
        method p0_tx_fifo_in_ready fifo_in_ready() clocked_by (p0_tx_clk_clk) reset_by (p0_tx_clk_clk_reset);
        method fifo_in_startofpacket(p0_tx_fifo_in_startofpacket) clocked_by (p0_tx_clk_clk) reset_by (p0_tx_clk_clk_reset) enable((*inhigh*) EN_p0_tx_fifo_in_startofpacket);
        method fifo_in_valid(p0_tx_fifo_in_valid) clocked_by (p0_tx_clk_clk) reset_by (p0_tx_clk_clk_reset) enable((*inhigh*) EN_p0_tx_fifo_in_valid);
        method p0_tx_status_data status_data() clocked_by (p0_tx_clk_clk) reset_by (p0_tx_clk_clk_reset);
        method p0_tx_status_error status_error() clocked_by (p0_tx_clk_clk) reset_by (p0_tx_clk_clk_reset);
        method p0_tx_status_valid status_valid() clocked_by (p0_tx_clk_clk) reset_by (p0_tx_clk_clk_reset);
    endinterface
    interface MacwrapP0_xgmii     p0_xgmii;
        method rx_data(p0_xgmii_rx_data) enable((*inhigh*) EN_p0_xgmii_rx_data);
        method p0_xgmii_tx_data tx_data();
    endinterface
    interface MacwrapP1_link_fault     p1_link_fault;
        method p1_link_fault_status_data status_data();
    endinterface
    interface MacwrapP1_rx     p1_rx;
        method p1_rx_fifo_out_data fifo_out_data() clocked_by (p1_rx_clk_clk) reset_by (p1_rx_clk_clk_reset);
        method p1_rx_fifo_out_empty fifo_out_empty() clocked_by (p1_rx_clk_clk) reset_by (p1_rx_clk_clk_reset);
        method p1_rx_fifo_out_endofpacket fifo_out_endofpacket() clocked_by (p1_rx_clk_clk) reset_by (p1_rx_clk_clk_reset);
        method p1_rx_fifo_out_error fifo_out_error() clocked_by (p1_rx_clk_clk) reset_by (p1_rx_clk_clk_reset);
        method fifo_out_ready(p1_rx_fifo_out_ready) clocked_by (p1_rx_clk_clk) reset_by (p1_rx_clk_clk_reset) enable((*inhigh*) EN_p1_rx_fifo_out_ready);
        method p1_rx_fifo_out_startofpacket fifo_out_startofpacket() clocked_by (p1_rx_clk_clk) reset_by (p1_rx_clk_clk_reset);
        method p1_rx_fifo_out_valid fifo_out_valid() clocked_by (p1_rx_clk_clk) reset_by (p1_rx_clk_clk_reset);
        method p1_rx_status_data status_data() clocked_by (p1_rx_clk_clk) reset_by (p1_rx_clk_clk_reset);
        method p1_rx_status_error status_error() clocked_by (p1_rx_clk_clk) reset_by (p1_rx_clk_clk_reset);
        method p1_rx_status_valid status_valid() clocked_by (p1_rx_clk_clk) reset_by (p1_rx_clk_clk_reset);
    endinterface
    interface MacwrapP1_tx     p1_tx;
        method fifo_in_data(p1_tx_fifo_in_data) clocked_by (p1_tx_clk_clk) reset_by (p1_tx_clk_clk_reset) enable((*inhigh*) EN_p1_tx_fifo_in_data);
        method fifo_in_empty(p1_tx_fifo_in_empty) clocked_by (p1_tx_clk_clk) reset_by (p1_tx_clk_clk_reset) enable((*inhigh*) EN_p1_tx_fifo_in_empty);
        method fifo_in_endofpacket(p1_tx_fifo_in_endofpacket) clocked_by (p1_tx_clk_clk) reset_by (p1_tx_clk_clk_reset) enable((*inhigh*) EN_p1_tx_fifo_in_endofpacket);
        method fifo_in_error(p1_tx_fifo_in_error) clocked_by (p1_tx_clk_clk) reset_by (p1_tx_clk_clk_reset) enable((*inhigh*) EN_p1_tx_fifo_in_error);
        method p1_tx_fifo_in_ready fifo_in_ready() clocked_by (p1_tx_clk_clk) reset_by (p1_tx_clk_clk_reset);
        method fifo_in_startofpacket(p1_tx_fifo_in_startofpacket) clocked_by (p1_tx_clk_clk) reset_by (p1_tx_clk_clk_reset) enable((*inhigh*) EN_p1_tx_fifo_in_startofpacket);
        method fifo_in_valid(p1_tx_fifo_in_valid) clocked_by (p1_tx_clk_clk) reset_by (p1_tx_clk_clk_reset) enable((*inhigh*) EN_p1_tx_fifo_in_valid);
        method p1_tx_status_data status_data() clocked_by (p1_tx_clk_clk) reset_by (p1_tx_clk_clk_reset);
        method p1_tx_status_error status_error() clocked_by (p1_tx_clk_clk) reset_by (p1_tx_clk_clk_reset);
        method p1_tx_status_valid status_valid() clocked_by (p1_tx_clk_clk) reset_by (p1_tx_clk_clk_reset);
    endinterface
    interface MacwrapP1_xgmii     p1_xgmii;
        method rx_data(p1_xgmii_rx_data) enable((*inhigh*) EN_p1_xgmii_rx_data);
        method p1_xgmii_tx_data tx_data();
    endinterface
    interface MacwrapP2_link_fault     p2_link_fault;
        method p2_link_fault_status_data status_data();
    endinterface
    interface MacwrapP2_rx     p2_rx;
        method p2_rx_fifo_out_data fifo_out_data() clocked_by (p2_rx_clk_clk) reset_by (p2_rx_clk_clk_reset);
        method p2_rx_fifo_out_empty fifo_out_empty() clocked_by (p2_rx_clk_clk) reset_by (p2_rx_clk_clk_reset);
        method p2_rx_fifo_out_endofpacket fifo_out_endofpacket() clocked_by (p2_rx_clk_clk) reset_by (p2_rx_clk_clk_reset);
        method p2_rx_fifo_out_error fifo_out_error() clocked_by (p2_rx_clk_clk) reset_by (p2_rx_clk_clk_reset);
        method fifo_out_ready(p2_rx_fifo_out_ready) clocked_by (p2_rx_clk_clk) reset_by (p2_rx_clk_clk_reset) enable((*inhigh*) EN_p2_rx_fifo_out_ready);
        method p2_rx_fifo_out_startofpacket fifo_out_startofpacket() clocked_by (p2_rx_clk_clk) reset_by (p2_rx_clk_clk_reset);
        method p2_rx_fifo_out_valid fifo_out_valid() clocked_by (p2_rx_clk_clk) reset_by (p2_rx_clk_clk_reset);
        method p2_rx_status_data status_data() clocked_by (p2_rx_clk_clk) reset_by (p2_rx_clk_clk_reset);
        method p2_rx_status_error status_error() clocked_by (p2_rx_clk_clk) reset_by (p2_rx_clk_clk_reset);
        method p2_rx_status_valid status_valid() clocked_by (p2_rx_clk_clk) reset_by (p2_rx_clk_clk_reset);
    endinterface
    interface MacwrapP2_tx     p2_tx;
        method fifo_in_data(p2_tx_fifo_in_data) clocked_by (p2_tx_clk_clk) reset_by (p2_tx_clk_clk_reset) enable((*inhigh*) EN_p2_tx_fifo_in_data);
        method fifo_in_empty(p2_tx_fifo_in_empty) clocked_by (p2_tx_clk_clk) reset_by (p2_tx_clk_clk_reset) enable((*inhigh*) EN_p2_tx_fifo_in_empty);
        method fifo_in_endofpacket(p2_tx_fifo_in_endofpacket) clocked_by (p2_tx_clk_clk) reset_by (p2_tx_clk_clk_reset) enable((*inhigh*) EN_p2_tx_fifo_in_endofpacket);
        method fifo_in_error(p2_tx_fifo_in_error) clocked_by (p2_tx_clk_clk) reset_by (p2_tx_clk_clk_reset) enable((*inhigh*) EN_p2_tx_fifo_in_error);
        method p2_tx_fifo_in_ready fifo_in_ready() clocked_by (p2_tx_clk_clk) reset_by (p2_tx_clk_clk_reset);
        method fifo_in_startofpacket(p2_tx_fifo_in_startofpacket) clocked_by (p2_tx_clk_clk) reset_by (p2_tx_clk_clk_reset) enable((*inhigh*) EN_p2_tx_fifo_in_startofpacket);
        method fifo_in_valid(p2_tx_fifo_in_valid) clocked_by (p2_tx_clk_clk) reset_by (p2_tx_clk_clk_reset) enable((*inhigh*) EN_p2_tx_fifo_in_valid);
        method p2_tx_status_data status_data() clocked_by (p2_tx_clk_clk) reset_by (p2_tx_clk_clk_reset);
        method p2_tx_status_error status_error() clocked_by (p2_tx_clk_clk) reset_by (p2_tx_clk_clk_reset);
        method p2_tx_status_valid status_valid() clocked_by (p2_tx_clk_clk) reset_by (p2_tx_clk_clk_reset);
    endinterface
    interface MacwrapP2_xgmii     p2_xgmii;
        method rx_data(p2_xgmii_rx_data) enable((*inhigh*) EN_p2_xgmii_rx_data);
        method p2_xgmii_tx_data tx_data();
    endinterface
    interface MacwrapP3_link_fault     p3_link_fault;
        method p3_link_fault_status_data status_data();
    endinterface
    interface MacwrapP3_rx     p3_rx;
        method p3_rx_fifo_out_data fifo_out_data() clocked_by (p3_rx_clk_clk) reset_by (p3_rx_clk_clk_reset);
        method p3_rx_fifo_out_empty fifo_out_empty() clocked_by (p3_rx_clk_clk) reset_by (p3_rx_clk_clk_reset);
        method p3_rx_fifo_out_endofpacket fifo_out_endofpacket() clocked_by (p3_rx_clk_clk) reset_by (p3_rx_clk_clk_reset);
        method p3_rx_fifo_out_error fifo_out_error() clocked_by (p3_rx_clk_clk) reset_by (p3_rx_clk_clk_reset);
        method fifo_out_ready(p3_rx_fifo_out_ready) clocked_by (p3_rx_clk_clk) reset_by (p3_rx_clk_clk_reset) enable((*inhigh*) EN_p3_rx_fifo_out_ready);
        method p3_rx_fifo_out_startofpacket fifo_out_startofpacket() clocked_by (p3_rx_clk_clk) reset_by (p3_rx_clk_clk_reset);
        method p3_rx_fifo_out_valid fifo_out_valid() clocked_by (p3_rx_clk_clk) reset_by (p3_rx_clk_clk_reset);
        method p3_rx_status_data status_data() clocked_by (p3_rx_clk_clk) reset_by (p3_rx_clk_clk_reset);
        method p3_rx_status_error status_error() clocked_by (p3_rx_clk_clk) reset_by (p3_rx_clk_clk_reset);
        method p3_rx_status_valid status_valid() clocked_by (p3_rx_clk_clk) reset_by (p3_rx_clk_clk_reset);
    endinterface
    interface MacwrapP3_tx     p3_tx;
        method fifo_in_data(p3_tx_fifo_in_data) clocked_by (p3_tx_clk_clk) reset_by (p3_tx_clk_clk_reset) enable((*inhigh*) EN_p3_tx_fifo_in_data);
        method fifo_in_empty(p3_tx_fifo_in_empty) clocked_by (p3_tx_clk_clk) reset_by (p3_tx_clk_clk_reset) enable((*inhigh*) EN_p3_tx_fifo_in_empty);
        method fifo_in_endofpacket(p3_tx_fifo_in_endofpacket) clocked_by (p3_tx_clk_clk) reset_by (p3_tx_clk_clk_reset) enable((*inhigh*) EN_p3_tx_fifo_in_endofpacket);
        method fifo_in_error(p3_tx_fifo_in_error) clocked_by (p3_tx_clk_clk) reset_by (p3_tx_clk_clk_reset) enable((*inhigh*) EN_p3_tx_fifo_in_error);
        method p3_tx_fifo_in_ready fifo_in_ready() clocked_by (p3_tx_clk_clk) reset_by (p3_tx_clk_clk_reset);
        method fifo_in_startofpacket(p3_tx_fifo_in_startofpacket) clocked_by (p3_tx_clk_clk) reset_by (p3_tx_clk_clk_reset) enable((*inhigh*) EN_p3_tx_fifo_in_startofpacket);
        method fifo_in_valid(p3_tx_fifo_in_valid) clocked_by (p3_tx_clk_clk) reset_by (p3_tx_clk_clk_reset) enable((*inhigh*) EN_p3_tx_fifo_in_valid);
        method p3_tx_status_data status_data() clocked_by (p3_tx_clk_clk) reset_by (p3_tx_clk_clk_reset);
        method p3_tx_status_error status_error() clocked_by (p3_tx_clk_clk) reset_by (p3_tx_clk_clk_reset);
        method p3_tx_status_valid status_valid() clocked_by (p3_tx_clk_clk) reset_by (p3_tx_clk_clk_reset);
    endinterface
    interface MacwrapP3_xgmii     p3_xgmii;
        method rx_data(p3_xgmii_rx_data) enable((*inhigh*) EN_p3_xgmii_rx_data);
        method p3_xgmii_tx_data tx_data();
    endinterface
    schedule (p0_link_fault.status_data, p0_rx.fifo_out_data, p0_rx.fifo_out_empty, p0_rx.fifo_out_endofpacket, p0_rx.fifo_out_error, p0_rx.fifo_out_ready, p0_rx.fifo_out_startofpacket, p0_rx.fifo_out_valid, p0_rx.status_data, p0_rx.status_error, p0_rx.status_valid, p0_tx.fifo_in_data, p0_tx.fifo_in_empty, p0_tx.fifo_in_endofpacket, p0_tx.fifo_in_error, p0_tx.fifo_in_ready, p0_tx.fifo_in_startofpacket, p0_tx.fifo_in_valid, p0_tx.status_data, p0_tx.status_error, p0_tx.status_valid, p0_xgmii.rx_data, p0_xgmii.tx_data, p1_link_fault.status_data, p1_rx.fifo_out_data, p1_rx.fifo_out_empty, p1_rx.fifo_out_endofpacket, p1_rx.fifo_out_error, p1_rx.fifo_out_ready, p1_rx.fifo_out_startofpacket, p1_rx.fifo_out_valid, p1_rx.status_data, p1_rx.status_error, p1_rx.status_valid, p1_tx.fifo_in_data, p1_tx.fifo_in_empty, p1_tx.fifo_in_endofpacket, p1_tx.fifo_in_error, p1_tx.fifo_in_ready, p1_tx.fifo_in_startofpacket, p1_tx.fifo_in_valid, p1_tx.status_data, p1_tx.status_error, p1_tx.status_valid, p1_xgmii.rx_data, p1_xgmii.tx_data, p2_link_fault.status_data, p2_rx.fifo_out_data, p2_rx.fifo_out_empty, p2_rx.fifo_out_endofpacket, p2_rx.fifo_out_error, p2_rx.fifo_out_ready, p2_rx.fifo_out_startofpacket, p2_rx.fifo_out_valid, p2_rx.status_data, p2_rx.status_error, p2_rx.status_valid, p2_tx.fifo_in_data, p2_tx.fifo_in_empty, p2_tx.fifo_in_endofpacket, p2_tx.fifo_in_error, p2_tx.fifo_in_ready, p2_tx.fifo_in_startofpacket, p2_tx.fifo_in_valid, p2_tx.status_data, p2_tx.status_error, p2_tx.status_valid, p2_xgmii.rx_data, p2_xgmii.tx_data, p3_link_fault.status_data, p3_rx.fifo_out_data, p3_rx.fifo_out_empty, p3_rx.fifo_out_endofpacket, p3_rx.fifo_out_error, p3_rx.fifo_out_ready, p3_rx.fifo_out_startofpacket, p3_rx.fifo_out_valid, p3_rx.status_data, p3_rx.status_error, p3_rx.status_valid, p3_tx.fifo_in_data, p3_tx.fifo_in_empty, p3_tx.fifo_in_endofpacket, p3_tx.fifo_in_error, p3_tx.fifo_in_ready, p3_tx.fifo_in_startofpacket, p3_tx.fifo_in_valid, p3_tx.status_data, p3_tx.status_error, p3_tx.status_valid, p3_xgmii.rx_data, p3_xgmii.tx_data) CF (p0_link_fault.status_data, p0_rx.fifo_out_data, p0_rx.fifo_out_empty, p0_rx.fifo_out_endofpacket, p0_rx.fifo_out_error, p0_rx.fifo_out_ready, p0_rx.fifo_out_startofpacket, p0_rx.fifo_out_valid, p0_rx.status_data, p0_rx.status_error, p0_rx.status_valid, p0_tx.fifo_in_data, p0_tx.fifo_in_empty, p0_tx.fifo_in_endofpacket, p0_tx.fifo_in_error, p0_tx.fifo_in_ready, p0_tx.fifo_in_startofpacket, p0_tx.fifo_in_valid, p0_tx.status_data, p0_tx.status_error, p0_tx.status_valid, p0_xgmii.rx_data, p0_xgmii.tx_data, p1_link_fault.status_data, p1_rx.fifo_out_data, p1_rx.fifo_out_empty, p1_rx.fifo_out_endofpacket, p1_rx.fifo_out_error, p1_rx.fifo_out_ready, p1_rx.fifo_out_startofpacket, p1_rx.fifo_out_valid, p1_rx.status_data, p1_rx.status_error, p1_rx.status_valid, p1_tx.fifo_in_data, p1_tx.fifo_in_empty, p1_tx.fifo_in_endofpacket, p1_tx.fifo_in_error, p1_tx.fifo_in_ready, p1_tx.fifo_in_startofpacket, p1_tx.fifo_in_valid, p1_tx.status_data, p1_tx.status_error, p1_tx.status_valid, p1_xgmii.rx_data, p1_xgmii.tx_data, p2_link_fault.status_data, p2_rx.fifo_out_data, p2_rx.fifo_out_empty, p2_rx.fifo_out_endofpacket, p2_rx.fifo_out_error, p2_rx.fifo_out_ready, p2_rx.fifo_out_startofpacket, p2_rx.fifo_out_valid, p2_rx.status_data, p2_rx.status_error, p2_rx.status_valid, p2_tx.fifo_in_data, p2_tx.fifo_in_empty, p2_tx.fifo_in_endofpacket, p2_tx.fifo_in_error, p2_tx.fifo_in_ready, p2_tx.fifo_in_startofpacket, p2_tx.fifo_in_valid, p2_tx.status_data, p2_tx.status_error, p2_tx.status_valid, p2_xgmii.rx_data, p2_xgmii.tx_data, p3_link_fault.status_data, p3_rx.fifo_out_data, p3_rx.fifo_out_empty, p3_rx.fifo_out_endofpacket, p3_rx.fifo_out_error, p3_rx.fifo_out_ready, p3_rx.fifo_out_startofpacket, p3_rx.fifo_out_valid, p3_rx.status_data, p3_rx.status_error, p3_rx.status_valid, p3_tx.fifo_in_data, p3_tx.fifo_in_empty, p3_tx.fifo_in_endofpacket, p3_tx.fifo_in_error, p3_tx.fifo_in_ready, p3_tx.fifo_in_startofpacket, p3_tx.fifo_in_valid, p3_tx.status_data, p3_tx.status_error, p3_tx.status_valid, p3_xgmii.rx_data, p3_xgmii.tx_data);
endmodule