added mkReducePipes

added mkReducePipes

Change-Id: I05f36ddbea864d2c5d782d81cfe2b0d52326eac7

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

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

module mkMap#(function b f(a av), PipeOut#(a) apipe)(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
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 <- mkMap(head, inpipe);
      return pipe;
   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 <- mkMap(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);
      PipeOut#(Tuple2#(a,a)) zippipe = (interface PipeOut#(Tuple2#(a,a));
				       method Tuple2#(a,a) first(); return tuple2(inpipes[0].first(), inpipes[1].first()); endmethod
				       method Action deq(); inpipes[0].deq(); inpipes[1].deq(); endmethod
				       method Bool notEmpty(); return inpipes[0].notEmpty && inpipes[1].notEmpty(); endmethod
				       endinterface);
      let pipe <- combinepipe(zippipe);
      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#(Tuple2#(a,a)) tplpipe = (interface PipeOut;
					method Tuple2#(a,a) first(); return tuple2(p0.first, p1.first); endmethod
					method Action deq();
					   p0.deq();
					   p1.deq();
					endmethod
					method notEmpty(); return p0.notEmpty() && p1.notEmpty(); endmethod
					endinterface);
      PipeOut#(a) outpipe <- combinepipe(tplpipe);
      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

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

module mkMap#(function b f(a av), PipeOut#(a) apipe)(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
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);
endtypeclass
instance ReducePipe#(1, a);
   module [Module] mkReducePipe (PipeOutConstructor#(Tuple2#(a,a), a) combinepipe,
				 PipeOut#(Vector#(1,a)) inpipe,
				 PipeOut#(a) ifc);
      let pipe <- mkMap(head, inpipe);
      return pipe;
   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 <- mkMap(foo, inpipe);
      let pipe <- combinepipe(zippipe);
      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#(Tuple2#(a,a)) tplpipe = (interface PipeOut;
					method Tuple2#(a,a) first(); return tuple2(p0.first, p1.first); endmethod
					method Action deq();
					   p0.deq();
					   p1.deq();
					endmethod
					method notEmpty(); return p0.notEmpty() && p1.notEmpty(); endmethod
					endinterface);
      PipeOut#(a) outpipe <- combinepipe(tplpipe);
      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


add BRAM

add BRAM

// 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 Complex::*;
import FixedPoint::*;
import FPCMult::*;
import Gearbox::*;
import Pipe::*;
import FIFO::*;
import BRAM::*;
import BRAMFIFO::*;
import Vector::*;
import Clocks::*;
import DefaultValue::*;
import DDS::*;

/* note rf signal is 64 bits wide, 2 sample of complex fixed point(0,16)
 */
(* always_enabled *)
interface ChannelSelect;
   interface PipeIn#(Vector#(2, Complex#(Signal))) rfreq;
   interface PipeOut#(Complex#(Signal)) ifreq;
   method Action setCoeff(Bit#(10) addr, Complex#(FixedPoint#(2, 23)) value);
endinterface

module mkChannelSelect#(UInt#(10) decimation)(ChannelSelect);
   BRAM_Configure cfg = defaultValue;
   cfg.memorySize = 1024;
   Vector#(2, BRAM2Port#(UInt#(8), Complex#(FixedPoint#(2,23)))) coeffRam <-
        replicate(mkBRAM2Server(cfg));
   Reg#(UInt#(10)) filterPhase <- mkReg(?);
   FIFO#(Bits#(1)) delayFilterPhase <- mkSizedFIFO(3);  // length > bram read latency

   Reg#(Vector#(2, Signal)) out <- mkReg(?);
   Vector#(2, FPCMult) mul <- replicate(mkFPCMult());

   Vector#(2, FIFO#(Complex#(Product))) accum <- replicate(mkFIFO());
   FIFO#(Complex#(Product)) ycombined <- mkFIFO();
   FPCMult lo <- mkFPCMult();

   mkConnection(rfreq, mul.x);

   /* could do this with mkForkVector() but we don't need the extra FIFOs
      since everything is ready every cycle
    */
   rule duplicateSignal;
      let v = rfreq.first;
      rfreq.deq();
      mul[0].x.enq(v);
      mul[1].x.enq(v);
   endrule

   rule filter_phase;
      if (filterPhase == (decimation - 1))
	 begin
	    filterPhase <= 0;
	    delayFilterPhase.enq(1);
	 end
      else
	 begin
	    filterPhase <= phase + 1;
	    delayFilterPhase.enq(0);
	 end
      coeffRam[0].portB.request.put(BRamRequest{write: False, responseOnWrite: False, address: filterPhase, datain: ?});
      coeffRam[1].portB.request.put(BRamRequest{write: False, responseOnWrite: False, address: filterPhase, datain: ?});
   endrule

   rule mulin;
      let c0 <- coeffRam[0].portB.response.get();
      let c1 <- coeffRam[1].portB.response.get();
      let phase <- delayFilterPhase.get();

      mul[0].coeffData.enq(CoeffData{a: c0, filterPhase: phase});
      mul[1].coeffData.enq(CoeffData{a: c1, filterPhase: phase});
   endrule

   rule muloutaccumin0;
      let m <- mul0.y.get();
      if (m.filterPhase)
	 begin
	    accum[0] <= m.y;
	    accumout[0].enq(accum[0]);
	 end
      else
	 begin
	    accum[0] <= accum[0] + m.y;
	 end
   endrule

   rule muloutaccumin1;
      let m <- mul1.y.get();
      if (m.filterPhase)
	 begin
	    accum[1] <= m.y;
	    accumout[1].enq(accum[1]);
	 end
      else
	 begin
	    accum[1] <= accum[1] + m.y;
	 end
   endrule

   rule accumoutcombinein;
      let a0 <- accumout[0].get();
      let a1 <- accumout[1].get();
      ycombined.enq(a0 + a1);
   endrule

   rule combineoutloin;
      let yin <- ycombined.get();
      let loin <- dds.osc.get();
      ifreq.x.enq(yin);
      ifreq.coeffData.enq(loin);
   endrule

   method Action setCoeff(Bit#(10) addr, Bit#(32) value);
      int idx = addr[0];
      coeffRam[idx].portA.request.put(BRamRequest{write: True, responseOnWrite: False, address: addr[8:1], datain: unpack(pack(value))});
   endmethod

   interface PipeOut ifreq = toPipeOut(out);

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 Complex::*;
import FixedPoint::*;
import FPCMult::*;
import Gearbox::*;
import Pipe::*;
import FIFO::*;
import BRAMFIFO::*;
import Vector::*;
import Clocks::*;
import DefaultValue::*;
import DDS::*;

/* note rf signal is 64 bits wide, 2 sample of complex fixed point(0,16)
 */
(* always_enabled *)
interface ChannelSelect;
   interface PipeIn#(Vector#(2, Complex#(Signal))) rfreq;
   interface PipeOut#(Complex#(Signal)) ifreq;
   method Action setCoeff(Bit#(10) addr, Complex#(FixedPoint#(2, 23)) value);
endinterface

module mkChannelSelect#(UInt#(10) decimation)(ChannelSelect);
   BRAM_Configure cfg = defaultValue;
   cfg.memorySize = 1024;
   Vector#(2, BRAM2Port#(UInt#(8), Complex#(FixedPoint#(2,23)))) coeffRam <-
        replicate(mkBRAM2Server(cfg));
   Reg#(UInt#(10)) filterPhase <- mkReg(?);
   FIFO#(Bits#(1)) delayFilterPhase <- mkSizedFIFO(3);  // length > bram read latency

   Reg#(Vector#(2, Signal)) out <- mkReg(?);
   Vector#(2, FPCMult) mul <- replicate(mkFPCMult());

   Vector#(2, FIFO#(Complex#(Product))) accum <- replicate(mkFIFO());
   FIFO#(Complex#(Product)) ycombined <- mkFIFO();
   FPCMult lo <- mkFPCMult();

   mkConnection(rfreq, mul.x);

   /* could do this with mkForkVector() but we don't need the extra FIFOs
      since everything is ready every cycle
    */
   rule duplicateSignal;
      let v = rfreq.first;
      rfreq.deq();
      mul[0].x.enq(v);
      mul[1].x.enq(v);
   endrule

   rule filter_phase;
      if (filterPhase == (decimation - 1))
	 begin
	    filterPhase <= 0;
	    delayFilterPhase.enq(1);
	 end
      else
	 begin
	    filterPhase <= phase + 1;
	    delayFilterPhase.enq(0);
	 end
      coeffRam[0].portB.request.put(BRamRequest{write: False, responseOnWrite: False, address: filterPhase, datain: ?});
      coeffRam[1].portB.request.put(BRamRequest{write: False, responseOnWrite: False, address: filterPhase, datain: ?});
   endrule

   rule mulin;
      let c0 <- coeffRam[0].portB.response.get();
      let c1 <- coeffRam[1].portB.response.get();
      let phase <- delayFilterPhase.get();

      mul[0].coeffData.enq(CoeffData{a: c0, filterPhase: phase});
      mul[1].coeffData.enq(CoeffData{a: c1, filterPhase: phase});
   endrule

   rule muloutaccumin0;
      let m <- mul0.y.get();
      if (m.filterPhase)
	 begin
	    accum[0] <= m.y;
	    accumout[0].enq(accum[0]);
	 end
      else
	 begin
	    accum[0] <= accum[0] + m.y;
	 end
   endrule

   rule muloutaccumin1;
      let m <- mul1.y.get();
      if (m.filterPhase)
	 begin
	    accum[1] <= m.y;
	    accumout[1].enq(accum[1]);
	 end
      else
	 begin
	    accum[1] <= accum[1] + m.y;
	 end
   endrule

   rule accumoutcombinein;
      let a0 <- accumout[0].get();
      let a1 <- accumout[1].get();
      ycombined.enq(a0 + a1);
   endrule

   rule combineoutloin;
      let yin <- ycombined.get();
      let loin <- dds.osc.get();
      ifreq.x.enq(yin);
      ifreq.coeffData.enq(loin);
   endrule

   method Action setCoeff(Bit#(10) addr, Bit#(32) value);
      int idx = addr[0];
      coeffRam[idx].portA.request.put(BRamRequest{write: True, responseOnWrite: False, address: addr[8:1], datain: unpack(pack(value))});
   endmethod

   interface PipeOut ifreq = toPipeOut(out);

endmodule


Simple logic on direction flag

Simple logic on direction flag

import Vector::*;
import GetPut::*;
import ConfigReg::*;

interface ITranspose#(numeric type n, type a);
   interface Put#(Vector#(n, a)) inp;
   interface Get#(Vector#(n, a)) oup;
endinterface

module mkTranspose(ITranspose#(n,a))
   provisos(
      Bits#(Vector#(n,a), __a),
      Add#(1, TLog#(n), cntBits)
   );

   RWire#(Vector#(n, a)) rw_inp           <- mkRWire;
   Reg#(Vector#(n, a)) obuf               <- mkRegU;

   Vector#(n, Reg#(Vector#(n, a))) matrix <- replicateM(mkRegU);
   Reg#(Bit#(cntBits)) count              <- mkReg(0);
   Reg#(Bool) startOutput                 <- mkConfigReg(False);

   rule shift_input(isValid(rw_inp.wget));
      let x = fromMaybe(?, rw_inp.wget);
      let dir = msb(count);

      if (dir == 0) begin
         // Row shift
         for(Integer i = 0; i < valueOf(n) - 1; i = i + 1) begin
            matrix[i] <= matrix[i + 1];
         end
         matrix[valueOf(n) - 1] <= x;

         if (startOutput) begin
            obuf <= matrix[0];
         end
      end
      else begin
         // Column shift
         for(Integer i = 0; i < valueOf(n); i = i + 1) begin
            matrix[i] <= shiftInAtN(matrix[i], x[i]);
         end

         if (startOutput) begin
            Vector#(n,a) tmp;
            for(Integer i = 0; i < valueOf(n); i = i + 1) begin
               tmp[i] = matrix[i][0];
            end
            obuf <= tmp;
         end
      end
      count <= count + 1;
   endrule

   rule do_start;
      if (count == '1) begin
         startOutput <= True;
      end
   endrule

   interface Put inp = toPut(rw_inp);
   interface Get oup = interface Get;
                          method ActionValue#(Vector#(n, a)) get() if (startOutput && isValid(rw_inp.wget));
                             return obuf;
                          endmethod
                       endinterface;
endmodule

(* synthesize *)
module mkTranspose32x32(ITranspose#(32, Bit#(8)));
   (* hide *) let _x <- mkTranspose;
   return _x;
endmodule

import Vector::*;
import GetPut::*;
import ConfigReg::*;

interface ITranspose#(numeric type n, type a);
   interface Put#(Vector#(n, a)) inp;
   interface Get#(Vector#(n, a)) oup;
endinterface

module mkTranspose(ITranspose#(n,a))
   provisos(
      Bits#(Vector#(n,a), __a),
      Log#(n, cntBits)
   );

   RWire#(Vector#(n, a)) rw_inp           <- mkRWire;
   Reg#(Vector#(n, a)) obuf               <- mkRegU;

   Vector#(n, Reg#(Vector#(n, a))) matrix <- replicateM(mkRegU);
   Reg#(Bit#(cntBits)) count              <- mkReg(0);
   Reg#(Bool) dir                         <- mkConfigReg(False);
   Reg#(Bool) startOutput                 <- mkConfigReg(False);

   rule shift_input(isValid(rw_inp.wget));
      let x = fromMaybe(?, rw_inp.wget);

      if (!dir) begin
         // Row shift
         for(Integer i = 0; i < valueOf(n) - 1; i = i + 1) begin
            matrix[i] <= matrix[i + 1];
         end
         matrix[valueOf(n) - 1] <= x;

         if (startOutput) begin
            obuf <= matrix[0];
         end
      end
      else begin
         // Column shift
         for(Integer i = 0; i < valueOf(n); i = i + 1) begin
            matrix[i] <= shiftInAtN(matrix[i], x[i]);
         end

         if (startOutput) begin
            Vector#(n,a) tmp;
            for(Integer i = 0; i < valueOf(n); i = i + 1) begin
               tmp[i] = matrix[i][0];
            end
            obuf <= tmp;
         end
      end
      count <= count + 1;
   endrule

   rule do_start;
      if (count == '1) begin
         startOutput <= True;
         dir <= !dir;
      end
   endrule

   interface Put inp = toPut(rw_inp);
   interface Get oup = interface Get;
                          method ActionValue#(Vector#(n, a)) get() if (startOutput && isValid(rw_inp.wget));
                             return obuf;
                          endmethod
                       endinterface;
endmodule

(* synthesize *)
module mkTranspose32x32(ITranspose#(32, Bit#(8)));
   (* hide *) let _x <- mkTranspose;
   return _x;
endmodule


added mkBramReaderPipeV to read from a vector of BRAMs

// Copyright (c) 2015 Connectal Project.

// 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 FIFO::*;
import FIFOF::*;
import GetPut::*;
import ClientServer::*;
import BRAM::*;
import Vector::*;
import Probe::*;

import MemTypes::*;
import Pipe::*;
import ConfigCounter::*;

interface MemReaderPipe#(numeric type dsz);
   interface PipeOut#(MemData#(dsz)) dataPipe;
   interface MemReadClient#(dsz) readClient;
endinterface

module mkMemReaderPipe#(Reg#(SGLId) ptrReg,
			IteratorIfc#(Bit#(addrsz)) addrIterator,
			Bit#(BurstLenSize) burstLen)(MemReaderPipe#(dsz))
   provisos (Add#(a__, addrsz, MemOffsetSize),
	     Add#(b__, BurstLenSize, addrsz));

   let verbose = False;

   ConfigCounter#(addrsz)              counter <- mkConfigCounter(0);
   FIFO#(MemRequest) readReqFifo <- mkFIFO();
   FIFOF#(MemData#(dsz)) readDataFifo <- mkSizedFIFOF(8);
   Reg#(Bit#(MemTagSize)) tagReg <- mkReg(0);

   // 8+1 outstanding reads
   rule startReadReqRule if (counter.read() <= (extend(unpack(burstLen)) << 3));
      counter.increment(extend(unpack(burstLen)));
      let offset <- toGet(addrIterator.pipe).get();
      let tag = tagReg;
      if (addrIterator.isFirst())
	 tag = 0;
      if (verbose) $display("startReadReqRule: offset=%d counter=%d", offset, counter.read() + (extend(unpack(burstLen)) << 3));
      readReqFifo.enq(MemRequest { sglId: ptrReg, offset: extend(offset), burstLen: burstLen, tag: extend(tag) });
      tagReg <= tag + 1;
   endrule

   interface dataPipe = toPipeOut(readDataFifo);
   interface MemReadClient readClient;
      interface Get readReq = toGet(readReqFifo);
      interface Put readData;
	 method Action put(MemData#(dsz) md);
	    readDataFifo.enq(md);
	    counter.decrement(fromInteger(valueOf(TDiv#(dsz,8))));
	    if (verbose) $display("memreader.readData counter.read() %d", counter.read());
	 endmethod
      endinterface
   endinterface
endmodule

interface MemWriterPipe#(numeric type dsz);
   interface PipeOut#(Bool) lastPipe;
   interface MemWriteClient#(dsz) writeClient;
endinterface

module mkMemWriterPipe#(Reg#(SGLId) ptrReg,
			IteratorIfc#(Bit#(addrsz)) addrIterator,
			PipeOut#(dtype) dataPipe,
			Bit#(BurstLenSize) burstLen)(MemWriterPipe#(dsz))
   provisos (Bits#(dtype, dsz),
	     Add#(a__, addrsz, MemOffsetSize),
	     Add#(b__, BurstLenSize, addrsz));

   ConfigCounter#(addrsz)              counter <- mkConfigCounter(0);
   FIFO#(MemRequest)                   reqFifo <- mkSizedFIFO(4);
   FIFO#(MemRequest)              writeReqFifo <- mkFIFO();
   FIFOF#(MemData#(dsz))         writeDataFifo <- mkSizedFIFOF(4);
   FIFO#(Bit#(MemTagSize))       writeDoneFifo <- mkSizedFIFO(4);
   FIFOF#(Bool)                       lastFifo <- mkSizedFIFOF(4);
   FIFOF#(Bool)                       doneFifo <- mkSizedFIFOF(4);

   rule writeReqRule;
      let offset <- toGet(addrIterator.pipe).get();
      let tag = 22;
      $display("writeReqRule: offset=%h burstLen=%d addrIterator.isLast %d", offset, burstLen, addrIterator.isLast());
      reqFifo.enq(MemRequest { sglId: ptrReg, offset: extend(offset), burstLen: burstLen, tag: tag });
      lastFifo.enq(addrIterator.isLast());
   endrule
   rule writeReqReadyRule if (counter.read() >= extend(unpack(burstLen)));
      let req <- toGet(reqFifo).get();
      writeReqFifo.enq(req);
      counter.decrement(extend(unpack(burstLen)));
   endrule
   rule writeDataRule;
      let tag = 22;
      let v <- toGet(dataPipe).get();
      //$display("MemWriterPipe.writeDataRule: data=%h", v);
      writeDataFifo.enq(MemData { data: pack(v), tag: tag, last: False });
      counter.increment(fromInteger(valueOf(TDiv#(dsz,8))));
   endrule
   rule writeDone;
      let last <- toGet(lastFifo).get();
      let tag <- toGet(writeDoneFifo).get();
      doneFifo.enq(last);
   endrule
   interface PipeOut lastPipe = toPipeOut(doneFifo);
   interface MemWriteClient writeClient;
      interface Get writeReq = toGet(writeReqFifo);
      interface Get writeData = toGet(writeDataFifo);
      interface Put writeDone = toPut(writeDoneFifo);
   endinterface
endmodule

module mkMemWriterPipe2#(Bool lastOnly,
			 Reg#(SGLId) ptrReg,
			 IteratorIfc#(Bit#(addrsz)) addrIterator,
			 PipeOut#(dtype) dataPipe,
			 Bit#(BurstLenSize) burstLen)(MemWriterPipe#(dsz))
   provisos (Bits#(dtype, dsz),
	     Add#(a__, addrsz, MemOffsetSize),
	     Add#(b__, BurstLenSize, addrsz));

   ConfigCounter#(addrsz)              counter <- mkConfigCounter(0);
   FIFO#(MemRequest)                   reqFifo <- mkSizedFIFO(4);
   FIFO#(MemRequest)              writeReqFifo <- mkFIFO();
   FIFOF#(MemData#(dsz))         writeDataFifo <- mkSizedFIFOF(4);
   FIFO#(Bit#(MemTagSize))       writeDoneFifo <- mkSizedFIFO(4);
   FIFOF#(Bool)                       lastFifo <- mkSizedFIFOF(4);
   FIFOF#(Bool)                       doneFifo <- mkFIFOF();

   rule writeReqRule;
      let offset <- toGet(addrIterator.pipe).get();
      let tag = 22;
      $display("writeReqRule: offset=%h burstLen=%d addrIterator.isLast %d", offset, burstLen, addrIterator.isLast());
      reqFifo.enq(MemRequest { sglId: ptrReg, offset: extend(offset), burstLen: burstLen, tag: tag });
      lastFifo.enq(addrIterator.isLast());
   endrule
   rule writeReqReadyRule if (counter.read() >= extend(unpack(burstLen)));
      let req <- toGet(reqFifo).get();
      writeReqFifo.enq(req);
      counter.decrement(extend(unpack(burstLen)));
   endrule
   rule writeDataRule;
      let tag = 22;
      let v <- toGet(dataPipe).get();
      //$display("MemWriterPipe.writeDataRule: data=%h", v);
      writeDataFifo.enq(MemData { data: pack(v), tag: tag, last: False });
      counter.increment(fromInteger(valueOf(TDiv#(dsz,8))));
   endrule
   rule writeDone;
      let last <- toGet(lastFifo).get();
      let tag <- toGet(writeDoneFifo).get();
      if (!lastOnly || last)
	 doneFifo.enq(last);
   endrule
   interface PipeOut lastPipe = toPipeOut(doneFifo);
   interface MemWriteClient writeClient;
      interface Get writeReq = toGet(writeReqFifo);
      interface Get writeData = toGet(writeDataFifo);
      interface Put writeDone = toPut(writeDoneFifo);
   endinterface
endmodule

module mkBramReaderPipe#(BRAMServer#(Bit#(addrsz), dataType) bramServer,
			 PipeOut#(IteratorValue#(Bit#(addrsz),void)) addrIterator)(PipeOut#(IteratorValue#(dataType,void)))
   provisos (Add#(a__, addrsz, MemOffsetSize),
	     Bits#(dataType,dsz));

   FIFOF#(Tuple2#(Bool,Bool)) firstlastFifo <- mkFIFOF();
   FIFOF#(IteratorValue#(dataType,void)) readDataFifo <- mkFIFOF();

   let verbose = False;

   rule issueBramReadRequest;
      let item <- toGet(addrIterator).get();
      bramServer.request.put(BRAMRequest{write: False, responseOnWrite: False, address: item.value, datain: unpack(0)});
      firstlastFifo.enq(tuple2(item.first, item.last));
      if (verbose) $display("issueBramReadRequest addr=%h first=%d last=%d", item.value, item.first, item.last);
   endrule

   rule readData;
      let v <- bramServer.response.get();
      match { .first, .last } <- toGet(firstlastFifo).get();
      readDataFifo.enq(IteratorValue { value: v, first: first, last: last });
   endrule
   return toPipeOut(readDataFifo);
endmodule

module mkBramReaderPipeV#(Vector#(n, BRAMServer#(Bit#(addrsz), dataType)) bramServer,
			  PipeOut#(IteratorValue#(Bit#(addrsz),void)) addrIterator)(PipeOut#(IteratorValue#(Vector#(n,dataType),void)))
   provisos (Add#(a__, addrsz, MemOffsetSize),
	     Bits#(dataType,dsz));

   FIFOF#(Tuple2#(Bool,Bool)) firstlastFifo <- mkFIFOF();
   FIFOF#(IteratorValue#(Vector#(n,dataType),void)) readDataFifo <- mkFIFOF();

   let verbose = False;

   rule issueBramReadRequest;
      let item <- toGet(addrIterator).get();
      for (Integer i = 0; i < valueOf(n); i = i + 1)
	 bramServer[i].request.put(BRAMRequest{write: False, responseOnWrite: False, address: item.value, datain: unpack(0)});
      firstlastFifo.enq(tuple2(item.first, item.last));
      if (verbose) $display("issueBramReadRequest addr=%h first=%d last=%d", item.value, item.first, item.last);
   endrule

   rule readData;
      Vector#(n, dataType) vs = unpack(0);
      for (Integer i = 0; i < valueOf(n); i = i + 1)
	 vs[i] <- bramServer[i].response.get();
      match { .first, .last } <- toGet(firstlastFifo).get();
      readDataFifo.enq(IteratorValue { value: vs, first: first, last: last });
   endrule
   return toPipeOut(readDataFifo);
endmodule

interface BramWriterPipe#(numeric type dsz);
   interface PipeOut#(Bool) lastPipe;
endinterface

module mkBramWriterPipe#(BRAMServer#(Bit#(addrsz), dtype) bramServer,
			IteratorIfc#(Bit#(addrsz)) addrIterator,
			PipeOut#(dtype) dataPipe)(BramWriterPipe#(dsz))
   provisos (Bits#(dtype, dsz),
	     Add#(a__, addrsz, MemOffsetSize));

   FIFOF#(Bool)                       lastFifo <- mkFIFOF();
   FIFOF#(Bool)                       doneFifo <- mkFIFOF();

   Reg#(Bit#(32)) wrrCount <- mkReg(0);
   Reg#(Bit#(32)) wdoneCount <- mkReg(0);
   rule writeReqRule;
      let offset <- toGet(addrIterator.pipe).get();
      let v <- toGet(dataPipe).get();
      wrrCount <= wrrCount + 1;
      //$display("BramWriter.writeReqRule: offset=%h addrIterator.isLast %d wrr %d", offset, addrIterator.isLast(), wrrCount);
      bramServer.request.put(BRAMRequest { write: True, responseOnWrite: False, address: offset, datain: v });
      lastFifo.enq(addrIterator.isLast());
   endrule
   rule writeDone;
      let last <- toGet(lastFifo).get();
      //$display("writeDone: wdoneCount=%d last=%d", wdoneCount, last);
      wdoneCount <= wdoneCount + 1;
      doneFifo.enq(last);
   endrule
   interface PipeOut lastPipe = toPipeOut(doneFifo);
endmodule

// Copyright (c) 2015 Connectal Project.

// 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 FIFO::*;
import FIFOF::*;
import GetPut::*;
import ClientServer::*;
import BRAM::*;
import Vector::*;
import Probe::*;

import MemTypes::*;
import Pipe::*;
import ConfigCounter::*;

interface MemReaderPipe#(numeric type dsz);
   interface PipeOut#(MemData#(dsz)) dataPipe;
   interface MemReadClient#(dsz) readClient;
endinterface

module mkMemReaderPipe#(Reg#(SGLId) ptrReg,
			IteratorIfc#(Bit#(addrsz)) addrIterator,
			Bit#(BurstLenSize) burstLen)(MemReaderPipe#(dsz))
   provisos (Add#(a__, addrsz, MemOffsetSize),
	     Add#(b__, BurstLenSize, addrsz));

   let verbose = False;

   ConfigCounter#(addrsz)              counter <- mkConfigCounter(0);
   FIFO#(MemRequest) readReqFifo <- mkFIFO();
   FIFOF#(MemData#(dsz)) readDataFifo <- mkSizedFIFOF(8);
   Reg#(Bit#(MemTagSize)) tagReg <- mkReg(0);

   // 8+1 outstanding reads
   rule startReadReqRule if (counter.read() <= (extend(unpack(burstLen)) << 3));
      counter.increment(extend(unpack(burstLen)));
      let offset <- toGet(addrIterator.pipe).get();
      let tag = tagReg;
      if (addrIterator.isFirst())
	 tag = 0;
      if (verbose) $display("startReadReqRule: offset=%d counter=%d", offset, counter.read() + (extend(unpack(burstLen)) << 3));
      readReqFifo.enq(MemRequest { sglId: ptrReg, offset: extend(offset), burstLen: burstLen, tag: extend(tag) });
      tagReg <= tag + 1;
   endrule

   interface dataPipe = toPipeOut(readDataFifo);
   interface MemReadClient readClient;
      interface Get readReq = toGet(readReqFifo);
      interface Put readData;
	 method Action put(MemData#(dsz) md);
	    readDataFifo.enq(md);
	    counter.decrement(fromInteger(valueOf(TDiv#(dsz,8))));
	    if (verbose) $display("memreader.readData counter.read() %d", counter.read());
	 endmethod
      endinterface
   endinterface
endmodule

interface MemWriterPipe#(numeric type dsz);
   interface PipeOut#(Bool) lastPipe;
   interface MemWriteClient#(dsz) writeClient;
endinterface

module mkMemWriterPipe#(Reg#(SGLId) ptrReg,
			IteratorIfc#(Bit#(addrsz)) addrIterator,
			PipeOut#(dtype) dataPipe,
			Bit#(BurstLenSize) burstLen)(MemWriterPipe#(dsz))
   provisos (Bits#(dtype, dsz),
	     Add#(a__, addrsz, MemOffsetSize),
	     Add#(b__, BurstLenSize, addrsz));

   ConfigCounter#(addrsz)              counter <- mkConfigCounter(0);
   FIFO#(MemRequest)                   reqFifo <- mkSizedFIFO(4);
   FIFO#(MemRequest)              writeReqFifo <- mkFIFO();
   FIFOF#(MemData#(dsz))         writeDataFifo <- mkSizedFIFOF(4);
   FIFO#(Bit#(MemTagSize))       writeDoneFifo <- mkSizedFIFO(4);
   FIFOF#(Bool)                       lastFifo <- mkSizedFIFOF(4);
   FIFOF#(Bool)                       doneFifo <- mkSizedFIFOF(4);

   rule writeReqRule;
      let offset <- toGet(addrIterator.pipe).get();
      let tag = 22;
      $display("writeReqRule: offset=%h burstLen=%d addrIterator.isLast %d", offset, burstLen, addrIterator.isLast());
      reqFifo.enq(MemRequest { sglId: ptrReg, offset: extend(offset), burstLen: burstLen, tag: tag });
      lastFifo.enq(addrIterator.isLast());
   endrule
   rule writeReqReadyRule if (counter.read() >= extend(unpack(burstLen)));
      let req <- toGet(reqFifo).get();
      writeReqFifo.enq(req);
      counter.decrement(extend(unpack(burstLen)));
   endrule
   rule writeDataRule;
      let tag = 22;
      let v <- toGet(dataPipe).get();
      //$display("MemWriterPipe.writeDataRule: data=%h", v);
      writeDataFifo.enq(MemData { data: pack(v), tag: tag, last: False });
      counter.increment(fromInteger(valueOf(TDiv#(dsz,8))));
   endrule
   rule writeDone;
      let last <- toGet(lastFifo).get();
      let tag <- toGet(writeDoneFifo).get();
      doneFifo.enq(last);
   endrule
   interface PipeOut lastPipe = toPipeOut(doneFifo);
   interface MemWriteClient writeClient;
      interface Get writeReq = toGet(writeReqFifo);
      interface Get writeData = toGet(writeDataFifo);
      interface Put writeDone = toPut(writeDoneFifo);
   endinterface
endmodule

module mkMemWriterPipe2#(Bool lastOnly,
			 Reg#(SGLId) ptrReg,
			 IteratorIfc#(Bit#(addrsz)) addrIterator,
			 PipeOut#(dtype) dataPipe,
			 Bit#(BurstLenSize) burstLen)(MemWriterPipe#(dsz))
   provisos (Bits#(dtype, dsz),
	     Add#(a__, addrsz, MemOffsetSize),
	     Add#(b__, BurstLenSize, addrsz));

   ConfigCounter#(addrsz)              counter <- mkConfigCounter(0);
   FIFO#(MemRequest)                   reqFifo <- mkSizedFIFO(4);
   FIFO#(MemRequest)              writeReqFifo <- mkFIFO();
   FIFOF#(MemData#(dsz))         writeDataFifo <- mkSizedFIFOF(4);
   FIFO#(Bit#(MemTagSize))       writeDoneFifo <- mkSizedFIFO(4);
   FIFOF#(Bool)                       lastFifo <- mkSizedFIFOF(4);
   FIFOF#(Bool)                       doneFifo <- mkFIFOF();

   rule writeReqRule;
      let offset <- toGet(addrIterator.pipe).get();
      let tag = 22;
      $display("writeReqRule: offset=%h burstLen=%d addrIterator.isLast %d", offset, burstLen, addrIterator.isLast());
      reqFifo.enq(MemRequest { sglId: ptrReg, offset: extend(offset), burstLen: burstLen, tag: tag });
      lastFifo.enq(addrIterator.isLast());
   endrule
   rule writeReqReadyRule if (counter.read() >= extend(unpack(burstLen)));
      let req <- toGet(reqFifo).get();
      writeReqFifo.enq(req);
      counter.decrement(extend(unpack(burstLen)));
   endrule
   rule writeDataRule;
      let tag = 22;
      let v <- toGet(dataPipe).get();
      //$display("MemWriterPipe.writeDataRule: data=%h", v);
      writeDataFifo.enq(MemData { data: pack(v), tag: tag, last: False });
      counter.increment(fromInteger(valueOf(TDiv#(dsz,8))));
   endrule
   rule writeDone;
      let last <- toGet(lastFifo).get();
      let tag <- toGet(writeDoneFifo).get();
      if (!lastOnly || last)
	 doneFifo.enq(last);
   endrule
   interface PipeOut lastPipe = toPipeOut(doneFifo);
   interface MemWriteClient writeClient;
      interface Get writeReq = toGet(writeReqFifo);
      interface Get writeData = toGet(writeDataFifo);
      interface Put writeDone = toPut(writeDoneFifo);
   endinterface
endmodule

module mkBramReaderPipe#(BRAMServer#(Bit#(addrsz), dataType) bramServer,
			 PipeOut#(IteratorValue#(Bit#(addrsz),void)) addrIterator)(PipeOut#(IteratorValue#(dataType,void)))
   provisos (Add#(a__, addrsz, MemOffsetSize),
	     Bits#(dataType,dsz));

   FIFOF#(Tuple2#(Bool,Bool)) firstlastFifo <- mkFIFOF();
   FIFOF#(IteratorValue#(dataType,void)) readDataFifo <- mkFIFOF();

   let verbose = False;

   rule issueBramReadRequest;
      let item <- toGet(addrIterator).get();
      bramServer.request.put(BRAMRequest{write: False, responseOnWrite: False, address: item.value, datain: unpack(0)});
      firstlastFifo.enq(tuple2(item.first, item.last));
      if (verbose) $display("issueBramReadRequest addr=%h first=%d last=%d", item.value, item.first, item.last);
   endrule

   rule readData;
      let v <- bramServer.response.get();
      match { .first, .last } <- toGet(firstlastFifo).get();
      readDataFifo.enq(IteratorValue { value: v, first: first, last: last });
   endrule
   return toPipeOut(readDataFifo);
endmodule

interface BramWriterPipe#(numeric type dsz);
   interface PipeOut#(Bool) lastPipe;
endinterface

module mkBramWriterPipe#(BRAMServer#(Bit#(addrsz), dtype) bramServer,
			IteratorIfc#(Bit#(addrsz)) addrIterator,
			PipeOut#(dtype) dataPipe)(BramWriterPipe#(dsz))
   provisos (Bits#(dtype, dsz),
	     Add#(a__, addrsz, MemOffsetSize));

   FIFOF#(Bool)                       lastFifo <- mkFIFOF();
   FIFOF#(Bool)                       doneFifo <- mkFIFOF();

   Reg#(Bit#(32)) wrrCount <- mkReg(0);
   Reg#(Bit#(32)) wdoneCount <- mkReg(0);
   rule writeReqRule;
      let offset <- toGet(addrIterator.pipe).get();
      let v <- toGet(dataPipe).get();
      wrrCount <= wrrCount + 1;
      //$display("BramWriter.writeReqRule: offset=%h addrIterator.isLast %d wrr %d", offset, addrIterator.isLast(), wrrCount);
      bramServer.request.put(BRAMRequest { write: True, responseOnWrite: False, address: offset, datain: v });
      lastFifo.enq(addrIterator.isLast());
   endrule
   rule writeDone;
      let last <- toGet(lastFifo).get();
      //$display("writeDone: wdoneCount=%d last=%d", wdoneCount, last);
      wdoneCount <= wdoneCount + 1;
      doneFifo.enq(last);
   endrule
   interface PipeOut lastPipe = toPipeOut(doneFifo);
endmodule


Use 16MB BAR2 on KC705 also

Use 16MB BAR2 on KC705 also