anchor.diff:     Reg#(MatrixDescriptor#(UInt#(addrwidth))) descriptorC <- mkReg(unpack(0));
      Reg#(UInt#(addrwidth)) dotprodCount <- mkReg(0);
   
  -   Vector#(J, Vector#(K, PipeOut#(Vector#(N,Float)))) aPipes  <- mapM(mkSizedForkVector(valueOf(SourceBufferSize)), map(vectorSourcePipe, sourceA));
  -   Vector#(K, Vector#(J, PipeOut#(Vector#(N,Float)))) bPipesT <- mapM(mkForkVector, map(vectorSourcePipe, sourceB));
  -   Vector#(J, Vector#(K, PipeOut#(Vector#(N,Float)))) bPipes  =  transpose(bPipesT);
  +   Vector#(J, PipeOut#(Vector#(N,Float))) aPipes  = map(vectorSourcePipe, sourceA);
  +   Vector#(K, Vector#(J, PipeOut#(Vector#(N,Float)))) bPipes  <- mapM(mkForkVector, map(vectorSourcePipe, sourceB));
   
      rule countCycles;
         cycles <= cycles+1;
      endrule
   
  -//`define OLDWAY
  -`ifdef OLDWAY
  -   function Module#(DotProdServer#(N)) mkFxDotProd(Integer i);
  -      return mkDotProdServer(fromInteger(i));
  +   function Module#(SharedDotProdServer#(K,N)) mkFxDotProd(Integer i);
  +      return mkSharedDotProdServer(fromInteger(i));
      endfunction
  -   function Put#(Tuple2#(Vector#(n,Float),Vector#(n,Float))) getDotProdServerRequestInterface(DotProdServer#(n) s); return s.request; endfunction
  -   function PipeOut#(Float) getDotProdServerPipe(DotProdServer#(n) s); return s.pipe; endfunction
  -   Vector#(TMul#(J,K), DotProdServer#(N)) fxdotprods <- genWithM(mkFxDotProd);
  -   Vector#(TMul#(J,K), PipeOut#(Float)) fxpipes = map(getDotProdServerPipe, fxdotprods);
  -
  +   function Vector#(k,PipeOut#(Float)) getDotProdServerPipes(SharedDotProdServer#(k,n) s); return s.pipes; endfunction
  +   Vector#(J, SharedDotProdServer#(K,N)) fxdotprods <- genWithM(mkFxDotProd);
  +   Vector#(J, Vector#(K, PipeOut#(Float))) fxpipes = map(getDotProdServerPipes, fxdotprods);
  +
  +   FirstLastPipe#(UInt#(addrwidth)) firstLastPipe <- mkFirstLastPipe();
  +   Vector#(2, PipeOut#(Tuple2#(Bool,Bool))) firstLastPipes      <- mkForkVector(firstLastPipe.pipe);
  +
  +   for (Integer j = 0; j < jj; j = j + 1)
  +      mkConnection(toGet(aPipes[j]), fxdotprods[j].aInput);
      for (Integer k = 0; k < kk; k = k+1) begin
         for (Integer j = 0; j < jj; j = j + 1) begin
  -	 rule connectDotProd;
  -	    let index = j*kk+k;
  -	    let a <- toGet(aPipes[j][k]).get();
  -	    let b <- toGet(bPipes[j][k]).get();
  -	    int jint = fromInteger(j);
  -	    int kint = fromInteger(k);
  -	    //$display($format(fshow("connectDotProd pos=")+fshow(tuple2(jint,kint))+fshow(" a=")+fshow(pack(a))+fshow(" b=")+fshow(pack(b))));
  -	    fxdotprods[index].request.put(tuple2(a, b));
  -	 endrule
  +	 mkConnection(toGet(bPipes[k][j]), fxdotprods[j].bInput[k]);
         end
      end
  -`else
  -   FirstLastPipe#(UInt#(addrwidth)) firstLastPipe <- mkFirstLastPipe();
  -   Vector#(2, PipeOut#(Tuple2#(Bool,Bool))) firstLastPipes      <- mkForkVector(firstLastPipe.pipe);
  -
  -   Vector#(TMul#(J,K), FIFOF#(Float))   accumFifos  <- replicateM(mkFIFOF);
  -   Vector#(TMul#(J,K), PipeOut#(Float)) accumPipes  =  map(toPipeOut, accumFifos);
  -   PipeOut#(Vector#(TMul#(J,K), Float)) accumPipe   <- mkJoinVector(id, accumPipes);
  -   PipeOut#(Vector#(M, Float))          accumFunnel <- mkFunnel(accumPipe);
  -
  -   rule primeTheAccum;
  -      match { .first, .last } <- toGet(firstLastPipes[0]).get();
  -      if (first)
  -	 for (Integer i = 0; i < valueOf(TMul#(J,K)); i = i + 1)
  -	    accumFifos[i].enq(unpack(0));
  -   endrule
  -
  -   Vector#(TMul#(J,K), PipeOut#(Vector#(1,Float))) aPipeVec <- mapM(mkFunnel, flattenMatrix(aPipes));
  -   Vector#(TMul#(J,K), PipeOut#(Vector#(1,Float))) bPipeVec <- mapM(mkFunnel, flattenMatrix(bPipes));
  -   Vector#(TMul#(J,K), PipeOut#(Tuple2#(Vector#(1,Float),Vector#(1,Float)))) abPipeVec = map(uncurry(zipPipeOut), zip(aPipeVec, bPipeVec));
  -   PipeOut#(Vector#(TMul#(J,K), Tuple2#(Vector#(1,Float),Vector#(1,Float)))) abPipe <- mkJoinVector(id, abPipeVec);
  -
  -
  -   PipeOut#(Vector#(M, Tuple2#(Vector#(1,Float),Vector#(1,Float)))) abFunnel <- mkFunnel(abPipe);
  -   Vector#(M, FloatAlu#(FP_MUL_DEPTH)) muls <- replicateM(mkFloatMultiplier(defaultValue));
  -   Vector#(M, FloatAlu#(FP_ADD_DEPTH)) adders <- replicateM(mkFloatAdder(defaultValue));
  -   rule mulreq;
  -      let vec <- toGet(abFunnel).get();
  -      $display("%d mulreq", cycles);
  -      for (Integer i = 0; i < valueOf(M); i = i + 1) begin
  -	 match { .avec, .bvec } = vec[i];
  -	 muls[i].request.put(tuple2(avec[0], bvec[0]));
  -      end
  -   endrule
  -   rule accumreq;
  -      $display("%d accumreq", cycles);
  -      let accum <- toGet(accumFunnel).get();
  -      for (Integer i = 0; i < valueOf(M); i = i + 1) begin
  -	 match {.resp, .*} <- muls[i].response.get();
  -	 adders[i].request.put(tuple2(resp, accum[i]));
  -      end
  -   endrule
  -   FIFOF#(Vector#(M, Float))   accumOutFunnel     <- mkFIFOF();
  -   PipeOut#(Vector#(M, Float)) accumOutFunnelPipe =  toPipeOut(accumOutFunnel);
  -   rule accumresp;
  -      function ActionValue#(Float) getAccumResponse(FloatAlu#(depth) adder); actionvalue match {.resp, .*} <- adder.response.get(); return resp; endactionvalue endfunction
  -      Vector#(M,Float) accum <- mapM(getAccumResponse, adders);
  -      accumOutFunnel.enq(accum);
  -   endrule
  -   PipeOut#(Vector#(TMul#(J,K), (Float))) accumOutPipe <- mkUnfunnel(accumOutFunnelPipe);
  -   Vector#(TMul#(J,K), FIFOF#(Float)) resultFifos <- replicateM(mkFIFOF());
  -   rule feedback;
  -      let accumOut <- toGet(accumOutPipe).get();
  -      match { .first, .last } <- toGet(firstLastPipes[1]).get();
  -      for (Integer i = 0; i < valueOf(TMul#(J,K)); i = i + 1)
  -	 if (last)
  -	    resultFifos[i].enq(accumOut[i]);
  -	 else
  -	    accumFifos[i].enq(accumOut[i]);
  -   endrule
  -   Vector#(TMul#(J,K), PipeOut#(Float)) fxpipes = map(toPipeOut, resultFifos);
  -
  -`endif
  +
      MIMOConfiguration mimoCfg = defaultValue;
      MIMO#(K,N,TAdd#(K,N),Float) dfifo <- mkMIMO(mimoCfg);
      Vector#(J, MIMO#(K,N,TAdd#(K,N),Float)) dfifos <- replicateM(mkMIMO(mimoCfg));
  
positive.code:    interface PipeOut pipe = dotpipe;
     interface Reg numElts = numEltsReg;
  endmodule : mkDotProdServer
  
  function Vector#(TMul#(j,k), etype) flattenMatrix(Vector#(j, Vector#(k, etype)) mat);
     function etype flatten(Integer i); return mat[i/valueOf(k)][i%valueOf(k)]; endfunction
  
negative.code: 	 Vector#(K,Float) vs;
  	 for (Integer k = 0; k < kk; k = k + 1) begin
  	    let dpnum = j*kk+k;
  	    let v <- toGet(fxpipes[j][k]).get();
  	    //let indexi = tuple2(tpl_1(index), tpl_2(index)+fromInteger(k));
  	    //if (verbose) $display($format(fshow(cycles)+fshow("    dotprodvalue index=")+fshow(indexi)+fshow(" dotprod=")+fshow(v)));
  	    int jint = fromInteger(j);
  