change tag back to 0 to see if it fixes TileTagOutOfRange

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

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

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

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

`ifdef NumEngineServers
typedef `NumEngineServers NumEngineServers;
`else
typedef 1 NumEngineServers;
`endif

typedef TDiv#(DataBusWidth,32) DataBusWords;

interface MemwriteRequest;
   method Action startWrite(Bit#(32) pointer, Bit#(32) offset, Bit#(32) numWords, Bit#(32) burstLen, Bit#(32) iterCnt);
   method Action getStateDbg();
endinterface

interface Memwrite;
   interface MemwriteRequest request;
   interface Vector#(1,MemWriteClient#(DataBusWidth)) dmaClient;
endinterface

interface MemwriteIndication;
   method Action started(Bit#(32) numWords);
   method Action reportStateDbg(Bit#(32) wrCnt, Bit#(32) srcGen);
   method Action writeDone(Bit#(32) v);
endinterface

module  mkMemwrite#(MemwriteIndication indication) (Memwrite);

   Reg#(SGLId)   pointer <- mkReg(0);
   Reg#(Bit#(32))       numWords <- mkReg(0);
   Reg#(Bit#(32))       burstLen <- mkReg(0);
   FIFOF#(void)               cf <- mkSizedFIFOF(1);

   Vector#(NumEngineServers, Reg#(Bit#(32)))         srcGens <- replicateM(mkReg(0));
   Reg#(Bit#(32))                                writeOffset <- mkReg(0);
   Reg#(Bit#(32))                                    iterCnt <- mkReg(0);
   Vector#(NumEngineServers, Reg#(Bit#(32)))        iterCnts <- replicateM(mkReg(0));
   Vector#(NumEngineServers, FIFOF#(void))               cfs <- replicateM(mkSizedFIFOF(1));
   Vector#(NumEngineServers, FIFOF#(Bool))       finishFifos <- replicateM(mkFIFOF);
   MemWriteEngine#(DataBusWidth,DataBusWidth,2,NumEngineServers)                we <- mkMemWriteEngine;
   Bit#(32) chunk = (extend(numWords)/fromInteger(valueOf(NumEngineServers)))*4;

   for(Integer i = 0; i < valueOf(NumEngineServers); i=i+1) begin
      rule start (iterCnts[i] > 0);
	 we.writeServers[i].request.put(MemengineCmd{tag:0, sglId:pointer, base:extend(writeOffset)+(fromInteger(i)*chunk), len:truncate(chunk), burstLen:truncate(burstLen*4)});
	 Bit#(32) srcGen = (writeOffset/4)+(fromInteger(i)*truncate(chunk/4));
	 srcGens[i] <= srcGen;
	 $display("start %d/%d, %h 0x%x %h", i, valueOf(NumEngineServers), srcGen, iterCnts[i], writeOffset);
	 cfs[i].enq(?);
	 iterCnts[i] <= iterCnts[i]-1;
      endrule
`ifdef MEMENGINE_REQUEST_CYCLES
      rule requestCycles;
	 let reqcycles <- toGet(we.writeServers[i].requestCycles).get();
	 $display("request %d took %d cycles", reqcycles.tag, reqcycles.cycles);
      endrule
`endif
      rule finish;
	 $display("finish %d 0x%x", i, iterCnts[i]);
	 let rv <- we.writeServers[i].done.get;
	 finishFifos[i].enq(rv);
      endrule
      rule src if (cfs[i].notEmpty);
	 Vector#(DataBusWords, Bit#(32)) v;
	 for (Integer j = 0; j < valueOf(DataBusWords); j = j + 1)
	    v[j] = srcGens[i]+fromInteger(j);
	 we.writeServers[i].data.enq(pack(v));
	 let new_srcGen = srcGens[i]+fromInteger(valueOf(DataBusWords));
	 srcGens[i] <= new_srcGen;
	 if(new_srcGen == (writeOffset/4)+(fromInteger(i+1)*truncate(chunk/4)))
	    cfs[i].deq;
      endrule
   end

   PipeOut#(Vector#(NumEngineServers, Bool)) finishPipe <- mkJoinVector(id, map(toPipeOut, finishFifos));
   PipeOut#(Bool) finishReducePipe <- mkReducePipe(uncurry(booland), finishPipe);

   rule indicate_finish;
      let rv <- toGet(finishReducePipe).get();
      if (iterCnt == 1) begin
	 cf.deq;
	 indication.writeDone(0);
      end
      iterCnt <= iterCnt - 1;
   endrule

   interface MemWriteClient dmaClient = cons(we.dmaClient, nil);
   interface MemwriteRequest request;
       method Action startWrite(Bit#(32) wp, Bit#(32) off, Bit#(32) nw, Bit#(32) bl, Bit#(32) ic);
	  $display("startWrite pointer=%d offset=%d numWords=%h burstLen=%d iterCnt=%d", pointer, off, nw, bl, ic);
	  indication.started(nw);
	  pointer <= wp;
	  cf.enq(?);
	  numWords  <= nw;
	  burstLen  <= bl;
	  iterCnt <= ic;
	  writeOffset <= off*4;
	  for(Integer i = 0; i < valueOf(NumEngineServers); i=i+1)
	     iterCnts[i] <= ic;
       endmethod
   endinterface
endmodule

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

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

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

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

`ifdef NumEngineServers
typedef `NumEngineServers NumEngineServers;
`else
typedef 1 NumEngineServers;
`endif

typedef TDiv#(DataBusWidth,32) DataBusWords;

interface MemwriteRequest;
   method Action startWrite(Bit#(32) pointer, Bit#(32) offset, Bit#(32) numWords, Bit#(32) burstLen, Bit#(32) iterCnt);
   method Action getStateDbg();
endinterface

interface Memwrite;
   interface MemwriteRequest request;
   interface Vector#(1,MemWriteClient#(DataBusWidth)) dmaClient;
endinterface

interface MemwriteIndication;
   method Action started(Bit#(32) numWords);
   method Action reportStateDbg(Bit#(32) wrCnt, Bit#(32) srcGen);
   method Action writeDone(Bit#(32) v);
endinterface

module  mkMemwrite#(MemwriteIndication indication) (Memwrite);

   Reg#(SGLId)   pointer <- mkReg(0);
   Reg#(Bit#(32))       numWords <- mkReg(0);
   Reg#(Bit#(32))       burstLen <- mkReg(0);
   FIFOF#(void)               cf <- mkSizedFIFOF(1);

   Vector#(NumEngineServers, Reg#(Bit#(32)))         srcGens <- replicateM(mkReg(0));
   Reg#(Bit#(32))                                writeOffset <- mkReg(0);
   Reg#(Bit#(32))                                    iterCnt <- mkReg(0);
   Vector#(NumEngineServers, Reg#(Bit#(32)))        iterCnts <- replicateM(mkReg(0));
   Vector#(NumEngineServers, FIFOF#(void))               cfs <- replicateM(mkSizedFIFOF(1));
   Vector#(NumEngineServers, FIFOF#(Bool))       finishFifos <- replicateM(mkFIFOF);
   MemWriteEngine#(DataBusWidth,DataBusWidth,2,NumEngineServers)                we <- mkMemWriteEngine;
   Bit#(32) chunk = (extend(numWords)/fromInteger(valueOf(NumEngineServers)))*4;

   for(Integer i = 0; i < valueOf(NumEngineServers); i=i+1) begin
      rule start (iterCnts[i] > 0);
	 we.writeServers[i].request.put(MemengineCmd{tag:truncate(iterCnts[i]), sglId:pointer, base:extend(writeOffset)+(fromInteger(i)*chunk), len:truncate(chunk), burstLen:truncate(burstLen*4)});
	 Bit#(32) srcGen = (writeOffset/4)+(fromInteger(i)*truncate(chunk/4));
	 srcGens[i] <= srcGen;
	 $display("start %d/%d, %h 0x%x %h", i, valueOf(NumEngineServers), srcGen, iterCnts[i], writeOffset);
	 cfs[i].enq(?);
	 iterCnts[i] <= iterCnts[i]-1;
      endrule
`ifdef MEMENGINE_REQUEST_CYCLES
      rule requestCycles;
	 let reqcycles <- toGet(we.writeServers[i].requestCycles).get();
	 $display("request %d took %d cycles", reqcycles.tag, reqcycles.cycles);
      endrule
`endif
      rule finish;
	 $display("finish %d 0x%x", i, iterCnts[i]);
	 let rv <- we.writeServers[i].done.get;
	 finishFifos[i].enq(rv);
      endrule
      rule src if (cfs[i].notEmpty);
	 Vector#(DataBusWords, Bit#(32)) v;
	 for (Integer j = 0; j < valueOf(DataBusWords); j = j + 1)
	    v[j] = srcGens[i]+fromInteger(j);
	 we.writeServers[i].data.enq(pack(v));
	 let new_srcGen = srcGens[i]+fromInteger(valueOf(DataBusWords));
	 srcGens[i] <= new_srcGen;
	 if(new_srcGen == (writeOffset/4)+(fromInteger(i+1)*truncate(chunk/4)))
	    cfs[i].deq;
      endrule
   end

   PipeOut#(Vector#(NumEngineServers, Bool)) finishPipe <- mkJoinVector(id, map(toPipeOut, finishFifos));
   PipeOut#(Bool) finishReducePipe <- mkReducePipe(uncurry(booland), finishPipe);

   rule indicate_finish;
      let rv <- toGet(finishReducePipe).get();
      if (iterCnt == 1) begin
	 cf.deq;
	 indication.writeDone(0);
      end
      iterCnt <= iterCnt - 1;
   endrule

   interface MemWriteClient dmaClient = cons(we.dmaClient, nil);
   interface MemwriteRequest request;
       method Action startWrite(Bit#(32) wp, Bit#(32) off, Bit#(32) nw, Bit#(32) bl, Bit#(32) ic);
	  $display("startWrite pointer=%d offset=%d numWords=%h burstLen=%d iterCnt=%d", pointer, off, nw, bl, ic);
	  indication.started(nw);
	  pointer <= wp;
	  cf.enq(?);
	  numWords  <= nw;
	  burstLen  <= bl;
	  iterCnt <= ic;
	  writeOffset <= off*4;
	  for(Integer i = 0; i < valueOf(NumEngineServers); i=i+1)
	     iterCnts[i] <= ic;
       endmethod
   endinterface
endmodule


there is no need to have muls on the critical path in SGList.  In fact, if we are willing to add a 'reset' method, we can get rid of them alltogether

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

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

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

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

// BSV Libraries
import RegFile::*;
import FIFOF::*;
import Vector::*;
import GetPut::*;
import BRAMFIFO::*;
import BRAM::*;
import Dma::*;
import StmtFSM::*;
import ClientServer::*;

typedef 16 MaxNumSGLists;
typedef Bit#(TLog#(MaxNumSGLists)) SGListId;
typedef 12 SGListPageShift0;
typedef 16 SGListPageShift4;
typedef 20 SGListPageShift8;

interface SGListMMU#(numeric type addrWidth);
   method Action sglist(Bit#(32) pointer, Bit#(DmaOffsetSize) offset, Bit#(32) len);
   interface Vector#(2,Server#(Tuple2#(SGListId,Bit#(DmaOffsetSize)),Bit#(addrWidth))) addr;
endinterface

typedef union tagged{
   Bit#(SGListPageShift0) OOrd0;
   Bit#(SGListPageShift4) OOrd4;
   Bit#(SGListPageShift8) OOrd8;
} Offset deriving (Eq,Bits);

typedef union tagged{
   Bit#(TSub#(DmaOffsetSize,SGListPageShift0)) POrd0;
   Bit#(TSub#(DmaOffsetSize,SGListPageShift4)) POrd4;
   Bit#(TSub#(DmaOffsetSize,SGListPageShift8)) POrd8;
} Page deriving (Eq,Bits);

module mkSGListMMU(SGListMMU#(addrWidth))

   provisos(Log#(MaxNumSGLists, listIdxSize),
	    Add#(listIdxSize,8, entryIdxSize),
	    Add#(c__, addrWidth, DmaOffsetSize));

   BRAM2Port#(Bit#(entryIdxSize), Page) pageTable <- mkBRAM2Server(defaultValue);
   Vector#(MaxNumSGLists, Reg#(Tuple3#(Bit#(40),Bit#(40),Bit#(40)))) regions <- replicateM(mkReg(unpack(0)));

   Vector#(2,FIFOF#(Offset))  offs <- replicateM(mkFIFOF);
   Reg#(Bit#(8))               idxReg  <- mkReg(0);

   let page_shift0 = fromInteger(valueOf(SGListPageShift0));
   let page_shift4 = fromInteger(valueOf(SGListPageShift4));
   let page_shift8 = fromInteger(valueOf(SGListPageShift8));

   let ord0 = 40'd1 << page_shift0;
   let ord4 = 40'd1 << page_shift4;
   let ord8 = 40'd1 << page_shift8;

   function BRAMServer#(Bit#(entryIdxSize), Page) portsel(int i);
      if(i==0)
	 return pageTable.portA;
      else
	 return pageTable.portB;
   endfunction

   Vector#(2,Server#(Tuple2#(SGListId,Bit#(DmaOffsetSize)),Bit#(addrWidth))) addrServers;
   for(int i = 0; i < 2; i=i+1)
      addrServers[i] =
      (interface Server#(Tuple2#(SGListId,Bit#(DmaOffsetSize)),Bit#(addrWidth));
	  interface Put request;
	     method Action put(Tuple2#(SGListId,Bit#(DmaOffsetSize)) req);
		let ptr = tpl_1(req);
		let off = tpl_2(req);
		Offset o = ?;
		Bit#(8) p = ?;
		Bit#(40) barrier8 = tpl_3(regions[ptr-1]);
		Bit#(40) barrier4 = tpl_2(regions[ptr-1]);
		Bit#(40) barrier0 = tpl_1(regions[ptr-1]);
		if (off < barrier8) begin
		   //$display("request: ptr=%h off=%h barrier8=%h", ptr, off, barrier8);
		   o = tagged OOrd8 truncate(off);
		   p = truncate(off>>page_shift8);
		end
		else if (off < barrier4) begin
		   //$display("request: ptr=%h off=%h barrier4=%h", ptr, off, barrier4);
		   o = tagged OOrd4 truncate(off);
		   p = truncate(off>>page_shift4);
		end
		else if (off < barrier0) begin
		   //$display("request: ptr=%h off=%h barrier0=%h", ptr, off, barrier0);
		   o = tagged OOrd0 truncate(off);
		   p = truncate(off>>page_shift0);
		end
		else begin
		   $display("mkSGListMMU.addr[%d].request.put: ERROR\n", i);
		end
		offs[i].enq(o);
		portsel(i).request.put(BRAMRequest{write:False, responseOnWrite:False, address:{ptr-1,p}, datain:?});
	     endmethod
	  endinterface
	  interface Get response;
	     method ActionValue#(Bit#(addrWidth)) get();
		Bit#(DmaOffsetSize) rv = 0;
		let page <- portsel(i).response.get;
		let offset = offs[i].first;
		case (offset) matches
		   tagged OOrd0 .o:
		      rv = {page.POrd0,o};
		   tagged OOrd4 .o:
		      rv = {page.POrd4,o};
		   tagged OOrd8 .o:
		      rv = {page.POrd8,o};
		endcase
		offs[i].deq;
		return truncate(rv);
	     endmethod
	  endinterface
       endinterface);

   method Action sglist(Bit#(32) pointer, Bit#(DmaOffsetSize) offset, Bit#(32) len);
      $display("sglist(pointer=%d, offset=%h, len=%h", pointer, offset,len);
      if(len == 0) begin
	 idxReg <= 0;
      end
      else begin
	 if (idxReg+1 == 0) begin
	    $display("sglist: exceeded maximun length of sglist");
	 end
	 else begin
	    idxReg <= idxReg+1;
	 end
	 Tuple3#(Bit#(40),Bit#(40),Bit#(40)) tt = regions[pointer-1];
	 Page page = ?;
	 // if we were willing to have a "reset" method, we could get rid of the multiplies
	 if (extend(len) == ord0) begin
	    regions[pointer-1] <= tuple3(extend(idxReg+1)*ord0, tpl_2(tt), tpl_3(tt));
	    page = tagged POrd0 truncate(offset>>page_shift0);
	 end
	 else if (extend(len) == ord4) begin
	    regions[pointer-1] <= tuple3(tpl_1(tt), extend(idxReg+1)*ord4,tpl_3(tt));
	    page = tagged POrd4 truncate(offset>>page_shift4);
	 end
	 else if (extend(len) == ord8) begin
	    regions[pointer-1] <= tuple3(tpl_1(tt), tpl_2(tt),extend(idxReg+1)*ord8);
	    page = tagged POrd8 truncate(offset>>page_shift8);
	 end
	 else begin
	    $display("mkSGListMMU::sglist unsupported length %h", len);
	 end
	 portsel(0).request.put(BRAMRequest{write:True, responseOnWrite:False, address:{truncate(pointer-1),idxReg}, datain:page});
      end
   endmethod

   interface addr = addrServers;

endmodule

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

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

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

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

// BSV Libraries
import RegFile::*;
import FIFOF::*;
import Vector::*;
import GetPut::*;
import BRAMFIFO::*;
import BRAM::*;
import Dma::*;
import StmtFSM::*;
import ClientServer::*;

typedef 16 MaxNumSGLists;
typedef Bit#(TLog#(MaxNumSGLists)) SGListId;
typedef 12 SGListPageShift0;
typedef 16 SGListPageShift4;
typedef 20 SGListPageShift8;

interface SGListMMU#(numeric type addrWidth);
   method Action sglist(Bit#(32) pointer, Bit#(DmaOffsetSize) offset, Bit#(32) len);
   interface Vector#(2,Server#(Tuple2#(SGListId,Bit#(DmaOffsetSize)),Bit#(addrWidth))) addr;
endinterface

typedef union tagged{
   Bit#(SGListPageShift0) OOrd0;
   Bit#(SGListPageShift4) OOrd4;
   Bit#(SGListPageShift8) OOrd8;
} Offset deriving (Eq,Bits);

typedef union tagged{
   Bit#(TSub#(DmaOffsetSize,SGListPageShift0)) POrd0;
   Bit#(TSub#(DmaOffsetSize,SGListPageShift4)) POrd4;
   Bit#(TSub#(DmaOffsetSize,SGListPageShift8)) POrd8;
} Page deriving (Eq,Bits);

module mkSGListMMU(SGListMMU#(addrWidth))

   provisos(Log#(MaxNumSGLists, listIdxSize),
	    Add#(listIdxSize,8, entryIdxSize),
	    Add#(c__, addrWidth, DmaOffsetSize));

   BRAM2Port#(Bit#(entryIdxSize), Page) pageTable <- mkBRAM2Server(defaultValue);
   Vector#(MaxNumSGLists, Reg#(Tuple3#(Bit#(8),Bit#(8),Bit#(8)))) regions <- replicateM(mkReg(unpack(0)));

   Vector#(2,FIFOF#(Offset))  offs <- replicateM(mkFIFOF);
   Reg#(Bit#(8))               idxReg  <- mkReg(0);

   let page_shift0 = fromInteger(valueOf(SGListPageShift0));
   let page_shift4 = fromInteger(valueOf(SGListPageShift4));
   let page_shift8 = fromInteger(valueOf(SGListPageShift8));

   let ord0 = 32'd1 << page_shift0;
   let ord4 = 32'd1 << page_shift4;
   let ord8 = 32'd1 << page_shift8;

   function BRAMServer#(Bit#(entryIdxSize), Page) portsel(int i);
      if(i==0)
	 return pageTable.portA;
      else
	 return pageTable.portB;
   endfunction

   Vector#(2,Server#(Tuple2#(SGListId,Bit#(DmaOffsetSize)),Bit#(addrWidth))) addrServers;
   for(int i = 0; i < 2; i=i+1)
      addrServers[i] =
      (interface Server#(Tuple2#(SGListId,Bit#(DmaOffsetSize)),Bit#(addrWidth));
	  interface Put request;
	     method Action put(Tuple2#(SGListId,Bit#(DmaOffsetSize)) req);
		let ptr = tpl_1(req);
		let off = tpl_2(req);
		Offset o = ?;
		Bit#(8) p = ?;
		Bit#(40) barrier8 = extend(tpl_3(regions[ptr-1]))*extend(ord8);
		Bit#(40) barrier4 = extend(tpl_2(regions[ptr-1]))*extend(ord4);
		Bit#(40) barrier0 = extend(tpl_1(regions[ptr-1]))*extend(ord0);
		if (off < barrier8) begin
		   //$display("request: ptr=%h off=%h barrier8=%h", ptr, off, barrier8);
		   o = tagged OOrd8 truncate(off);
		   p = truncate(off>>page_shift8);
		end
		else if (off < barrier4) begin
		   //$display("request: ptr=%h off=%h barrier4=%h", ptr, off, barrier4);
		   o = tagged OOrd4 truncate(off);
		   p = truncate(off>>page_shift4);
		end
		else if (off < barrier0) begin
		   //$display("request: ptr=%h off=%h barrier0=%h", ptr, off, barrier0);
		   o = tagged OOrd0 truncate(off);
		   p = truncate(off>>page_shift0);
		end
		else begin
		   $display("mkSGListMMU.addr[%d].request.put: ERROR\n", i);
		end
		offs[i].enq(o);
		portsel(i).request.put(BRAMRequest{write:False, responseOnWrite:False, address:{ptr-1,p}, datain:?});
	     endmethod
	  endinterface
	  interface Get response;
	     method ActionValue#(Bit#(addrWidth)) get();
		Bit#(DmaOffsetSize) rv = 0;
		let page <- portsel(i).response.get;
		let offset = offs[i].first;
		case (offset) matches
		   tagged OOrd0 .o:
		      rv = {page.POrd0,o};
		   tagged OOrd4 .o:
		      rv = {page.POrd4,o};
		   tagged OOrd8 .o:
		      rv = {page.POrd8,o};
		endcase
		offs[i].deq;
		return truncate(rv);
	     endmethod
	  endinterface
       endinterface);

   method Action sglist(Bit#(32) pointer, Bit#(DmaOffsetSize) offset, Bit#(32) len);
      $display("sglist(pointer=%d, offset=%h, len=%h", pointer, offset,len);
      if(len == 0) begin
	 idxReg <= 0;
      end
      else begin
	 if (idxReg+1 == 0) begin
	    $display("sglist: exceeded maximun length of sglist");
	 end
	 else begin
	    idxReg <= idxReg+1;
	 end
	 Tuple3#(Bit#(8),Bit#(8),Bit#(8)) tt = regions[pointer-1];
	 Page page = ?;
	 if (len == ord0) begin
	    regions[pointer-1] <= tuple3(idxReg+1, tpl_2(tt), tpl_3(tt));
	    page = tagged POrd0 truncate(offset>>page_shift0);
	 end
	 else if (len == ord4) begin
	    regions[pointer-1] <= tuple3(tpl_1(tt), idxReg+1,tpl_3(tt));
	    page = tagged POrd4 truncate(offset>>page_shift4);
	 end
	 else if (len == ord8) begin
	    regions[pointer-1] <= tuple3(tpl_1(tt), tpl_2(tt),idxReg+1);
	    page = tagged POrd8 truncate(offset>>page_shift8);
	 end
	 else begin
	    $display("mkSGListMMU::sglist unsupported length %h", len);
	 end
	 portsel(0).request.put(BRAMRequest{write:True, responseOnWrite:False, address:{truncate(pointer-1),idxReg}, datain:page});
      end
   endmethod

   interface addr = addrServers;

endmodule


add requestSize and indicationSize methods to PipePortal

Change-Id: I735a9ef48ebcf2123c0fa71852fb5449b61648c5

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

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

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

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

import Vector::*;
import MemTypes::*;
import Leds::*;
import XADC::*;
import Pipe::*;
import ConnectalMemory::*;

// implementation of a Portal as a group of Pipes
interface PipePortal#(numeric type numRequests, numeric type numIndications, numeric type slaveDataWidth);
   method Bit#(16) requestSize(Bit#(16) methodNumber);
   method Bit#(16) indicationSize(Bit#(16) methodNumber);
   interface Vector#(numRequests, PipeIn#(Bit#(slaveDataWidth))) requests;
   interface Vector#(numIndications, PipeOut#(Bit#(slaveDataWidth))) indications;
endinterface

// implementation of a Portal as a physical memory slave
interface MemPortal#(numeric type slaveAddrWidth, numeric type slaveDataWidth);
   interface PhysMemSlave#(slaveAddrWidth,slaveDataWidth) slave;
   interface ReadOnly#(Bool) interrupt;
   interface WriteOnly#(Bool) top;
endinterface

function PhysMemSlave#(_a,_d) getSlave(MemPortal#(_a,_d) p);
   return p.slave;
endfunction

function ReadOnly#(Bool) getInterrupt(MemPortal#(_a,_d) p);
   return p.interrupt;
endfunction

function Vector#(16, ReadOnly#(Bool)) getInterruptVector(Vector#(numPortals, MemPortal#(_a,_d)) portals);
   Vector#(16, ReadOnly#(Bool)) interrupts = replicate(interface ReadOnly; method Bool _read(); return False; endmethod endinterface);
   for (Integer i = 0; i < valueOf(numPortals); i = i + 1)
      interrupts[i] = getInterrupt(portals[i]);
   return interrupts;
endfunction

interface SharedMemoryPortal#(numeric type dataBusWidth);
   interface MemReadClient#(dataBusWidth)  readClient;
   interface MemWriteClient#(dataBusWidth) writeClient;
   interface SharedMemoryPortalConfig cfg;
   interface ReadOnly#(Bool) interrupt;
endinterface

typedef MemPortal#(16,32) StdPortal;

interface ConnectalTop#(numeric type addrWidth, numeric type dataWidth, type pins, numeric type numMasters);
   interface PhysMemSlave#(32,32) slave;
   interface Vector#(numMasters,PhysMemMaster#(addrWidth, dataWidth)) masters;
   interface Vector#(16,ReadOnly#(Bool)) interrupt;
   interface LEDS             leds;
   interface pins             pins;
endinterface

typedef ConnectalTop#(addrWidth,64,Empty,0) StdConnectalTop#(numeric type addrWidth);
typedef ConnectalTop#(addrWidth,64,Empty,1) StdConnectalDmaTop#(numeric type addrWidth);

typeclass SynthesizableConnectalTop#(numeric type addrWidth, numeric type dataWidth, type pins, numeric type numMasters);
   module mkSynthesizableConnectalTop(ConnectalTop#(addrWidth,dataWidth,pins,numMasters) ifc);
endtypeclass

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

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

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

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

import Vector::*;
import MemTypes::*;
import Leds::*;
import XADC::*;
import Pipe::*;
import ConnectalMemory::*;

// implementation of a Portal as a group of Pipes
interface PipePortal#(numeric type numRequests, numeric type numIndications, numeric type slaveDataWidth);
   interface Vector#(numRequests, PipeIn#(Bit#(slaveDataWidth))) requests;
   interface Vector#(numIndications, PipeOut#(Bit#(slaveDataWidth))) indications;
endinterface

// implementation of a Portal as a physical memory slave
interface MemPortal#(numeric type slaveAddrWidth, numeric type slaveDataWidth);
   interface PhysMemSlave#(slaveAddrWidth,slaveDataWidth) slave;
   interface ReadOnly#(Bool) interrupt;
   interface WriteOnly#(Bool) top;
endinterface

function PhysMemSlave#(_a,_d) getSlave(MemPortal#(_a,_d) p);
   return p.slave;
endfunction

function ReadOnly#(Bool) getInterrupt(MemPortal#(_a,_d) p);
   return p.interrupt;
endfunction

function Vector#(16, ReadOnly#(Bool)) getInterruptVector(Vector#(numPortals, MemPortal#(_a,_d)) portals);
   Vector#(16, ReadOnly#(Bool)) interrupts = replicate(interface ReadOnly; method Bool _read(); return False; endmethod endinterface);
   for (Integer i = 0; i < valueOf(numPortals); i = i + 1)
      interrupts[i] = getInterrupt(portals[i]);
   return interrupts;
endfunction

interface SharedMemoryPortal#(numeric type dataBusWidth);
   interface MemReadClient#(dataBusWidth)  readClient;
   interface MemWriteClient#(dataBusWidth) writeClient;
   interface SharedMemoryPortalConfig cfg;
   interface ReadOnly#(Bool) interrupt;
endinterface

typedef MemPortal#(16,32) StdPortal;

interface ConnectalTop#(numeric type addrWidth, numeric type dataWidth, type pins, numeric type numMasters);
   interface PhysMemSlave#(32,32) slave;
   interface Vector#(numMasters,PhysMemMaster#(addrWidth, dataWidth)) masters;
   interface Vector#(16,ReadOnly#(Bool)) interrupt;
   interface LEDS             leds;
   interface pins             pins;
endinterface

typedef ConnectalTop#(addrWidth,64,Empty,0) StdConnectalTop#(numeric type addrWidth);
typedef ConnectalTop#(addrWidth,64,Empty,1) StdConnectalDmaTop#(numeric type addrWidth);

typeclass SynthesizableConnectalTop#(numeric type addrWidth, numeric type dataWidth, type pins, numeric type numMasters);
   module mkSynthesizableConnectalTop(ConnectalTop#(addrWidth,dataWidth,pins,numMasters) ifc);
endtypeclass


comment out unused(?) variants of SyncBits (to see if they are actually needed)

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

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

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

import Vector::*;
import Clocks::*;

module mkSyncBits#(a initValue, Clock sClkIn, Reset sRst, Clock dClkIn, Reset dRst)(SyncBitIfc#(a))
   provisos (Bits#(a,awidth));

   Reg#(a) ff0 <- mkReg(initValue, clocked_by sClkIn, reset_by sRst);
   Reg#(a) ff1 <- mkReg(initValue, clocked_by dClkIn, reset_by dRst);
   Reg#(a) ff2 <- mkReg(initValue, clocked_by dClkIn, reset_by dRst);

   ReadOnly#(a) ff0cross <- mkNullCrossingWire(dClkIn, ff0);

   rule update;
      ff1 <= ff0cross;
      ff2 <= ff1;
   endrule

   method a read();
      return ff2;
   endmethod: read

   method Action send(a value);
      ff0 <= value;
   endmethod: send
endmodule
/* Not needed?? -- jca
module mkSyncBitsFromCC#(a initValue, Clock dClkIn, Reset dRst)(SyncBitIfc#(a))
   provisos (Bits#(a,awidth));
   Clock sClkIn <- exposeCurrentClock();
   Reset sRst <- exposeCurrentReset();
   SyncBitIfc#(a) syncbits <- mkSyncBits(initValue, sClkIn, sRst, dClkIn, dRst);
   return syncbits;
endmodule

module mkSyncBitsToCC#(a initValue, Clock sClkIn, Reset sRst)(SyncBitIfc#(a))
   provisos (Bits#(a,awidth));
   Clock dClkIn <- exposeCurrentClock();
   Reset dRst <- exposeCurrentReset();
   SyncBitIfc#(a) syncbits <- mkSyncBits(initValue, sClkIn, sRst, dClkIn, dRst);
   return syncbits;
endmodule

module mkSyncBits128#(Clock sClkIn, Reset sRst, Clock dClkIn, Reset dRst)(SyncBitIfc#(Bit#(128)));
   SyncBitIfc#(Bit#(128)) sbits <- mkSyncBits(0, sClkIn, sRst, dClkIn, dRst);
   method read = sbits.read;
   method send = sbits.send;
endmodule: mkSyncBits128
*/

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

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

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

import Vector::*;
import Clocks::*;

module mkSyncBits#(a initValue, Clock sClkIn, Reset sRst, Clock dClkIn, Reset dRst)(SyncBitIfc#(a))
   provisos (Bits#(a,awidth));

   Reg#(a) ff0 <- mkReg(initValue, clocked_by sClkIn, reset_by sRst);
   Reg#(a) ff1 <- mkReg(initValue, clocked_by dClkIn, reset_by dRst);
   Reg#(a) ff2 <- mkReg(initValue, clocked_by dClkIn, reset_by dRst);

   ReadOnly#(a) ff0cross <- mkNullCrossingWire(dClkIn, ff0);

   rule update;
      ff1 <= ff0cross;
      ff2 <= ff1;
   endrule

   method a read();
      return ff2;
   endmethod: read

   method Action send(a value);
      ff0 <= value;
   endmethod: send
endmodule

module mkSyncBitsFromCC#(a initValue, Clock dClkIn, Reset dRst)(SyncBitIfc#(a))
   provisos (Bits#(a,awidth));
   Clock sClkIn <- exposeCurrentClock();
   Reset sRst <- exposeCurrentReset();
   SyncBitIfc#(a) syncbits <- mkSyncBits(initValue, sClkIn, sRst, dClkIn, dRst);
   return syncbits;
endmodule

module mkSyncBitsToCC#(a initValue, Clock sClkIn, Reset sRst)(SyncBitIfc#(a))
   provisos (Bits#(a,awidth));
   Clock dClkIn <- exposeCurrentClock();
   Reset dRst <- exposeCurrentReset();
   SyncBitIfc#(a) syncbits <- mkSyncBits(initValue, sClkIn, sRst, dClkIn, dRst);
   return syncbits;
endmodule

module mkSyncBits128#(Clock sClkIn, Reset sRst, Clock dClkIn, Reset dRst)(SyncBitIfc#(Bit#(128)));
   SyncBitIfc#(Bit#(128)) sbits <- mkSyncBits(0, sClkIn, sRst, dClkIn, dRst);
   method read = sbits.read;
   method send = sbits.send;
endmodule: mkSyncBits128


Separate implementation for 32-bit and 64-bit divider and sqrt pipes

// Copyright (c) 2013-2019 Bluespec, Inc. All Rights Reserved
package FPU;

import FIFOF :: *;
import RegFile :: *;
import GetPut :: *;
import ClientServer :: *;

import FloatingPoint :: *;
import Divide :: *;
import SquareRoot ::*;
import ISA_Decls :: *;

// ================================================================
// Type definitions
typedef FloatingPoint#(11,52) FDouble;
typedef FloatingPoint#(8,23)  FSingle;

typedef union tagged {
   FDouble D;
   FSingle S;
   } FloatU deriving(Bits,Eq);

typedef Tuple5#( FloatU,FloatU,FloatU,RoundMode,FpuOp) Fpu_Req;
typedef Tuple2#( FloatU, FloatingPoint::Exception )       Fpu_Rsp;

`ifdef ISA_D
typedef Tuple2#( FDouble, FloatingPoint::Exception )      FpuR;
`else
typedef Tuple2#( FSingle, FloatingPoint::Exception )      FpuR;
`endif

interface FPU_IFC;
   interface Server #( Fpu_Req, Fpu_Rsp ) server_core;

   // ---- Reset
   interface Server #(Token, Token) server_reset;
endinterface

(* synthesize *)
module mkFPU ( FPU_IFC );
`ifdef INCLUDE_FDIV
`ifdef ISA_D
   Server# (Tuple2# (UInt# (114), UInt# (57))
          , Tuple2# (UInt# (57) , UInt# (57))) _div <- mkNonPipelinedDivider(2);
   Server# (Tuple3#(FDouble, FDouble, RoundMode)
          , FpuR) fpu_div  <- mkFloatingPointDivider(_div);
`else
   Server# (Tuple2# (UInt #(56), UInt #(28))
          , Tuple2# (UInt #(28), UInt #(28))) _div <- mkNonPipelinedDivider(2);
   Server# (Tuple3# (FSingle, FSingle, RoundMode)
          , FpuR) fpu_div <- mkFloatingPointDivider(_div);
`endif
`endif

`ifdef INCLUDE_FSQRT
`ifdef ISA_D
   Server# (UInt# (116)
          , Tuple2# (UInt# (116), Bool)) _sqrt <- mkNonPipelinedSquareRooter(2);
   Server# (Tuple2# (FDouble, RoundMode)
          , FpuR) fpu_sqr <- mkFloatingPointSquareRooter(_sqrt);
`else
   Server# (UInt# (60)
          , Tuple2# (UInt# (60), Bool)) _sqrt <- mkNonPipelinedSquareRooter(2);
   Server# (Tuple2# (FSingle, RoundMode)
          , FpuR) fpu_sqr <- mkFloatingPointSquareRooter(_sqrt);
`endif
`endif

`ifdef ISA_D
   Server# (Tuple4# (Maybe# (FDouble), FDouble, FDouble, RoundMode)
          , FpuR ) fpu_madd <- mkFloatingPointFusedMultiplyAccumulate;
`else
   Server# (Tuple4# (Maybe# (FSingle), FSingle, FSingle, RoundMode)
          , FpuR ) fpu_madd <- mkFloatingPointFusedMultiplyAccumulate;
`endif

   FIFOF #(Token)          resetReqsF           <- mkFIFOF;
   FIFOF #(Token)          resetRspsF           <- mkFIFOF;

   FIFOF#( Fpu_Req )  iFifo        <- mkFIFOF; // TODO: bypass fifos?
   FIFOF#( Fpu_Rsp )  oFifo        <- mkFIFOF; // TODO: bypass fifos?
   FIFOF#( RoundMode ) rmdFifo     <- mkFIFOF; // TODO: bypass fifos?
`ifdef ISA_D
   FIFOF#( Bool )     isDoubleFifo <- mkFIFOF; // TODO: bypass fifos?
`endif
   FIFOF#( Bool )     isNegateFifo <- mkFIFOF; // TODO: bypass fifos?
   Reg#(FpuR)         resWire      <- mkWire;

   function FDouble toDouble( FloatU x, RoundMode rmode );
      if (x matches tagged S .val) begin
         let r = convert( val , rmode , True );
         return tpl_1(r);
      end
      else if (x matches tagged D .val)
         return val;
      else
         return unpack(0);
   endfunction

   let x    = iFifo.first();
   let op1  = tpl_1(x);
   let op2  = tpl_2(x);
   let op3  = tpl_3(x);
   let rmd  = tpl_4(x);
   let iop  = tpl_5(x);

`ifdef ISA_D
   FDouble opd1 = toDouble(op1, rmd);
   FDouble opd2 = toDouble(op2, rmd);
   FDouble opd3 = toDouble(op3, rmd);
`else
   FSingle opd1 = op1.S;
   FSingle opd2 = op2.S;
   FSingle opd3 = op3.S;
`endif

   rule start_op;
      iFifo.deq();
`ifdef ISA_D
      if (op1 matches tagged D .val) isDoubleFifo.enq(True);
      else                           isDoubleFifo.enq(False);
`endif

      if      (iop == FPNMAdd)    isNegateFifo.enq(True);
      else if (iop == FPNMSub)    isNegateFifo.enq(True);
      else                        isNegateFifo.enq(False);

      rmdFifo.enq(rmd);

      case ( iop )
         FPAdd:   fpu_madd.request.put (tuple4(Valid(opd1), opd2,         one(False), rmd) );
         FPSub:   fpu_madd.request.put (tuple4(Valid(opd1), negate(opd2), one(False), rmd) );
         FPMul:   fpu_madd.request.put (tuple4(Invalid,     opd1,         opd2,       rmd) );
`ifdef INCLUDE_FDIV
         FPDiv:   fpu_div.request.put (tuple3 (opd1, opd2, rmd) );
`endif
`ifdef INCLUDE_FSQRT
         FPSqrt:  fpu_sqr.request.put (tuple2(opd1, rmd) );
`endif
         FPMAdd:  fpu_madd.request.put(  tuple4(Valid(opd3),         opd1, opd2, rmd) );
         FPMSub:  fpu_madd.request.put(  tuple4(Valid(negate(opd3)), opd1, opd2, rmd) );
         FPNMAdd: fpu_madd.request.put(  tuple4(Valid(opd3),         opd1, opd2, rmd) );
         FPNMSub: fpu_madd.request.put(  tuple4(Valid(negate(opd3)), opd1, opd2, rmd) );
      endcase

   endrule

   // rule generator for handling responses from multi-cycle pipes
   function Rules fn_genMultCycResRules (Server #(req, FpuR) pipe);
      return (rules
         rule getResFromPipe;
            let res <- pipe.response.get ();
            resWire <= res;
         endrule
      endrules);
   endfunction

   let rl_resRules = emptyRules;
   rl_resRules = rJoin (rl_resRules, fn_genMultCycResRules (fpu_madd));
`ifdef INCLUDE_FDIV
   rl_resRules = rJoinMutuallyExclusive (rl_resRules, fn_genMultCycResRules (fpu_div));
`endif
`ifdef INCLUDE_FSQRT
   rl_resRules = rJoinMutuallyExclusive (rl_resRules, fn_genMultCycResRules (fpu_sqr));
`endif
   addRules (rl_resRules);

   rule passResult;
`ifdef ISA_D
      isDoubleFifo.deq();
      let is64Bits = isDoubleFifo.first();
`endif

      isNegateFifo.deq();
      let negateResult = isNegateFifo.first();

      rmdFifo.deq();
      let rmode = rmdFifo.first();

`ifdef ISA_D
      if (is64Bits) begin
         FDouble   v  = tpl_1(resWire);
         FloatingPoint::Exception ex = tpl_2(resWire);
         if (negateResult)
            v = negate( v );
         FloatU res = tagged D v;
         oFifo.enq( tuple2( res, ex ) );
      end
      else begin
         Tuple2#(FSingle,FloatingPoint::Exception) sres = convert( tpl_1(resWire) , rmode , True );
         FSingle   v  = tpl_1(sres);
         FloatingPoint::Exception ex = tpl_2(resWire) | tpl_2(sres);
         if (negateResult)
            v = negate( v );
         FloatU res = tagged S v;
         oFifo.enq( tuple2( res, ex ) );
      end
`else
      FSingle   v  = tpl_1(resWire);
      FloatingPoint::Exception ex = tpl_2(resWire);
      if (negateResult)
         v = negate( v );
      FloatU res = tagged S v;
      oFifo.enq( tuple2( res, ex ) );
`endif
   endrule

   rule rl_reset;
      resetReqsF.deq;
      iFifo.clear;
      oFifo.clear;
      rmdFifo.clear;
`ifdef ISA_D
      isDoubleFifo.clear;
`endif
      isNegateFifo.clear;
      resetRspsF.enq (?);
   endrule

   // =============================================================
   // INTERFACE
   // ---- Reset
   interface server_reset = toGPServer (resetReqsF, resetRspsF);
   interface server_core = toGPServer ( iFifo, oFifo );
endmodule
endpackage

// Copyright (c) 2013-2019 Bluespec, Inc. All Rights Reserved
package FPU;

import FIFOF :: *;
import RegFile :: *;
import GetPut :: *;
import ClientServer :: *;

import FloatingPoint :: *;
import Divide :: *;
import SquareRoot ::*;
import ISA_Decls :: *;

// ================================================================
// Type definitions
typedef FloatingPoint#(11,52) FDouble;
typedef FloatingPoint#(8,23)  FSingle;

typedef union tagged {
   FDouble D;
   FSingle S;
   } FloatU deriving(Bits,Eq);

typedef Tuple5#( FloatU,FloatU,FloatU,RoundMode,FpuOp) Fpu_Req;
typedef Tuple2#( FloatU, FloatingPoint::Exception )       Fpu_Rsp;

`ifdef ISA_D
typedef Tuple2#( FDouble, FloatingPoint::Exception )      FpuR;
`else
typedef Tuple2#( FSingle, FloatingPoint::Exception )      FpuR;
`endif

interface FPU_IFC;
   interface Server #( Fpu_Req, Fpu_Rsp ) server_core;

   // ---- Reset
   interface Server #(Token, Token) server_reset;
endinterface

(* synthesize *)
module mkFPU ( FPU_IFC );
`ifdef INCLUDE_FDIV
   Server#(Tuple2#(UInt#(114),UInt#(57)),Tuple2#(UInt#(57),UInt#(57))) _div <- mkNonPipelinedDivider(2);
   Server#( Tuple3#(FDouble,FDouble,RoundMode),         FpuR ) fpu_div64  <- mkFloatingPointDivider(_div);
`endif

`ifdef INCLUDE_FSQRT
   Server#(UInt#(116),Tuple2#(UInt#(116),Bool)) _sqrt                       <- mkNonPipelinedSquareRooter(2);
   Server#( Tuple2#(FDouble,RoundMode),                 FpuR ) fpu_sqr64  <- mkFloatingPointSquareRooter(_sqrt);
`endif

`ifdef ISA_D
   Server#( Tuple4#(Maybe#(FDouble),FDouble,FDouble,RoundMode), FpuR ) fpu_madd   <- mkFloatingPointFusedMultiplyAccumulate;
`else
   Server#( Tuple4#(Maybe#(FSingle),FSingle,FSingle,RoundMode), FpuR ) fpu_madd   <- mkFloatingPointFusedMultiplyAccumulate;
`endif

   FIFOF #(Token)          resetReqsF           <- mkFIFOF;
   FIFOF #(Token)          resetRspsF           <- mkFIFOF;

   FIFOF#( Fpu_Req )  iFifo        <- mkFIFOF; // TODO: bypass fifos?
   FIFOF#( Fpu_Rsp )  oFifo        <- mkFIFOF; // TODO: bypass fifos?
   FIFOF#( RoundMode ) rmdFifo     <- mkFIFOF; // TODO: bypass fifos?
`ifdef ISA_D
   FIFOF#( Bool )     isDoubleFifo <- mkFIFOF; // TODO: bypass fifos?
`endif
   FIFOF#( Bool )     isNegateFifo <- mkFIFOF; // TODO: bypass fifos?
   Reg#(FpuR)         resWire      <- mkWire;

   function FDouble toDouble( FloatU x, RoundMode rmode );
      if (x matches tagged S .val) begin
         let r = convert( val , rmode , True );
         return tpl_1(r);
      end
      else if (x matches tagged D .val)
         return val;
      else
         return unpack(0);
   endfunction

   let x    = iFifo.first();
   let op1  = tpl_1(x);
   let op2  = tpl_2(x);
   let op3  = tpl_3(x);
   let rmd  = tpl_4(x);
   let iop  = tpl_5(x);

`ifdef ISA_D
   FDouble opd1 = toDouble(op1, rmd);
   FDouble opd2 = toDouble(op2, rmd);
   FDouble opd3 = toDouble(op3, rmd);
`else
   FSingle opd1 = op1.S;
   FSingle opd2 = op2.S;
   FSingle opd3 = op3.S;
`endif

   rule start_op;
      iFifo.deq();
`ifdef ISA_D
      if (op1 matches tagged D .val) isDoubleFifo.enq(True);
      else                           isDoubleFifo.enq(False);
`endif

      if      (iop == FPNMAdd)    isNegateFifo.enq(True);
      else if (iop == FPNMSub)    isNegateFifo.enq(True);
      else                        isNegateFifo.enq(False);

      rmdFifo.enq(rmd);

      case ( iop )
         FPAdd:   fpu_madd.request.put(  tuple4(Valid(opd1), opd2,         one(False), rmd) );
         FPSub:   fpu_madd.request.put(  tuple4(Valid(opd1), negate(opd2), one(False), rmd) );
         FPMul:   fpu_madd.request.put(  tuple4(Invalid,     opd1,         opd2,       rmd) );
`ifdef INCLUDE_FDIV
         FPDiv:   fpu_div64.request.put( tuple3(opd1, opd2,         rmd) );
`endif
`ifdef INCLUDE_FSQRT
         FPSqrt:  fpu_sqr64.request.put( tuple2(opd1,               rmd) );
`endif
         FPMAdd:  fpu_madd.request.put(  tuple4(Valid(opd3),         opd1, opd2, rmd) );
         FPMSub:  fpu_madd.request.put(  tuple4(Valid(negate(opd3)), opd1, opd2, rmd) );
         FPNMAdd: fpu_madd.request.put(  tuple4(Valid(opd3),         opd1, opd2, rmd) );
         FPNMSub: fpu_madd.request.put(  tuple4(Valid(negate(opd3)), opd1, opd2, rmd) );
      endcase

   endrule

   // rule generator for handling responses from multi-cycle pipes
   function Rules fn_genMultCycResRules (Server #(req, FpuR) pipe);
      return (rules
         rule getResFromPipe;
            let res <- pipe.response.get ();
            resWire <= res;
         endrule
      endrules);
   endfunction

   let rl_resRules = emptyRules;
   rl_resRules = rJoin (rl_resRules, fn_genMultCycResRules (fpu_madd));
`ifdef INCLUDE_FDIV
   rl_resRules = rJoinMutuallyExclusive (rl_resRules, fn_genMultCycResRules (fpu_div64));
`endif
`ifdef INCLUDE_FSQRT
   rl_resRules = rJoinMutuallyExclusive (rl_resRules, fn_genMultCycResRules (fpu_sqr64));
`endif
   addRules (rl_resRules);

   rule passResult;
`ifdef ISA_D
      isDoubleFifo.deq();
      let is64Bits = isDoubleFifo.first();
`endif

      isNegateFifo.deq();
      let negateResult = isNegateFifo.first();

      rmdFifo.deq();
      let rmode = rmdFifo.first();

`ifdef ISA_D
      if (is64Bits) begin
         FDouble   v  = tpl_1(resWire);
         FloatingPoint::Exception ex = tpl_2(resWire);
         if (negateResult)
            v = negate( v );
         FloatU res = tagged D v;
         oFifo.enq( tuple2( res, ex ) );
      end
      else begin
         Tuple2#(FSingle,FloatingPoint::Exception) sres = convert( tpl_1(resWire) , rmode , True );
         FSingle   v  = tpl_1(sres);
         FloatingPoint::Exception ex = tpl_2(resWire) | tpl_2(sres);
         if (negateResult)
            v = negate( v );
         FloatU res = tagged S v;
         oFifo.enq( tuple2( res, ex ) );
      end
`else
      FSingle   v  = tpl_1(resWire);
      FloatingPoint::Exception ex = tpl_2(resWire);
      if (negateResult)
         v = negate( v );
      FloatU res = tagged S v;
      oFifo.enq( tuple2( res, ex ) );
`endif
   endrule

   rule rl_reset;
      resetReqsF.deq;
      iFifo.clear;
      oFifo.clear;
      rmdFifo.clear;
`ifdef ISA_D
      isDoubleFifo.clear;
`endif
      isNegateFifo.clear;
      resetRspsF.enq (?);
   endrule

   // =============================================================
   // INTERFACE
   // ---- Reset
   interface server_reset = toGPServer (resetReqsF, resetRspsF);
   interface server_core = toGPServer ( iFifo, oFifo );
endmodule
endpackage


prioQ: reduce enq latency by half, optimized away unnecessary internal states

import Vector::*;
import FIFO::*;
import SpecialFIFOs::*;
import GetPut::*;
import DefaultValue::*;

import PriorityEncoder::*;

typedef 32 SIZE;

typedef struct {
    valueType v;
    priorityType p;
} Node#(type valueType, type priorityType) deriving(Bits, Eq);

instance DefaultValue#(Node#(Bit#(size_t), Bit#(size_t)));
    defaultValue = Node {
        v : 0,
        p : maxBound
    };
endinstance

interface MinPriorityQueue#(type valueType, type priorityType);
    interface Put#(Node#(valueType, priorityType)) insert_req;
    interface Get#(void) insert_res;
    method ActionValue#(Node#(valueType, priorityType)) first();
    method Action deq();
    method Action clear();
    method Action displayQueue();
endinterface

function Bit#(1) compare (Node#(Bit#(size_t), Bit#(size_t)) x,
                          Node#(Bit#(size_t), Bit#(size_t)) y);
    if (x.p > y.p)
        return 1;
    else
        return 0;
//    else if (x.p == y.p)
//        return 0;
//    else
//        return -1;
endfunction

module mkMinPriorityQueue (MinPriorityQueue#(Bit#(size_t), Bit#(size_t)));
    FIFO#(void) insert_res_fifo <- mkBypassFIFO;

    PE#(SIZE) priority_encoder <- mkPEncoder;

    Vector#(SIZE, Reg#(Node#(Bit#(size_t), Bit#(size_t))))
                   sorted_list <- replicateM(mkReg(defaultValue));
    Reg#(Node#(Bit#(size_t), Bit#(size_t))) node_to_insert <- mkReg(defaultValue);
    Reg#(Bit#(TLog#(SIZE))) location_to_insert <- mkReg(0);
    Reg#(Bit#(TLog#(SIZE))) curr_size <- mkReg(0);

    Reg#(Bit#(1)) insert_in_progress <- mkReg(0);

    Vector#(SIZE, FIFO#(void))
        insert_in_correct_location_fifo <- replicateM(mkBypassFIFO);

    Reg#(Bit#(64)) count <- mkReg(0);
    rule counter;
        count <= count + 1;
    endrule

    rule get_correct_location_rule (insert_in_progress == 1);
        let x <- toGet(priority_encoder.bin).get;
        $display("get from pe %h", x);
        case (x) matches
            tagged Valid .index : insert_in_correct_location_fifo[index].enq(?);
            tagged Invalid: $display("invalid output %h", x);
        endcase
    endrule

    for (Integer i = 0; i < valueof(SIZE); i = i + 1)
    begin
        rule insert_in_correct_location_rule (insert_in_progress == 1);
            let y <- toGet(insert_in_correct_location_fifo[i]).get;
            for (Integer j = i; j < valueof(SIZE)-1; j = j + 1)
                sorted_list[j + 1] <= sorted_list[j];
            sorted_list[i] <= node_to_insert;
            insert_in_progress <= 0;
            curr_size <= curr_size + 1;
            insert_res_fifo.enq(?);
        endrule
    end

    method ActionValue#(Node#(Bit#(size_t), Bit#(size_t))) first()
                                               if (curr_size > 0);
        return sorted_list[0];
    endmethod

    method Action deq() if (insert_in_progress == 0 && curr_size > 0);
        for (Integer i = 0; i < valueof(SIZE)-1; i = i + 1)
            sorted_list[i] <= sorted_list[i + 1];
        sorted_list[valueof(SIZE)-1] <= defaultValue;
        curr_size <= curr_size - 1;
    endmethod

    method Action clear() if (insert_in_progress == 0 && curr_size > 0);
        writeVReg(sorted_list, defaultValue);
        curr_size <= 0;
    endmethod

    method Action displayQueue();
        for (Integer i = 0; i < valueof(SIZE); i = i + 1)
            $display("(%d %d)", sorted_list[i].v, sorted_list[i].p);
    endmethod

    interface Put insert_req;
        method Action put (Node#(Bit#(size_t), Bit#(size_t)) v) if (insert_in_progress == 0);
            node_to_insert <= v;
            insert_in_progress <= 1;
            $display("sorted_list %h", readVReg(sorted_list));
            let r = map(uncurry(compare), zip(readVReg(sorted_list), replicate(v)));
            $display("put %h", r);
            priority_encoder.oht.put(pack(r));
        endmethod
    endinterface
    interface Get insert_res = toGet(insert_res_fifo);
endmodule

import Vector::*;
import FIFO::*;
import SpecialFIFOs::*;
import GetPut::*;
import DefaultValue::*;

import PriorityEncoder::*;

typedef 32 SIZE;

typedef struct {
    valueType v;
    priorityType p;
} Node#(type valueType, type priorityType) deriving(Bits, Eq);

instance DefaultValue#(Node#(Bit#(size_t), Bit#(size_t)));
    defaultValue = Node {
        v : 0,
        p : maxBound
    };
endinstance

interface MinPriorityQueue#(type valueType, type priorityType);
    interface Put#(Node#(valueType, priorityType)) insert_req;
    interface Get#(void) insert_res;
    method ActionValue#(Node#(valueType, priorityType)) first();
    method Action deq();
    method Action clear();
    method Action displayQueue();
endinterface

function Int#(2) compare (Node#(Bit#(size_t), Bit#(size_t)) x,
                          Node#(Bit#(size_t), Bit#(size_t)) y);
    if (x.p > y.p)
        return 1;
    else if (x.p == y.p)
        return 0;
    else
        return -1;
endfunction

module mkMinPriorityQueue (MinPriorityQueue#(Bit#(size_t), Bit#(size_t)));
    FIFO#(Node#(Bit#(size_t), Bit#(size_t)))
        insert_req_fifo <- mkSizedFIFO(valueof(SIZE));
    FIFO#(void) insert_res_fifo <- mkBypassFIFO;

    PE#(SIZE) priority_encoder <- mkPEncoder;

    Vector#(SIZE, Reg#(Node#(Bit#(size_t), Bit#(size_t))))
                   sorted_list <- replicateM(mkReg(defaultValue));
    Vector#(SIZE, Reg#(Bit#(1))) b_vector <- replicateM(mkReg(0));
    Reg#(Node#(Bit#(size_t), Bit#(size_t))) node_to_insert <- mkReg(defaultValue);
    Reg#(Bit#(TLog#(SIZE))) location_to_insert <- mkReg(0);
    Reg#(Bit#(TLog#(SIZE))) curr_size <- mkReg(0);

    Reg#(Bit#(1)) insert_in_progress <- mkReg(0);

    Vector#(SIZE, FIFO#(void)) create_bit_vector_fifo <- replicateM(mkFIFO);
    FIFO#(void) find_correct_location_fifo <- mkPipelineFIFO;
    Vector#(SIZE, FIFO#(void))
        insert_in_correct_location_fifo <- replicateM(mkBypassFIFO);

    Reg#(Bit#(64)) count <- mkReg(0);
    rule counter;
        count <= count + 1;
    endrule

    for (Integer i = 0; i < valueof(SIZE); i = i + 1)
    begin
        rule create_bit_vector_rule (insert_in_progress == 1);
            let x <- toGet(create_bit_vector_fifo[i]).get;
            if (i == 0)
                find_correct_location_fifo.enq(?);
            if (compare(sorted_list[i], node_to_insert) > 0)
                b_vector[i] <= 1;
            else
                b_vector[i] <= 0;
        endrule
    end

    rule find_correct_location_rule (insert_in_progress == 1);
        let x <- toGet(find_correct_location_fifo).get;
        priority_encoder.oht.put(pack(readVReg(b_vector)));
    endrule

    rule get_correct_location_rule (insert_in_progress == 1);
        let x <- toGet(priority_encoder.bin).get;
        case (x) matches
            tagged Valid .index : insert_in_correct_location_fifo[index].enq(?);
        endcase
    endrule

    for (Integer i = 0; i < valueof(SIZE); i = i + 1)
    begin
        rule insert_in_correct_location_rule (insert_in_progress == 1);
            let y <- toGet(insert_in_correct_location_fifo[i]).get;
            for (Integer j = i; j < valueof(SIZE)-1; j = j + 1)
                sorted_list[j + 1] <= sorted_list[j];
            sorted_list[i] <= node_to_insert;
            insert_in_progress <= 0;
            curr_size <= curr_size + 1;
            insert_res_fifo.enq(?);
        endrule
    end

    rule handle_insert_req (insert_in_progress == 0);
        let req <- toGet(insert_req_fifo).get;
        node_to_insert <= req;
        insert_in_progress <= 1;
        for (Integer i = 0; i < valueof(SIZE); i = i + 1)
            create_bit_vector_fifo[i].enq(?);
    endrule

    method ActionValue#(Node#(Bit#(size_t), Bit#(size_t))) first()
                                               if (curr_size > 0);
        return sorted_list[0];
    endmethod

    method Action deq() if (insert_in_progress == 0 && curr_size > 0);
        for (Integer i = 0; i < valueof(SIZE)-1; i = i + 1)
            sorted_list[i] <= sorted_list[i + 1];
        sorted_list[valueof(SIZE)-1] <= defaultValue;
        curr_size <= curr_size - 1;
    endmethod

    method Action clear() if (insert_in_progress == 0 && curr_size > 0);
        writeVReg(sorted_list, defaultValue);
        curr_size <= 0;
    endmethod

    method Action displayQueue();
        for (Integer i = 0; i < valueof(SIZE); i = i + 1)
            $display("(%d %d)", sorted_list[i].v, sorted_list[i].p);
    endmethod

    interface Put insert_req = toPut(insert_req_fifo);
    interface Get insert_res = toGet(insert_res_fifo);
endmodule


fixed clocks, revised names, AxiIntcBvi

fixed clocks, revised names, AxiIntcBvi

/*
   ../scripts/importbvi.py
   -P
   AxiIntc
   -I
   AxiIntc
   -c
   s_axi_aclk
   -r
   s_axi_aresetn
   -o
   AxiIntcBvi.bsv
   ../../out/vc709/axi_intc_0/axi_intc_0_stub.v
*/

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

(* always_ready, always_enabled *)
interface AxiintcbviS_axi;
    method Action      araddr(Bit#(9) v);
    method Bit#(1)     arready();
    method Action      arvalid(Bit#(1) v);
    method Action      awaddr(Bit#(9) v);
    method Bit#(1)     awready();
    method Action      awvalid(Bit#(1) v);
    method Action      bready(Bit#(1) v);
    method Bit#(2)     bresp();
    method Bit#(1)     bvalid();
    method Bit#(32)     rdata();
    method Action      rready(Bit#(1) v);
    method Bit#(2)     rresp();
    method Bit#(1)     rvalid();
    method Action      wdata(Bit#(32) v);
    method Bit#(1)     wready();
    method Action      wstrb(Bit#(4) v);
    method Action      wvalid(Bit#(1) v);
endinterface
(* always_ready, always_enabled *)
interface AxiIntc;
    method Action      intr(Bit#(2) v);
    method Bit#(1)     irq();
    interface AxiintcbviS_axi s_axi;
endinterface
import "BVI" axi_intc_0 =
module mkAxiIntcBvi#(Clock s_axi_aclk, Reset s_axi_aresetn)(AxiIntc);
    default_clock clk();
    default_reset rst();
        input_clock s_axi_aclk(s_axi_aclk) = s_axi_aclk;
        input_reset s_axi_aresetn(s_axi_aresetn) = s_axi_aresetn;
    method intr(intr) enable((*inhigh*) EN_intr) clocked_by (s_axi_aclk) reset_by (s_axi_aresetn);
    method irq irq() clocked_by (s_axi_aclk) reset_by (s_axi_aresetn);
    interface AxiintcbviS_axi s_axi;
        method araddr(s_axi_araddr) clocked_by (s_axi_aclk) reset_by (s_axi_aresetn) enable((*inhigh*) EN_s_axi_araddr);
        method s_axi_arready arready() clocked_by (s_axi_aclk) reset_by (s_axi_aresetn);
        method arvalid(s_axi_arvalid) clocked_by (s_axi_aclk) reset_by (s_axi_aresetn) enable((*inhigh*) EN_s_axi_arvalid);
        method awaddr(s_axi_awaddr) clocked_by (s_axi_aclk) reset_by (s_axi_aresetn) enable((*inhigh*) EN_s_axi_awaddr);
        method s_axi_awready awready() clocked_by (s_axi_aclk) reset_by (s_axi_aresetn);
        method awvalid(s_axi_awvalid) clocked_by (s_axi_aclk) reset_by (s_axi_aresetn) enable((*inhigh*) EN_s_axi_awvalid);
        method bready(s_axi_bready) clocked_by (s_axi_aclk) reset_by (s_axi_aresetn) enable((*inhigh*) EN_s_axi_bready);
        method s_axi_bresp bresp() clocked_by (s_axi_aclk) reset_by (s_axi_aresetn);
        method s_axi_bvalid bvalid() clocked_by (s_axi_aclk) reset_by (s_axi_aresetn);
        method s_axi_rdata rdata() clocked_by (s_axi_aclk) reset_by (s_axi_aresetn);
        method rready(s_axi_rready) clocked_by (s_axi_aclk) reset_by (s_axi_aresetn) enable((*inhigh*) EN_s_axi_rready);
        method s_axi_rresp rresp() clocked_by (s_axi_aclk) reset_by (s_axi_aresetn);
        method s_axi_rvalid rvalid() clocked_by (s_axi_aclk) reset_by (s_axi_aresetn);
        method wdata(s_axi_wdata) clocked_by (s_axi_aclk) reset_by (s_axi_aresetn) enable((*inhigh*) EN_s_axi_wdata);
        method s_axi_wready wready() clocked_by (s_axi_aclk) reset_by (s_axi_aresetn);
        method wstrb(s_axi_wstrb) clocked_by (s_axi_aclk) reset_by (s_axi_aresetn) enable((*inhigh*) EN_s_axi_wstrb);
        method wvalid(s_axi_wvalid) clocked_by (s_axi_aclk) reset_by (s_axi_aresetn) enable((*inhigh*) EN_s_axi_wvalid);
    endinterface
    schedule (intr, irq, s_axi.araddr, s_axi.arready, s_axi.arvalid, s_axi.awaddr, s_axi.awready, s_axi.awvalid, s_axi.bready, s_axi.bresp, s_axi.bvalid, s_axi.rdata, s_axi.rready, s_axi.rresp, s_axi.rvalid, s_axi.wdata, s_axi.wready, s_axi.wstrb, s_axi.wvalid) CF (intr, irq, s_axi.araddr, s_axi.arready, s_axi.arvalid, s_axi.awaddr, s_axi.awready, s_axi.awvalid, s_axi.bready, s_axi.bresp, s_axi.bvalid, s_axi.rdata, s_axi.rready, s_axi.rresp, s_axi.rvalid, s_axi.wdata, s_axi.wready, s_axi.wstrb, s_axi.wvalid);
endmodule

instance ToAxi4SlaveBits#(Axi4SlaveLiteBits#(9,32), AxiintcbviS_axi);
   function Axi4SlaveLiteBits#(9,32) toAxi4SlaveBits(AxiintcbviS_axi s);
      return (interface Axi4SlaveLiteBits#(9,32);
	 method araddr = s.araddr;
	 method arready = s.arready;
	 method arvalid = s.arvalid;
	 method awaddr = s.awaddr;
	 method awready = s.awready;
	 method awvalid = s.awvalid;
	 method bready = s.bready;
	 method bresp = s.bresp;
	 method bvalid = s.bvalid;
	 method rdata = s.rdata;
	 method rready = s.rready;
	 method rresp = s.rresp;
	 method rvalid = s.rvalid;
	 method wdata = s.wdata;
	 method wready = s.wready;
	 method Action      wvalid(Bit#(1) v);
	    s.wvalid(v);
	    s.wstrb(pack(replicate(v)));
	 endmethod
	 endinterface);
   endfunction
endinstance

/*
   ../scripts/importbvi.py
   -P
   AxiIntc
   -I
   AxiIntc
   -c
   s_axi_aclk
   -r
   s_axi_aresetn
   -o
   AxiIntcBvi.bsv
   ../../out/vc709/axi_intc_0/axi_intc_0_stub.v
*/

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

(* always_ready, always_enabled *)
interface AxiintcS_axi;
    method Action      araddr(Bit#(9) v);
    method Bit#(1)     arready();
    method Action      arvalid(Bit#(1) v);
    method Action      awaddr(Bit#(9) v);
    method Bit#(1)     awready();
    method Action      awvalid(Bit#(1) v);
    method Action      bready(Bit#(1) v);
    method Bit#(2)     bresp();
    method Bit#(1)     bvalid();
    method Bit#(32)     rdata();
    method Action      rready(Bit#(1) v);
    method Bit#(2)     rresp();
    method Bit#(1)     rvalid();
    method Action      wdata(Bit#(32) v);
    method Bit#(1)     wready();
    method Action      wstrb(Bit#(4) v);
    method Action      wvalid(Bit#(1) v);
endinterface
(* always_ready, always_enabled *)
interface AxiIntc;
    method Action      intr(Bit#(2) v);
    method Bit#(1)     irq();
    interface AxiintcS_axi     s_axi;
endinterface
import "BVI" axi_intc_0(s_axi_aclk, =
module mkAxiIntc#(Clock s_axi_aclk, Reset s_axi_aclk_reset, Reset s_axi_aresetn)(AxiIntc);
    default_clock clk();
    default_reset rst();
        input_clock s_axi_aclk(s_axi_aclk) = s_axi_aclk;
        input_reset s_axi_aclk_reset() = s_axi_aclk_reset; /* from clock*/
        input_reset s_axi_aresetn(s_axi_aresetn) = s_axi_aresetn;
    method intr(intr) enable((*inhigh*) EN_intr);
    method irq irq();
    interface AxiintcS_axi     s_axi;
        method araddr(s_axi_araddr) clocked_by (s_axi_aclk) reset_by (s_axi_aclk_reset) enable((*inhigh*) EN_s_axi_araddr);
        method s_axi_arready arready() clocked_by (s_axi_aclk) reset_by (s_axi_aclk_reset);
        method arvalid(s_axi_arvalid) clocked_by (s_axi_aclk) reset_by (s_axi_aclk_reset) enable((*inhigh*) EN_s_axi_arvalid);
        method awaddr(s_axi_awaddr) clocked_by (s_axi_aclk) reset_by (s_axi_aclk_reset) enable((*inhigh*) EN_s_axi_awaddr);
        method s_axi_awready awready() clocked_by (s_axi_aclk) reset_by (s_axi_aclk_reset);
        method awvalid(s_axi_awvalid) clocked_by (s_axi_aclk) reset_by (s_axi_aclk_reset) enable((*inhigh*) EN_s_axi_awvalid);
        method bready(s_axi_bready) clocked_by (s_axi_aclk) reset_by (s_axi_aclk_reset) enable((*inhigh*) EN_s_axi_bready);
        method s_axi_bresp bresp() clocked_by (s_axi_aclk) reset_by (s_axi_aclk_reset);
        method s_axi_bvalid bvalid() clocked_by (s_axi_aclk) reset_by (s_axi_aclk_reset);
        method s_axi_rdata rdata() clocked_by (s_axi_aclk) reset_by (s_axi_aclk_reset);
        method rready(s_axi_rready) clocked_by (s_axi_aclk) reset_by (s_axi_aclk_reset) enable((*inhigh*) EN_s_axi_rready);
        method s_axi_rresp rresp() clocked_by (s_axi_aclk) reset_by (s_axi_aclk_reset);
        method s_axi_rvalid rvalid() clocked_by (s_axi_aclk) reset_by (s_axi_aclk_reset);
        method wdata(s_axi_wdata) clocked_by (s_axi_aclk) reset_by (s_axi_aclk_reset) enable((*inhigh*) EN_s_axi_wdata);
        method s_axi_wready wready() clocked_by (s_axi_aclk) reset_by (s_axi_aclk_reset);
        method wstrb(s_axi_wstrb) clocked_by (s_axi_aclk) reset_by (s_axi_aclk_reset) enable((*inhigh*) EN_s_axi_wstrb);
        method wvalid(s_axi_wvalid) clocked_by (s_axi_aclk) reset_by (s_axi_aclk_reset) enable((*inhigh*) EN_s_axi_wvalid);
    endinterface
    schedule (intr, irq, s_axi.araddr, s_axi.arready, s_axi.arvalid, s_axi.awaddr, s_axi.awready, s_axi.awvalid, s_axi.bready, s_axi.bresp, s_axi.bvalid, s_axi.rdata, s_axi.rready, s_axi.rresp, s_axi.rvalid, s_axi.wdata, s_axi.wready, s_axi.wstrb, s_axi.wvalid) CF (intr, irq, s_axi.araddr, s_axi.arready, s_axi.arvalid, s_axi.awaddr, s_axi.awready, s_axi.awvalid, s_axi.bready, s_axi.bresp, s_axi.bvalid, s_axi.rdata, s_axi.rready, s_axi.rresp, s_axi.rvalid, s_axi.wdata, s_axi.wready, s_axi.wstrb, s_axi.wvalid);
endmodule


remove bogus s_axi_aresetn added by importbvi

/*
   /home/jamey/connectal.clean/generated/scripts/importbvi.py
   -P
   AxiIic
   -I
   AxiIic
   -c
   s_axi_aclk
   -r
   s_axi_aresetn
   -n
   iic2intc_irpt
   -o
   AxiIic.bsv
   cores/vc709/axi_iic_0/axi_iic_0_stub.v
*/

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

(* always_ready, always_enabled *)
interface AxiiicS_axi;
    method Action      araddr(Bit#(9) v);
    method Bit#(1)     arready();
    method Action      arvalid(Bit#(1) v);
    method Action      awaddr(Bit#(9) v);
    method Bit#(1)     awready();
    method Action      awvalid(Bit#(1) v);
    method Action      bready(Bit#(1) v);
    method Bit#(2)     bresp();
    method Bit#(1)     bvalid();
    method Bit#(32)     rdata();
    method Action      rready(Bit#(1) v);
    method Bit#(2)     rresp();
    method Bit#(1)     rvalid();
    method Action      wdata(Bit#(32) v);
    method Bit#(1)     wready();
    method Action      wstrb(Bit#(4) v);
    method Action      wvalid(Bit#(1) v);
endinterface
(* always_ready, always_enabled *)
interface AxiiicScl;
    method Action      i(Bit#(1) v);
    method Bit#(1)     o();
    method Bit#(1)     t();
endinterface
(* always_ready, always_enabled *)
interface AxiiicSda;
    method Action      i(Bit#(1) v);
    method Bit#(1)     o();
    method Bit#(1)     t();
endinterface
(* always_ready, always_enabled *)
interface AxiIic;
    method Bit#(8)     gpo();
    method Bit#(1)     iic2intc_irpt();
    interface AxiiicS_axi     s_axi;
    interface AxiiicScl     scl;
    interface AxiiicSda     sda;
endinterface
import "BVI" axi_iic_0 =
module mkAxiIicBvi#(Clock s_axi_aclk, Reset s_axi_aresetn)(AxiIic);
    default_clock clk();
    default_reset rst();
        input_clock s_axi_aclk(s_axi_aclk) = s_axi_aclk;
        input_reset s_axi_aresetn(s_axi_aresetn) = s_axi_aresetn;
    method gpo gpo();
    method iic2intc_irpt iic2intc_irpt();
    interface AxiiicS_axi     s_axi;
        method araddr(s_axi_araddr) clocked_by (s_axi_aclk) reset_by (s_axi_aresetn) enable((*inhigh*) EN_s_axi_araddr);
        method s_axi_arready arready() clocked_by (s_axi_aclk) reset_by (s_axi_aresetn);
        method arvalid(s_axi_arvalid) clocked_by (s_axi_aclk) reset_by (s_axi_aresetn) enable((*inhigh*) EN_s_axi_arvalid);
        method awaddr(s_axi_awaddr) clocked_by (s_axi_aclk) reset_by (s_axi_aresetn) enable((*inhigh*) EN_s_axi_awaddr);
        method s_axi_awready awready() clocked_by (s_axi_aclk) reset_by (s_axi_aresetn);
        method awvalid(s_axi_awvalid) clocked_by (s_axi_aclk) reset_by (s_axi_aresetn) enable((*inhigh*) EN_s_axi_awvalid);
        method bready(s_axi_bready) clocked_by (s_axi_aclk) reset_by (s_axi_aresetn) enable((*inhigh*) EN_s_axi_bready);
        method s_axi_bresp bresp() clocked_by (s_axi_aclk) reset_by (s_axi_aresetn);
        method s_axi_bvalid bvalid() clocked_by (s_axi_aclk) reset_by (s_axi_aresetn);
        method s_axi_rdata rdata() clocked_by (s_axi_aclk) reset_by (s_axi_aresetn);
        method rready(s_axi_rready) clocked_by (s_axi_aclk) reset_by (s_axi_aresetn) enable((*inhigh*) EN_s_axi_rready);
        method s_axi_rresp rresp() clocked_by (s_axi_aclk) reset_by (s_axi_aresetn);
        method s_axi_rvalid rvalid() clocked_by (s_axi_aclk) reset_by (s_axi_aresetn);
        method wdata(s_axi_wdata) clocked_by (s_axi_aclk) reset_by (s_axi_aresetn) enable((*inhigh*) EN_s_axi_wdata);
        method s_axi_wready wready() clocked_by (s_axi_aclk) reset_by (s_axi_aresetn);
        method wstrb(s_axi_wstrb) clocked_by (s_axi_aclk) reset_by (s_axi_aresetn) enable((*inhigh*) EN_s_axi_wstrb);
        method wvalid(s_axi_wvalid) clocked_by (s_axi_aclk) reset_by (s_axi_aresetn) enable((*inhigh*) EN_s_axi_wvalid);
    endinterface
    interface AxiiicScl     scl;
        method i(scl_i) enable((*inhigh*) EN_scl_i);
        method scl_o o();
        method scl_t t();
    endinterface
    interface AxiiicSda     sda;
        method i(sda_i) enable((*inhigh*) EN_sda_i);
        method sda_o o();
        method sda_t t();
    endinterface
    schedule (gpo, iic2intc_irpt, s_axi.araddr, s_axi.arready, s_axi.arvalid, s_axi.awaddr, s_axi.awready, s_axi.awvalid, s_axi.bready, s_axi.bresp, s_axi.bvalid, s_axi.rdata, s_axi.rready, s_axi.rresp, s_axi.rvalid, s_axi.wdata, s_axi.wready, s_axi.wstrb, s_axi.wvalid, scl.i, scl.o, scl.t, sda.i, sda.o, sda.t) CF (gpo, iic2intc_irpt, s_axi.araddr, s_axi.arready, s_axi.arvalid, s_axi.awaddr, s_axi.awready, s_axi.awvalid, s_axi.bready, s_axi.bresp, s_axi.bvalid, s_axi.rdata, s_axi.rready, s_axi.rresp, s_axi.rvalid, s_axi.wdata, s_axi.wready, s_axi.wstrb, s_axi.wvalid, scl.i, scl.o, scl.t, sda.i, sda.o, sda.t);
endmodule

instance ToAxi4SlaveBits#(Axi4SlaveLiteBits#(9,32), AxiiicS_axi);
   function Axi4SlaveLiteBits#(9,32) toAxi4SlaveBits(AxiiicS_axi s);
      return (interface Axi4SlaveLiteBits#(9,32);
	 method araddr = s.araddr;
	 method arready = s.arready;
	 method arvalid = s.arvalid;
	 method awaddr = s.awaddr;
	 method awready = s.awready;
	 method awvalid = s.awvalid;
	 method bready = s.bready;
	 method bresp = s.bresp;
	 method bvalid = s.bvalid;
	 method rdata = s.rdata;
	 method rready = s.rready;
	 method rresp = s.rresp;
	 method rvalid = s.rvalid;
	 method wdata = s.wdata;
	 method wready = s.wready;
	 method Action      wvalid(Bit#(1) v);
	    s.wvalid(v);
	    s.wstrb(pack(replicate(v)));
	 endmethod
	 endinterface);
   endfunction
endinstance

/*
   /home/jamey/connectal.clean/generated/scripts/importbvi.py
   -P
   AxiIic
   -I
   AxiIic
   -c
   s_axi_aclk
   -r
   s_axi_aresetn
   -n
   iic2intc_irpt
   -o
   AxiIic.bsv
   cores/vc709/axi_iic_0/axi_iic_0_stub.v
*/

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

(* always_ready, always_enabled *)
interface AxiiicS_axi;
    method Action      araddr(Bit#(9) v);
    method Bit#(1)     arready();
    method Action      arvalid(Bit#(1) v);
    method Action      awaddr(Bit#(9) v);
    method Bit#(1)     awready();
    method Action      awvalid(Bit#(1) v);
    method Action      bready(Bit#(1) v);
    method Bit#(2)     bresp();
    method Bit#(1)     bvalid();
    method Bit#(32)     rdata();
    method Action      rready(Bit#(1) v);
    method Bit#(2)     rresp();
    method Bit#(1)     rvalid();
    method Action      wdata(Bit#(32) v);
    method Bit#(1)     wready();
    method Action      wstrb(Bit#(4) v);
    method Action      wvalid(Bit#(1) v);
endinterface
(* always_ready, always_enabled *)
interface AxiiicScl;
    method Action      i(Bit#(1) v);
    method Bit#(1)     o();
    method Bit#(1)     t();
endinterface
(* always_ready, always_enabled *)
interface AxiiicSda;
    method Action      i(Bit#(1) v);
    method Bit#(1)     o();
    method Bit#(1)     t();
endinterface
(* always_ready, always_enabled *)
interface AxiIic;
    method Bit#(8)     gpo();
    method Bit#(1)     iic2intc_irpt();
    interface AxiiicS_axi     s_axi;
    interface AxiiicScl     scl;
    interface AxiiicSda     sda;
endinterface
import "BVI" axi_iic_0 =
module mkAxiIicBvi#(Clock s_axi_aclk, Reset s_axi_aresetn)(AxiIic);
    default_clock clk();
    default_reset rst();
        input_clock s_axi_aclk(s_axi_aclk) = s_axi_aclk;
        input_reset s_axi_aclk_reset() = s_axi_aresetn; /* from clock*/
        input_reset s_axi_aresetn(s_axi_aresetn) = s_axi_aresetn;
    method gpo gpo();
    method iic2intc_irpt iic2intc_irpt();
    interface AxiiicS_axi     s_axi;
        method araddr(s_axi_araddr) clocked_by (s_axi_aclk) reset_by (s_axi_aresetn) enable((*inhigh*) EN_s_axi_araddr);
        method s_axi_arready arready() clocked_by (s_axi_aclk) reset_by (s_axi_aresetn);
        method arvalid(s_axi_arvalid) clocked_by (s_axi_aclk) reset_by (s_axi_aresetn) enable((*inhigh*) EN_s_axi_arvalid);
        method awaddr(s_axi_awaddr) clocked_by (s_axi_aclk) reset_by (s_axi_aresetn) enable((*inhigh*) EN_s_axi_awaddr);
        method s_axi_awready awready() clocked_by (s_axi_aclk) reset_by (s_axi_aresetn);
        method awvalid(s_axi_awvalid) clocked_by (s_axi_aclk) reset_by (s_axi_aresetn) enable((*inhigh*) EN_s_axi_awvalid);
        method bready(s_axi_bready) clocked_by (s_axi_aclk) reset_by (s_axi_aresetn) enable((*inhigh*) EN_s_axi_bready);
        method s_axi_bresp bresp() clocked_by (s_axi_aclk) reset_by (s_axi_aresetn);
        method s_axi_bvalid bvalid() clocked_by (s_axi_aclk) reset_by (s_axi_aresetn);
        method s_axi_rdata rdata() clocked_by (s_axi_aclk) reset_by (s_axi_aresetn);
        method rready(s_axi_rready) clocked_by (s_axi_aclk) reset_by (s_axi_aresetn) enable((*inhigh*) EN_s_axi_rready);
        method s_axi_rresp rresp() clocked_by (s_axi_aclk) reset_by (s_axi_aresetn);
        method s_axi_rvalid rvalid() clocked_by (s_axi_aclk) reset_by (s_axi_aresetn);
        method wdata(s_axi_wdata) clocked_by (s_axi_aclk) reset_by (s_axi_aresetn) enable((*inhigh*) EN_s_axi_wdata);
        method s_axi_wready wready() clocked_by (s_axi_aclk) reset_by (s_axi_aresetn);
        method wstrb(s_axi_wstrb) clocked_by (s_axi_aclk) reset_by (s_axi_aresetn) enable((*inhigh*) EN_s_axi_wstrb);
        method wvalid(s_axi_wvalid) clocked_by (s_axi_aclk) reset_by (s_axi_aresetn) enable((*inhigh*) EN_s_axi_wvalid);
    endinterface
    interface AxiiicScl     scl;
        method i(scl_i) enable((*inhigh*) EN_scl_i);
        method scl_o o();
        method scl_t t();
    endinterface
    interface AxiiicSda     sda;
        method i(sda_i) enable((*inhigh*) EN_sda_i);
        method sda_o o();
        method sda_t t();
    endinterface
    schedule (gpo, iic2intc_irpt, s_axi.araddr, s_axi.arready, s_axi.arvalid, s_axi.awaddr, s_axi.awready, s_axi.awvalid, s_axi.bready, s_axi.bresp, s_axi.bvalid, s_axi.rdata, s_axi.rready, s_axi.rresp, s_axi.rvalid, s_axi.wdata, s_axi.wready, s_axi.wstrb, s_axi.wvalid, scl.i, scl.o, scl.t, sda.i, sda.o, sda.t) CF (gpo, iic2intc_irpt, s_axi.araddr, s_axi.arready, s_axi.arvalid, s_axi.awaddr, s_axi.awready, s_axi.awvalid, s_axi.bready, s_axi.bresp, s_axi.bvalid, s_axi.rdata, s_axi.rready, s_axi.rresp, s_axi.rvalid, s_axi.wdata, s_axi.wready, s_axi.wstrb, s_axi.wvalid, scl.i, scl.o, scl.t, sda.i, sda.o, sda.t);
endmodule

instance ToAxi4SlaveBits#(Axi4SlaveLiteBits#(9,32), AxiiicS_axi);
   function Axi4SlaveLiteBits#(9,32) toAxi4SlaveBits(AxiiicS_axi s);
      return (interface Axi4SlaveLiteBits#(9,32);
	 method araddr = s.araddr;
	 method arready = s.arready;
	 method arvalid = s.arvalid;
	 method awaddr = s.awaddr;
	 method awready = s.awready;
	 method awvalid = s.awvalid;
	 method bready = s.bready;
	 method bresp = s.bresp;
	 method bvalid = s.bvalid;
	 method rdata = s.rdata;
	 method rready = s.rready;
	 method rresp = s.rresp;
	 method rvalid = s.rvalid;
	 method wdata = s.wdata;
	 method wready = s.wready;
	 method Action      wvalid(Bit#(1) v);
	    s.wvalid(v);
	    s.wstrb(pack(replicate(v)));
	 endmethod
	 endinterface);
   endfunction
endinstance


minimize differences between ImageonZynqTop.bsv and ZynqTop.bsv

// 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 Clocks :: *;
import Vector            :: *;
import Connectable       :: *;
import Portal            :: *;
import Leds              :: *;
import Top               :: *;
import AxiMasterSlave    :: *;
import XilinxCells       :: *;
import XbsvXilinxCells   :: *;
import PS7LIB::*;
import PPS7LIB::*;
import XADC::*;
import ConnectableWithTrace::*;
import CtrlMux::*;
import AxiMasterSlave    :: *;
import AxiDma            :: *;

interface I2C_Pins;
   interface Inout#(Bit#(1)) scl;
   interface Inout#(Bit#(1)) sda;
endinterface

(* always_ready, always_enabled *)
interface ZynqTop#(type pins);
   (* prefix="" *)
   interface ZynqPins zynq;
   (* prefix="GPIO" *)
   interface LEDS             leds;
   (* prefix="XADC" *)
   interface XADC             xadc;
   (* prefix="I2C" *)
   interface I2C_Pins         i2c;
   (* prefix="" *)
   interface pins             pins;
   interface Vector#(4, Clock) deleteme_unused_clock;
   interface Vector#(4, Reset) deleteme_unused_reset;
endinterface

typedef (function Module#(PortalTop#(32, 64, ipins, nMasters)) mkpt()) MkPortalTop#(type ipins, numeric type nMasters);

module [Module] mkZynqTopFromPortal#(MkPortalTop#(ipins,nMasters) constructor)(ZynqTop#(ipins))
   provisos(Add#(a__,nMasters,4));

   PS7 ps7 <- mkPS7();
   Clock mainclock <- mkClockBUFG(clocked_by ps7.fclkclk[0]);
   Clock clock200 <- mkClockBUFG(clocked_by ps7.fclkclk[3]);
   Reset mainreset = ps7.fclkreset[0];
   IDELAYCTRL idel <- mkIDELAYCTRL(2, clocked_by clock200, reset_by mainreset);

   let tscl <- mkIOBUF(~ps7.i2c[1].scltn, ps7.i2c[1].sclo, clocked_by mainclock, reset_by mainreset);
   let tsda <- mkIOBUF(~ps7.i2c[1].sdatn, ps7.i2c[1].sdao, clocked_by mainclock, reset_by mainreset);
   rule sdai;
      ps7.i2c[1].sdai(tsda.o);
      ps7.i2c[1].scli(tscl.o);
   endrule

   let top <- constructor(clocked_by mainclock, reset_by mainreset);

   Axi3Slave#(32,32,12) ctrl <- mkAxiDmaSlave(top.slave);
   mkConnection(ps7.m_axi_gp[0].client, ctrl, clocked_by mainclock, reset_by mainreset);
   Vector#(nMasters,Axi3Master#(32,64,6)) m_axis;
   if(valueOf(nMasters) > 0) begin
      m_axis[0] <- mkAxiDmaMaster(clocked_by mainclock, reset_by mainreset, top.masters[0]);
      mkConnectionWithTrace(m_axis[0], ps7.s_axi_hp[0].axi.server, clocked_by mainclock, reset_by mainreset);
   end
   if(valueOf(nMasters) > 1) begin
      m_axis[1] <- mkAxiDmaMaster(clocked_by mainclock, reset_by mainreset, top.masters[1]);
      mkConnection(m_axis[1], ps7.s_axi_hp[1].axi.server, clocked_by mainclock, reset_by mainreset);
   end
   if(valueOf(nMasters) > 2) begin
      m_axis[2] <- mkAxiDmaMaster(clocked_by mainclock, reset_by mainreset, top.masters[2]);
      mkConnection(m_axis[2], ps7.s_axi_hp[2].axi.server, clocked_by mainclock, reset_by mainreset);
   end
   if(valueOf(nMasters) > 3) begin
      m_axis[3] <- mkAxiDmaMaster(clocked_by mainclock, reset_by mainreset, top.masters[3]);
      mkConnection(m_axis[3], ps7.s_axi_hp[3].axi.server, clocked_by mainclock, reset_by mainreset);
   end

   let intr_mux <- mkInterruptMux(top.interrupt);
   rule send_int_rule;
      ps7.interrupt(pack(intr_mux));
   endrule

   interface zynq = ps7.pins;
   interface leds = top.leds;
   interface XADC xadc;
       method Bit#(4) gpio;
           return 0;
       endmethod
   endinterface
   interface I2C_Pins i2c;
      interface Inout scl = tscl.io;
      interface Inout sda = tsda.io;
   endinterface
   interface pins = top.pins;
   interface deleteme_unused_clock = ps7.fclkclk;
   interface deleteme_unused_reset = ps7.fclkreset;
endmodule

module mkImageonZynqTop(ZynqTop#(ImageCapturePins));
   let top <- mkZynqTopFromPortal(mkPortalTop);
   return top;
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 Clocks :: *;
import Vector            :: *;
import Connectable       :: *;
import Portal            :: *;
import Leds              :: *;
import Top               :: *;
import AxiMasterSlave    :: *;
import AxiDma            :: *;
import XilinxCells       :: *;
import XbsvXilinxCells   :: *;
import PS7LIB::*;
import PPS7LIB::*;
import XADC::*;
import ConnectableWithTrace::*;
import CtrlMux::*;

interface I2C_Pins;
   interface Inout#(Bit#(1)) scl;
   interface Inout#(Bit#(1)) sda;
endinterface

(* always_ready, always_enabled *)
interface ZynqTop#(type pins);
   (* prefix="" *)
   interface ZynqPins zynq;
   (* prefix="GPIO" *)
   interface LEDS             leds;
   (* prefix="XADC" *)
   interface XADC             xadc;
   (* prefix="I2C" *)
   interface I2C_Pins         i2c;
   (* prefix="" *)
   interface pins             pins;
   interface Vector#(4, Clock) deleteme_unused_clock;
   interface Vector#(4, Reset) deleteme_unused_reset;
endinterface

typedef (function Module#(PortalTop#(32, 64, ipins, 0)) mkpt()) MkPortalTop#(type ipins);
//typedef (function Module#(PortalTop#(32, 64, ipins, nMasters)) mkpt()) MkPortalTop#(type ipins, numeric type nMasters);

module [Module] mkZynqTopFromPortal#(MkPortalTop#(ipins) constructor)(ZynqTop#(ipins));
   PS7 ps7 <- mkPS7();
   Clock mainclock <- mkClockBUFG(clocked_by ps7.fclkclk[0]);
   Clock clock200 <- mkClockBUFG(clocked_by ps7.fclkclk[3]);
   Reset mainreset = ps7.fclkreset[0];
   IDELAYCTRL idel <- mkIDELAYCTRL(2, clocked_by clock200, reset_by mainreset);

   let tscl <- mkIOBUF(~ps7.i2c[1].scltn, ps7.i2c[1].sclo, clocked_by mainclock, reset_by mainreset);
   let tsda <- mkIOBUF(~ps7.i2c[1].sdatn, ps7.i2c[1].sdao, clocked_by mainclock, reset_by mainreset);
   rule sdai;
      ps7.i2c[1].sdai(tsda.o);
      ps7.i2c[1].scli(tscl.o);
   endrule

   let top <- constructor(clocked_by mainclock, reset_by mainreset);
   Axi3Slave#(32,32,12) ctrl <- mkAxiDmaSlave(top.slave);
   mkConnection(ps7.m_axi_gp[0].client, ctrl, clocked_by mainclock, reset_by mainreset);
   //Axi3Master#(32,64,6) m_axi <- mkAxiDmaMaster(top.masters[0], clocked_by mainclock, reset_by mainreset);
   //mkConnectionWithTrace(m_axi, ps7.s_axi_hp[0].axi.server, clocked_by mainclock, reset_by mainreset);

   let intr_mux <- mkInterruptMux(top.interrupt);
   rule send_int_rule;
      ps7.interrupt(pack(intr_mux));
   endrule

   interface zynq = ps7.pins;
   interface leds = top.leds;
   interface XADC xadc;
      method Bit#(4) gpio;
         return 0;
      endmethod
   endinterface

   interface I2C_Pins i2c;
      interface Inout scl = tscl.io;
      interface Inout sda = tsda.io;
   endinterface

   interface pins = top.pins;

   // these are exported to make bsc happy, and then the ports are disconnected after synthesis
   interface deleteme_unused_clock = ps7.fclkclk;
   interface deleteme_unused_reset = ps7.fclkreset;
endmodule

module mkImageonZynqTop(ZynqTop#(ImageCapturePins));
   let top <- mkZynqTopFromPortal(mkPortalTop);
   return top;
endmodule