rename fifo for aid in debugging netlist

// Copyright (c) 2016 Connectal Project

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

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

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

import Connectable::*;
import FIFOF::*;
import GetPut::*;
import GetPutM::*;

(* always_ready, always_enabled *)
interface AxiStreamMaster#(numeric type dsz);
    method Bit#(dsz)              tdata();
    method Bit#(TDiv#(dsz,8))     tkeep();
    method Bit#(1)                tlast();
    (* prefix = "" *)method Action                 tready((* port="tready" *) Bit#(1) v);
    method Bit#(1)                tvalid();
endinterface

(* always_ready, always_enabled *)
interface AxiStreamSlave#(numeric type dsz);
    (* prefix = "" *)
    method Action      tdata((* port = "tdata" *) Bit#(dsz) v);
    (* prefix = "" *)
    method Action      tkeep((* port = "tkeep" *) Bit#(TDiv#(dsz,8)) v);
    (* prefix = "" *)
    method Action      tlast((* port = "tlast" *) Bit#(1) v);
    method Bit#(1)     tready();
    (* prefix = "" *)
    method Action      tvalid((* port = "tvalid" *)Bit#(1) v);
endinterface

instance Connectable#(AxiStreamMaster#(dataWidth), AxiStreamSlave#(dataWidth));
   module mkConnection#(AxiStreamMaster#(dataWidth) from, AxiStreamSlave#(dataWidth) to)(Empty);
      rule rl_axi_stream;
	 to.tdata(from.tdata());
	 to.tkeep(from.tkeep());
	 to.tlast(from.tlast());
	 to.tvalid(from.tvalid());
	 from.tready(to.tready());
      endrule
   endmodule
endinstance

instance Connectable#(AxiStreamMaster#(dataWidth), Put#(dtype))
   provisos (Bits#(dtype, dataWidth));
   module mkConnection#(AxiStreamMaster#(dataWidth) from, Put#(dtype) to)(Empty);
      FIFOF#(Bit#(dataWidth)) asputfifo <- mkFIFOF();
      rule rl_ready;
	 from.tready(pack(asputfifo.notFull));
      endrule
      rule rl_enq if (from.tvalid == 1);
	 asputfifo.enq(from.tdata);
      endrule
      rule rl_put;
	 let v <- toGet(asputfifo).get();
	 to.put(unpack(v));
      endrule
   endmodule
endinstance

instance Connectable#(Get#(dtype), AxiStreamSlave#(dataWidth))
   provisos (Bits#(dtype, dataWidth));
   module mkConnection#(Get#(dtype) from, AxiStreamSlave#(dataWidth) to)(Empty);
      FIFOF#(Bit#(dataWidth)) asgetfifo <- mkFIFOF();
      rule rl_get;
	 let v <- from.get();
	 asgetfifo.enq(pack(v));
      endrule
      rule rl_axi_stream;
	 to.tdata(asgetfifo.first);
	 to.tkeep(maxBound);
	 to.tlast(0);
      endrule
      rule rl_tvalid;
	 to.tvalid(pack(asgetfifo.notEmpty));
      endrule
      rule rl_deq if (to.tready == 1);
	 asgetfifo.deq();
      endrule
   endmodule
endinstance

////////////////////////////////////////////////////////////

instance ToGetM#(AxiStreamMaster#(asz), Bit#(asz));
   module toGetM#(AxiStreamMaster#(asz) m)(Get#(Bit#(asz)));
      FIFOF#(Bit#(asz)) tmpfifo <- mkFIFOF();

      rule handshake;
         m.tready(pack(tmpfifo.notFull));
      endrule
      rule enq if (unpack(m.tvalid));
	 tmpfifo.enq(m.tdata());
      endrule

      return toGet(tmpfifo);
   endmodule
endinstance

instance ToPutM#(AxiStreamSlave#(asz), Bit#(asz));
   module toPutM#(AxiStreamSlave#(asz) m)(Put#(Bit#(asz)));
      FIFOF#(Bit#(asz)) tmpfifo <- mkFIFOF();

      rule handshake;
	 m.tvalid(pack(tmpfifo.notEmpty()));
      endrule
      rule deq if (unpack(m.tready()));
	 m.tdata(tmpfifo.first());
	 m.tkeep(maxBound);
	 m.tlast(1);
	 tmpfifo.deq();
      endrule

      return toPut(tmpfifo);
   endmodule
endinstance

////////////////////////////////////////////////////////////
typeclass ToAxiStream#(type atype, type btype);
   function atype toAxiStream(btype b);
endtypeclass
typeclass MkAxiStream#(type atype, type btype);
   module mkAxiStream#(btype b)(atype);
endtypeclass

instance MkAxiStream#(AxiStreamMaster#(dsize), FIFOF#(Bit#(dsize)));
   module mkAxiStream#(FIFOF#(Bit#(dsize)) f)(AxiStreamMaster#(dsize));
      Wire#(Bool) readyWire <- mkDWire(False);
      Wire#(Bit#(dsize)) dataWire <- mkDWire(0);
      rule rl_data if (f.notEmpty());
	 dataWire <= f.first();
      endrule
      rule rl_deq if (readyWire && f.notEmpty);
	 f.deq();
      endrule
     method Bit#(dsize)              tdata();
	return dataWire;
     endmethod
     method Bit#(TDiv#(dsize,8))     tkeep(); return maxBound; endmethod
     method Bit#(1)                tlast(); return pack(False); endmethod
     method Action                 tready(Bit#(1) v);
	readyWire <= unpack(v);
     endmethod
     method Bit#(1)                tvalid(); return pack(f.notEmpty()); endmethod
   endmodule
endinstance

instance MkAxiStream#(AxiStreamSlave#(dsize), FIFOF#(Bit#(dsize)));
   module mkAxiStream#(FIFOF#(Bit#(dsize)) f)(AxiStreamSlave#(dsize));
      Wire#(Bit#(dsize)) dataWire <- mkDWire(unpack(0));
      Wire#(Bool) validWire <- mkDWire(False);
      rule enq if (validWire && f.notFull());
	 f.enq(dataWire);
      endrule
      method Action      tdata(Bit#(dsize) v);
	 dataWire <= v;
      endmethod
      method Action      tkeep(Bit#(TDiv#(dsize,8)) v); endmethod
      method Action      tlast(Bit#(1) v); endmethod
      method Bit#(1)     tready(); return pack(f.notFull()); endmethod
      method Action      tvalid(Bit#(1) v);
	 validWire <= unpack(v);
      endmethod
   endmodule
endinstance

// Copyright (c) 2016 Connectal Project

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

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

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

import Connectable::*;
import FIFOF::*;
import GetPut::*;
import GetPutM::*;

(* always_ready, always_enabled *)
interface AxiStreamMaster#(numeric type dsz);
    method Bit#(dsz)              tdata();
    method Bit#(TDiv#(dsz,8))     tkeep();
    method Bit#(1)                tlast();
    (* prefix = "" *)method Action                 tready((* port="tready" *) Bit#(1) v);
    method Bit#(1)                tvalid();
endinterface

(* always_ready, always_enabled *)
interface AxiStreamSlave#(numeric type dsz);
    (* prefix = "" *)
    method Action      tdata((* port = "tdata" *) Bit#(dsz) v);
    (* prefix = "" *)
    method Action      tkeep((* port = "tkeep" *) Bit#(TDiv#(dsz,8)) v);
    (* prefix = "" *)
    method Action      tlast((* port = "tlast" *) Bit#(1) v);
    method Bit#(1)     tready();
    (* prefix = "" *)
    method Action      tvalid((* port = "tvalid" *)Bit#(1) v);
endinterface

instance Connectable#(AxiStreamMaster#(dataWidth), AxiStreamSlave#(dataWidth));
   module mkConnection#(AxiStreamMaster#(dataWidth) from, AxiStreamSlave#(dataWidth) to)(Empty);
      rule rl_axi_stream;
	 to.tdata(from.tdata());
	 to.tkeep(from.tkeep());
	 to.tlast(from.tlast());
	 to.tvalid(from.tvalid());
	 from.tready(to.tready());
      endrule
   endmodule
endinstance

instance Connectable#(AxiStreamMaster#(dataWidth), Put#(dtype))
   provisos (Bits#(dtype, dataWidth));
   module mkConnection#(AxiStreamMaster#(dataWidth) from, Put#(dtype) to)(Empty);
      FIFOF#(Bit#(dataWidth)) tmpfifo <- mkFIFOF();
      rule rl_ready;
	 from.tready(pack(tmpfifo.notFull));
      endrule
      rule rl_enq if (from.tvalid == 1);
	 tmpfifo.enq(from.tdata);
      endrule
      rule rl_put;
	 let v <- toGet(tmpfifo).get();
	 to.put(unpack(v));
      endrule
   endmodule
endinstance

instance Connectable#(Get#(dtype), AxiStreamSlave#(dataWidth))
   provisos (Bits#(dtype, dataWidth));
   module mkConnection#(Get#(dtype) from, AxiStreamSlave#(dataWidth) to)(Empty);
      FIFOF#(Bit#(dataWidth)) tmpfifo <- mkFIFOF();
      rule rl_get;
	 let v <- from.get();
	 tmpfifo.enq(pack(v));
      endrule
      rule rl_axi_stream;
	 to.tdata(tmpfifo.first);
	 to.tkeep(maxBound);
	 to.tlast(0);
      endrule
      rule rl_tvalid;
	 to.tvalid(pack(tmpfifo.notEmpty));
      endrule
      rule rl_deq if (to.tready == 1);
	 tmpfifo.deq();
      endrule
   endmodule
endinstance

////////////////////////////////////////////////////////////

instance ToGetM#(AxiStreamMaster#(asz), Bit#(asz));
   module toGetM#(AxiStreamMaster#(asz) m)(Get#(Bit#(asz)));
      FIFOF#(Bit#(asz)) tmpfifo <- mkFIFOF();

      rule handshake;
         m.tready(pack(tmpfifo.notFull));
      endrule
      rule enq if (unpack(m.tvalid));
	 tmpfifo.enq(m.tdata());
      endrule

      return toGet(tmpfifo);
   endmodule
endinstance

instance ToPutM#(AxiStreamSlave#(asz), Bit#(asz));
   module toPutM#(AxiStreamSlave#(asz) m)(Put#(Bit#(asz)));
      FIFOF#(Bit#(asz)) tmpfifo <- mkFIFOF();

      rule handshake;
	 m.tvalid(pack(tmpfifo.notEmpty()));
      endrule
      rule deq if (unpack(m.tready()));
	 m.tdata(tmpfifo.first());
	 m.tkeep(maxBound);
	 m.tlast(1);
	 tmpfifo.deq();
      endrule

      return toPut(tmpfifo);
   endmodule
endinstance

////////////////////////////////////////////////////////////
typeclass ToAxiStream#(type atype, type btype);
   function atype toAxiStream(btype b);
endtypeclass
typeclass MkAxiStream#(type atype, type btype);
   module mkAxiStream#(btype b)(atype);
endtypeclass

instance MkAxiStream#(AxiStreamMaster#(dsize), FIFOF#(Bit#(dsize)));
   module mkAxiStream#(FIFOF#(Bit#(dsize)) f)(AxiStreamMaster#(dsize));
      Wire#(Bool) readyWire <- mkDWire(False);
      Wire#(Bit#(dsize)) dataWire <- mkDWire(0);
      rule rl_data if (f.notEmpty());
	 dataWire <= f.first();
      endrule
      rule rl_deq if (readyWire && f.notEmpty);
	 f.deq();
      endrule
     method Bit#(dsize)              tdata();
	return dataWire;
     endmethod
     method Bit#(TDiv#(dsize,8))     tkeep(); return maxBound; endmethod
     method Bit#(1)                tlast(); return pack(False); endmethod
     method Action                 tready(Bit#(1) v);
	readyWire <= unpack(v);
     endmethod
     method Bit#(1)                tvalid(); return pack(f.notEmpty()); endmethod
   endmodule
endinstance

instance MkAxiStream#(AxiStreamSlave#(dsize), FIFOF#(Bit#(dsize)));
   module mkAxiStream#(FIFOF#(Bit#(dsize)) f)(AxiStreamSlave#(dsize));
      Wire#(Bit#(dsize)) dataWire <- mkDWire(unpack(0));
      Wire#(Bool) validWire <- mkDWire(False);
      rule enq if (validWire && f.notFull());
	 f.enq(dataWire);
      endrule
      method Action      tdata(Bit#(dsize) v);
	 dataWire <= v;
      endmethod
      method Action      tkeep(Bit#(TDiv#(dsize,8)) v); endmethod
      method Action      tlast(Bit#(1) v); endmethod
      method Bit#(1)     tready(); return pack(f.notFull()); endmethod
      method Action      tvalid(Bit#(1) v);
	 validWire <= unpack(v);
      endmethod
   endmodule
endinstance


Implement PipeOut and PipeIn for PMA

Implement PipeOut and PipeIn for PMA

// Copyright (c) 2014 Cornell University.

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

package EthPma;

import Clocks                               ::*;
import Vector                               ::*;
import Connectable                          ::*;
import FIFOF ::*;
import SpecialFIFOs ::*;
import Pipe ::*;
import GetPut ::*;

import ConnectalClocks                      ::*;
import Ethernet                             ::*;
import ALTERA_ETH_PMA_WRAPPER               ::*;
import ALTERA_ETH_PMA_RECONFIG_WRAPPER      ::*;
import ALTERA_ETH_PMA_RESET_CONTROL_WRAPPER ::*;

`ifdef NUMBER_OF_10G_PORTS
typedef `NUMBER_OF_10G_PORTS NumPorts;
`else
typedef 4 NumPorts;
`endif

(* always_ready, always_enabled *)
interface PhyMgmtIfc;
(* prefix="" *) method Action      phy_mgmt_address( (* port="address" *) Bit#(7) v);
(* prefix="" *) method Action      phy_mgmt_read   ( (* port="read" *)    Bit#(1) v);
(* prefix="", result="readdata" *)    method Bit#(32)    phy_mgmt_readdata;
(* prefix="", result="waitrequest" *) method Bit#(1)     phy_mgmt_waitrequest;
(* prefix="" *) method Action      phy_mgmt_write  ( (* port="write" *)   Bit#(1) v);
(* prefix="" *) method Action      phy_mgmt_write_data( (* port="write_data" *) Bit#(32) v);
endinterface

(* always_ready, always_enabled *)
interface Status;
   method Bit#(1)     pll_locked;
   method Bit#(1)     rx_is_lockedtodata;
   method Bit#(1)     rx_is_lockedtoref;
endinterface

(* always_ready, always_enabled *)
interface EthPmaInternal#(numeric type np);
   interface PhyMgmtIfc             phy_mgmt;
   interface Vector#(np, Status)    status;
   interface Vector#(np, SerialIfc) pmd;
   interface Vector#(np, XCVR_PMA)  fpga;
endinterface

interface EthPma#(numeric type numPorts);
   interface Vector#(numPorts, PipeOut#(Bit#(40))) rx;
   interface Vector#(numPorts, PipeIn#(Bit#(40)))  tx;
   interface Vector#(numPorts, Bool)  rx_ready;
   interface Vector#(numPorts, Clock) rx_clkout;
   interface Vector#(numPorts, Bool)  tx_ready;
   interface Vector#(numPorts, Clock) tx_clkout;
   interface Vector#(numPorts, SerialIfc) pmd;
endinterface

//(* synthesize *)
module mkEthPmaInternal#(Clock phy_mgmt_clk, Clock pll_ref_clk, Reset phy_mgmt_reset)(EthPmaInternal#(NumPorts));

   Clock defaultClock <- exposeCurrentClock();
   Reset defaultReset <- exposeCurrentReset();

   EthXcvrWrap         xcvr  <- mkEthXcvrWrap();
   EthXcvrReconfigWrap cfg   <- mkEthXcvrReconfigWrap(phy_mgmt_clk, phy_mgmt_reset, phy_mgmt_reset);
   EthXcvrResetWrap    rst   <- mkEthXcvrResetWrap(phy_mgmt_clk, phy_mgmt_reset, phy_mgmt_reset);

   C2B c2b <- mkC2B(pll_ref_clk);
   rule convert_clk_to_bit;
      xcvr.tx.pll_refclk(c2b.o);
      xcvr.rx.cdr_refclk(c2b.o);
   endrule

   rule connect_xcvr_reconfig;
      cfg.reconfig.from_xcvr(xcvr.reconfig.from_xcvr);
      xcvr.reconfig.to_xcvr(cfg.reconfig.to_xcvr);
   endrule

   rule connect_xcvr_and_reset_controller;
      xcvr.rx.analogreset(rst.rx.analogreset);
      xcvr.rx.digitalreset(rst.rx.digitalreset);
      xcvr.tx.analogreset(rst.tx.analogreset);
      xcvr.tx.digitalreset(rst.tx.digitalreset);
      rst.rx.cal_busy(xcvr.rx.cal_busy);
      rst.tx.cal_busy(xcvr.tx.cal_busy);
      rst.rx.is_lockedtodata(xcvr.rx.is_lockedtodata);
      rst.pll.locked(xcvr.pll.locked);
      xcvr.pll.powerdown(rst.pll.powerdown);
   endrule

   rule connect_any_constants;
      rst.pll.select(2'b11);
   endrule

   // Status
   Vector#(NumPorts, Status) status_ifcs;
   for (Integer i=0; i < valueOf(NumPorts); i=i+1) begin
      status_ifcs[i] = interface Status;
          method Bit#(1) pll_locked;
             return xcvr.pll.locked[i];
          endmethod
          method Bit#(1) rx_is_lockedtodata;
             return xcvr.rx.is_lockedtodata[i];
          endmethod
          method Bit#(1) rx_is_lockedtoref;
             return xcvr.rx.is_lockedtoref[i];
          endmethod
       endinterface;
   end

   // Use Wire to pass data from interface expression to other rules.
   Vector#(NumPorts, Wire#(Bit#(1))) wires <- replicateM(mkDWire(0));
   Vector#(NumPorts, SerialIfc) serial_ifcs;
   for (Integer i=0; i < valueOf(NumPorts); i=i+1) begin
       serial_ifcs[i] = interface SerialIfc;
          method Action rx (Bit#(1) v);
             wires[i] <= v;
          endmethod
          method Bit#(1) tx;
             return xcvr.tx.serial_data[i];
          endmethod
       endinterface;
   end
   rule set_serial_data;
      // Use readVReg to read Vector of Wires.
      xcvr.rx.serial_data(pack(readVReg(wires)));
   endrule

   // FPGA Fabric-Side Interface
   Vector#(NumPorts, Wire#(Bit#(40))) p_wires <- replicateM(mkDWire(0));
   Vector#(NumPorts, XCVR_PMA) xcvr_ifcs;
   for (Integer i=0; i < valueOf(NumPorts); i=i+1) begin
      xcvr_ifcs[i] = interface XCVR_PMA;
          interface XCVR_RX_PMA rx;
             method Bit#(1) rx_ready;
                return rst.rx_r.eady[i];
             endmethod
             method Bit#(1) rx_clkout;
                return xcvr.rx.pma_clkout[i];
             endmethod
             method Bit#(40) rx_data;
                return xcvr.rx.pma_parallel_data[39 + 40 * i : 40 * i];
             endmethod
          endinterface
          interface XCVR_TX_PMA tx;
             method Bit#(1) tx_ready;
                return rst.tx_r.eady[i];
             endmethod
             method Bit#(1) tx_clkout;
                return xcvr.tx.pma_clkout[i];
             endmethod
             method Action tx_data (Bit#(40) v);
                p_wires[i] <= v;
             endmethod
          endinterface
       endinterface;
   end
   rule set_parallel_data;
      xcvr.tx.pma_parallel_data(pack(readVReg(p_wires)));
   endrule

   interface status = status_ifcs;
   interface pmd    = serial_ifcs;
   interface fpga   = xcvr_ifcs;

   interface PhyMgmtIfc phy_mgmt;
      method Action phy_mgmt_address(v);
         cfg.reconfig.mgmt_address(v);
      endmethod

      method Action phy_mgmt_read(v);
         cfg.reconfig.mgmt_read(v);
      endmethod

      method Bit#(32) phy_mgmt_readdata;
         return cfg.reconfig.mgmt_readdata;
      endmethod

      method Bit#(1) phy_mgmt_waitrequest;
         return cfg.reconfig.mgmt_waitrequest;
      endmethod

      method Action phy_mgmt_write(v);
         cfg.reconfig.mgmt_write(v);
      endmethod

      method Action phy_mgmt_write_data(v);
         cfg.reconfig.mgmt_writedata(v);
      endmethod
   endinterface

endmodule: mkEthPmaInternal

module mkEthPma(EthPma#(NumPorts) intf);
   Clock defaultClock <- exposeCurrentClock();
   Reset defaultReset <- exposeCurrentReset();
   EthPmaInternal#(NumPorts) pma <- mkEthPmaInternal(defaultClock, defaultClock, defaultReset);

   Vector#(NumPorts, FIFOF#(Bit#(40))) rxFifo <- replicateM(mkFIFOF());
   Vector#(NumPorts, FIFOF#(Bit#(40))) txFifo <- replicateM(mkFIFOF());
   Vector#(NumPorts, PipeOut#(Bit#(40))) vRxPipe = newVector;
   Vector#(NumPorts, PipeIn#(Bit#(40))) vTxPipe = newVector;
   for (Integer i=0; i<valueOf(NumPorts); i=i+1) begin
      vRxPipe[i] = toPipeOut(rxFifo[i]);
      vTxPipe[i] = toPipeIn(txFifo[i]);
   end
   rule receive (True);
      for(Integer i=0; i<valueOf(NumPorts); i=i+1) begin
         rxFifo[i].enq(pma.fpga[i].rx.rx_data);
      end
   endrule
   rule transmit (True);
      for(Integer i=0; i<valueOf(NumPorts); i=i+1) begin
         let v <- toGet(txFifo[i]).get;
         pma.fpga[i].tx.tx_data(v);
      end
   endrule

   Vector#(NumPorts, Bool) rxReady = newVector;
   Vector#(NumPorts, Bool) txReady = newVector;
   for(Integer i=0; i<valueOf(NumPorts); i=i+1) begin
      rxReady[i] = unpack(pma.fpga[i].rx.rx_ready);
      txReady[i] = unpack(pma.fpga[i].tx.tx_ready);
   end

   Vector#(NumPorts, B2C1) tx_clk;
   Vector#(NumPorts, B2C1) rx_clk;
   for (Integer i=0; i < valueOf(NumPorts); i=i+1) begin
      tx_clk[i] <- mkB2C1();
      rx_clk[i] <- mkB2C1();
   end
   rule out_pma_clk;
      for (Integer i=0; i < valueOf(NumPorts); i=i+1) begin
         tx_clk[i].inputclock(pma.fpga[i].tx.tx_clkout);
         rx_clk[i].inputclock(pma.fpga[i].rx.rx_clkout);
      end
   endrule

   Vector#(NumPorts, Clock) out_tx_clk;
   Vector#(NumPorts, Clock) out_rx_clk;
   for (Integer i=0; i< valueOf(NumPorts); i=i+1) begin
      out_tx_clk[i] = tx_clk[i].c;
      out_rx_clk[i] = rx_clk[i].c;
   end

   interface tx_clkout = out_tx_clk;
   interface rx_clkout = out_rx_clk;
   interface rx_ready  = rxReady;
   interface tx_ready  = txReady;
   interface rx        = vRxPipe;
   interface tx        = vTxPipe;
   interface pmd       = pma.pmd;
endmodule: mkEthPma

(* synthesize *)
module mkEthPmaTop(EthPma#(4));
   EthPma#(4) _a <- mkEthPma(); return _a;
endmodule

endpackage: EthPma

// Copyright (c) 2014 Cornell University.

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

package EthPma;

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

import ConnectalClocks                      ::*;
import Ethernet                             ::*;

import ALTERA_ETH_PMA_WRAPPER               ::*;
import ALTERA_ETH_PMA_RECONFIG_WRAPPER      ::*;
import ALTERA_ETH_PMA_RESET_CONTROL_WRAPPER ::*;

`ifdef NUMBER_OF_10G_PORTS
typedef `NUMBER_OF_10G_PORTS NumPorts;
`else
typedef 4 NumPorts;
`endif

(* always_ready, always_enabled *)
interface PhyMgmtIfc;
(* prefix="" *) method Action      phy_mgmt_address( (* port="address" *) Bit#(7) v);
(* prefix="" *) method Action      phy_mgmt_read   ( (* port="read" *)    Bit#(1) v);
(* prefix="", result="readdata" *)    method Bit#(32)    phy_mgmt_readdata;
(* prefix="", result="waitrequest" *) method Bit#(1)     phy_mgmt_waitrequest;
(* prefix="" *) method Action      phy_mgmt_write  ( (* port="write" *)   Bit#(1) v);
(* prefix="" *) method Action      phy_mgmt_write_data( (* port="write_data" *) Bit#(32) v);
endinterface

(* always_ready, always_enabled *)
interface Status;
   method Bit#(1)     pll_locked;
   method Bit#(1)     rx_is_lockedtodata;
   method Bit#(1)     rx_is_lockedtoref;
endinterface

(* always_ready, always_enabled *)
interface EthPmaIfc#(numeric type np);
   interface PhyMgmtIfc             phy_mgmt;
   interface Vector#(np, Status)    status;
   interface Vector#(np, SerialIfc) fiber;
   interface Vector#(np, XCVR_PMA)  fpga;
endinterface

(* synthesize *)
module mkEthPma#(Clock phy_mgmt_clk, Clock pll_ref_clk, Reset phy_mgmt_reset)(EthPmaIfc#(NumPorts));

   Clock defaultClock <- exposeCurrentClock();
   Reset defaultReset <- exposeCurrentReset();

   EthXcvrWrap         xcvr  <- mkEthXcvrWrap();
   EthXcvrReconfigWrap cfg   <- mkEthXcvrReconfigWrap(phy_mgmt_clk, phy_mgmt_reset, phy_mgmt_reset);
   EthXcvrResetWrap    rst   <- mkEthXcvrResetWrap(phy_mgmt_clk, phy_mgmt_reset, phy_mgmt_reset);

   C2B c2b <- mkC2B(pll_ref_clk);
   rule convert_clk_to_bit;
      xcvr.tx.pll_refclk(c2b.o);
      xcvr.rx.cdr_refclk(c2b.o);
   endrule

   rule connect_xcvr_reconfig;
      cfg.reconfig.from_xcvr(xcvr.reconfig.from_xcvr);
      xcvr.reconfig.to_xcvr(cfg.reconfig.to_xcvr);
   endrule

   rule connect_xcvr_and_reset_controller;
      xcvr.rx.analogreset(rst.rx.analogreset);
      xcvr.rx.digitalreset(rst.rx.digitalreset);
      xcvr.tx.analogreset(rst.tx.analogreset);
      xcvr.tx.digitalreset(rst.tx.digitalreset);
      rst.rx.cal_busy(xcvr.rx.cal_busy);
      rst.tx.cal_busy(xcvr.tx.cal_busy);
      rst.rx.is_lockedtodata(xcvr.rx.is_lockedtodata);
      rst.pll.locked(xcvr.pll.locked);
      xcvr.pll.powerdown(rst.pll.powerdown);
   endrule

   rule connect_any_constants;
      rst.pll.select(2'b11);
   endrule

   /* connect all three components */
//   Vector#(NumPorts, B2C1) tx_clk;
//   Vector#(NumPorts, B2C1) rx_clk;
//   for (Integer i=0; i < valueOf(NumPorts); i=i+1) begin
//      tx_clk[i] <- mkB2C1();
//      rx_clk[i] <- mkB2C1();
//   end
//
//   rule out_pma_clk;
//      for (Integer i=0; i < valueOf(NumPorts); i=i+1) begin
//         tx_clk[i].inputclock(xcvr.tx.pma_clkout[i]);
//         rx_clk[i].inputclock(xcvr.rx.pma_clkout[i]);
//      end
//   endrule
//
//   Vector#(NumPorts, Clock) out_tx_clk;
//   Vector#(NumPorts, Clock) out_rx_clk;
//   for (Integer i=0; i< valueOf(NumPorts); i=i+1) begin
//      out_tx_clk[i] = tx_clk[i].c;
//      out_rx_clk[i] = rx_clk[i].c;
//   end
//   interface tx_clkout = out_tx_clk;
//   interface rx_clkout = out_rx_clk;

   // Status
   Vector#(NumPorts, Status) status_ifcs;
   for (Integer i=0; i < valueOf(NumPorts); i=i+1) begin
      status_ifcs[i] = interface Status;
          method Bit#(1) pll_locked;
             return xcvr.pll.locked[i];
          endmethod
          method Bit#(1) rx_is_lockedtodata;
             return xcvr.rx.is_lockedtodata[i];
          endmethod
          method Bit#(1) rx_is_lockedtoref;
             return xcvr.rx.is_lockedtoref[i];
          endmethod
       endinterface;
   end

   // Use Wire to pass data from interface expression to other rules.
   Vector#(NumPorts, Wire#(Bit#(1))) wires <- replicateM(mkDWire(0));
   Vector#(NumPorts, SerialIfc) serial_ifcs;
   for (Integer i=0; i < valueOf(NumPorts); i=i+1) begin
       serial_ifcs[i] = interface SerialIfc;
          method Action rx (Bit#(1) v);
             wires[i] <= v;
          endmethod
          method Bit#(1) tx;
             return xcvr.tx.serial_data[i];
          endmethod
       endinterface;
   end
   rule set_serial_data;
      // Use readVReg to read Vector of Wires.
      xcvr.rx.serial_data(pack(readVReg(wires)));
   endrule

   // FPGA Fabric-Side Interface
   Vector#(NumPorts, Wire#(Bit#(40))) p_wires <- replicateM(mkDWire(0));
   Vector#(NumPorts, XCVR_PMA) xcvr_ifcs;
   for (Integer i=0; i < valueOf(NumPorts); i=i+1) begin
      xcvr_ifcs[i] = interface XCVR_PMA;
          interface XCVR_RX_PMA rx;
             method Bit#(1) rx_ready;
                return rst.rx_r.eady[i];
             endmethod
             method Bit#(1) rx_clkout;
                return xcvr.rx.pma_clkout[i];
             endmethod
             method Bit#(40) rx_data;
                return xcvr.rx.pma_parallel_data[39 + 40 * i : 40 * i];
             endmethod
          endinterface
          interface XCVR_TX_PMA tx;
             method Bit#(1) tx_ready;
                return rst.tx_r.eady[i];
             endmethod
             method Bit#(1) tx_clkout;
                return xcvr.tx.pma_clkout[i];
             endmethod
             method Action tx_data (Bit#(40) v);
                p_wires[i] <= v;
             endmethod
          endinterface
       endinterface;
   end
   rule set_parallel_data;
      xcvr.tx.pma_parallel_data(pack(readVReg(p_wires)));
   endrule

   interface status = status_ifcs;
   interface fiber  = serial_ifcs;
   interface fpga   = xcvr_ifcs;

   interface PhyMgmtIfc phy_mgmt;
      method Action phy_mgmt_address(v);
         cfg.reconfig.mgmt_address(v);
      endmethod

      method Action phy_mgmt_read(v);
         cfg.reconfig.mgmt_read(v);
      endmethod

      method Bit#(32) phy_mgmt_readdata;
         return cfg.reconfig.mgmt_readdata;
      endmethod

      method Bit#(1) phy_mgmt_waitrequest;
         return cfg.reconfig.mgmt_waitrequest;
      endmethod

      method Action phy_mgmt_write(v);
         cfg.reconfig.mgmt_write(v);
      endmethod

      method Action phy_mgmt_write_data(v);
         cfg.reconfig.mgmt_writedata(v);
      endmethod
   endinterface

endmodule: mkEthPma
endpackage: EthPma


export pins from mkXsimTop

export pins from mkXsimTop

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

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

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

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
import ConnectalConfig::*;
import Vector            :: *;
import GetPut::*;
import Connectable::*;
import Portal            :: *;
import Top               :: *;
import HostInterface     :: *;
import Pipe::*;
import CnocPortal::*;
import MemTypes:: *;
import MMU:: *;
import MemServer:: *;
import MMURequest::*;
import MMUIndication::*;
import MemServerIndication::*;
import MemServerRequest::*;
import SimDma::*;
import IfcNames::*;
import BuildVector::*;

`include "ConnectalProjectConfig.bsv"

`ifdef PIN_TYPE_INCLUDE
import `PIN_TYPE_INCLUDE::*;
`endif
`ifdef PIN_TYPE
typedef `PIN_TYPE PinType;
`else
typedef Empty PinType;
`endif

interface XsimTop;
   interface PinType pins;
endinterface

interface XsimSource;
    method Action beat(Bit#(32) v);
endinterface
import "BVI" XsimSource =
module mkXsimSourceBVI#(Bit#(32) portal)(XsimSource);
    port portal = portal;
    method beat(beat) enable(en_beat);
    schedule (beat) C (beat);
endmodule
module mkXsimSource#(PortalMsgIndication indication)(Empty);
   let tmp <- mkXsimSourceBVI(indication.id);
   rule ind_dst_rdy;
      indication.message.deq();
      tmp.beat(indication.message.first());
   endrule
endmodule

interface MsgSinkR#(numeric type bytes_per_beat);
   method ActionValue#(Bit#(32)) beat();
endinterface

import "BVI" XsimSink =
module mkXsimSinkBVI#(Bit#(32) portal)(MsgSinkR#(4));
   port portal = portal;
   method beat beat() enable (EN_beat) ready (RDY_beat);
   schedule (beat) C (beat);
endmodule
module mkXsimSink#(PortalMsgRequest request)(Empty);
   let sink <- mkXsimSinkBVI(request.id);

   rule req_src_rdy;
      let beat <- sink.beat();
      request.message.enq(beat);
   endrule
endmodule

module mkXsimMemoryConnection#(PhysMemMaster#(addrWidth, dataWidth) master)(Empty)
   provisos (Mul#(TDiv#(dataWidth, 8), 8, dataWidth),
	     Mul#(TDiv#(dataWidth, 32), 32, dataWidth),
	     Add#(a__, TDiv#(DataBusWidth,8), TDiv#(dataWidth, 8)),
	     Mul#(TDiv#(dataWidth, 32), 4, TDiv#(dataWidth, 8)));
   PhysMemSlave#(addrWidth,dataWidth) slave <- mkSimDmaDmaMaster();
   mkConnection(master, slave);
endmodule

module mkXsimTop#(Clock derivedClock, Reset derivedReset)(XsimTop);

   Reg#(Bool) dumpstarted <- mkReg(False);
   rule startdump if (!dumpstarted);
      //$dumpfile("dump.vcd");
      //$dumpvars;
      $display("XsimTop starting");
      dumpstarted <= True;
   endrule
   XsimHost host <- mkXsimHost(derivedClock, derivedReset);
   let top <- mkCnocTop(
`ifdef IMPORT_HOSTIF
       host
`else
`ifdef IMPORT_HOST_CLOCKS // enables synthesis boundary
       derivedClock, derivedReset
`else
// otherwise no params
`endif
`endif
       );

   MMUIndicationOutput lMMUIndicationOutput <- mkMMUIndicationOutput;
   MMURequestInput lMMURequestInput <- mkMMURequestInput;
   MMU#(PhysAddrWidth) lMMU <- mkMMU(0,True, lMMUIndicationOutput.ifc);
   mkConnection(lMMURequestInput.pipes, lMMU.request);

   MemServerIndicationOutput lMemServerIndicationOutput <- mkMemServerIndicationOutput;
   MemServerRequestInput lMemServerRequestInput <- mkMemServerRequestInput;
   MemServer#(PhysAddrWidth,DataBusWidth,NumberOfMasters) lMemServer <- mkMemServer(top.readers, top.writers, cons(lMMU,nil), lMemServerIndicationOutput.ifc);
   mkConnection(lMemServerRequestInput.pipes, lMemServer.request);

   let lMMUIndicationOutputNoc <- mkPortalMsgIndication(extend(pack(IfcNames_MMUIndicationH2S)), lMMUIndicationOutput.portalIfc.indications, lMMUIndicationOutput.portalIfc.messageSize);
   let lMMURequestInputNoc <- mkPortalMsgRequest(extend(pack(IfcNames_MMURequestS2H)), lMMURequestInput.portalIfc.requests);
   let lMemServerIndicationOutputNoc <- mkPortalMsgIndication(extend(pack(IfcNames_MemServerIndicationH2S)), lMemServerIndicationOutput.portalIfc.indications, lMemServerIndicationOutput.portalIfc.messageSize);
   let lMemServerRequestInputNoc <- mkPortalMsgRequest(extend(pack(IfcNames_MemServerRequestS2H)), lMemServerRequestInput.portalIfc.requests);

   mapM_(mkXsimSink, append(top.requests, append(vec(lMMURequestInputNoc), vec(lMemServerRequestInputNoc))));
   mapM_(mkXsimSource, append(top.indications, append(vec(lMMUIndicationOutputNoc), vec(lMemServerIndicationOutputNoc))));
   mapM_(mkXsimMemoryConnection, lMemServer.masters);

`ifdef PIN_TYPE
   interface pins = top.pins;
`endif
endmodule

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

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

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

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
import ConnectalConfig::*;
import Vector            :: *;
import GetPut::*;
import Connectable::*;
import Portal            :: *;
import Top               :: *;
import HostInterface     :: *;
import Pipe::*;
import CnocPortal::*;
import MemTypes:: *;
import MMU:: *;
import MemServer:: *;
import MMURequest::*;
import MMUIndication::*;
import MemServerIndication::*;
import MemServerRequest::*;
import SimDma::*;
import IfcNames::*;
import BuildVector::*;

`include "ConnectalProjectConfig.bsv"

interface XsimSource;
    method Action beat(Bit#(32) v);
endinterface
import "BVI" XsimSource =
module mkXsimSourceBVI#(Bit#(32) portal)(XsimSource);
    port portal = portal;
    method beat(beat) enable(en_beat);
    schedule (beat) C (beat);
endmodule
module mkXsimSource#(PortalMsgIndication indication)(Empty);
   let tmp <- mkXsimSourceBVI(indication.id);
   rule ind_dst_rdy;
      indication.message.deq();
      tmp.beat(indication.message.first());
   endrule
endmodule

interface MsgSinkR#(numeric type bytes_per_beat);
   method ActionValue#(Bit#(32)) beat();
endinterface

import "BVI" XsimSink =
module mkXsimSinkBVI#(Bit#(32) portal)(MsgSinkR#(4));
   port portal = portal;
   method beat beat() enable (EN_beat) ready (RDY_beat);
   schedule (beat) C (beat);
endmodule
module mkXsimSink#(PortalMsgRequest request)(Empty);
   let sink <- mkXsimSinkBVI(request.id);

   rule req_src_rdy;
      let beat <- sink.beat();
      request.message.enq(beat);
   endrule
endmodule

module mkXsimMemoryConnection#(PhysMemMaster#(addrWidth, dataWidth) master)(Empty)
   provisos (Mul#(TDiv#(dataWidth, 8), 8, dataWidth),
	     Mul#(TDiv#(dataWidth, 32), 32, dataWidth),
	     Add#(a__, TDiv#(DataBusWidth,8), TDiv#(dataWidth, 8)),
	     Mul#(TDiv#(dataWidth, 32), 4, TDiv#(dataWidth, 8)));
   PhysMemSlave#(addrWidth,dataWidth) slave <- mkSimDmaDmaMaster();
   mkConnection(master, slave);
endmodule

module mkXsimTop#(Clock derivedClock, Reset derivedReset)(Empty);

   Reg#(Bool) dumpstarted <- mkReg(False);
   rule startdump if (!dumpstarted);
      //$dumpfile("dump.vcd");
      //$dumpvars;
      $display("XsimTop starting");
      dumpstarted <= True;
   endrule
   XsimHost host <- mkXsimHost(derivedClock, derivedReset);
   let top <- mkCnocTop(
`ifdef IMPORT_HOSTIF
       host
`else
`ifdef IMPORT_HOST_CLOCKS // enables synthesis boundary
       derivedClock, derivedReset
`else
// otherwise no params
`endif
`endif
       );

   MMUIndicationOutput lMMUIndicationOutput <- mkMMUIndicationOutput;
   MMURequestInput lMMURequestInput <- mkMMURequestInput;
   MMU#(PhysAddrWidth) lMMU <- mkMMU(0,True, lMMUIndicationOutput.ifc);
   mkConnection(lMMURequestInput.pipes, lMMU.request);

   MemServerIndicationOutput lMemServerIndicationOutput <- mkMemServerIndicationOutput;
   MemServerRequestInput lMemServerRequestInput <- mkMemServerRequestInput;
   MemServer#(PhysAddrWidth,DataBusWidth,NumberOfMasters) lMemServer <- mkMemServer(top.readers, top.writers, cons(lMMU,nil), lMemServerIndicationOutput.ifc);
   mkConnection(lMemServerRequestInput.pipes, lMemServer.request);

   let lMMUIndicationOutputNoc <- mkPortalMsgIndication(extend(pack(IfcNames_MMUIndicationH2S)), lMMUIndicationOutput.portalIfc.indications, lMMUIndicationOutput.portalIfc.messageSize);
   let lMMURequestInputNoc <- mkPortalMsgRequest(extend(pack(IfcNames_MMURequestS2H)), lMMURequestInput.portalIfc.requests);
   let lMemServerIndicationOutputNoc <- mkPortalMsgIndication(extend(pack(IfcNames_MemServerIndicationH2S)), lMemServerIndicationOutput.portalIfc.indications, lMemServerIndicationOutput.portalIfc.messageSize);
   let lMemServerRequestInputNoc <- mkPortalMsgRequest(extend(pack(IfcNames_MemServerRequestS2H)), lMemServerRequestInput.portalIfc.requests);

   mapM_(mkXsimSink, append(top.requests, append(vec(lMMURequestInputNoc), vec(lMemServerRequestInputNoc))));
   mapM_(mkXsimSource, append(top.indications, append(vec(lMMUIndicationOutputNoc), vec(lMemServerIndicationOutputNoc))));
   mapM_(mkXsimMemoryConnection, lMemServer.masters);
endmodule


removing redundant file

removing redundant file

import FIFOF::*;
import SpecialFIFOs::*;
import GetPut::*;
import ClientServer::*;
import StmtFSM::*;
import Vector::*;
import DefaultValue::*;

import MatchTableTypes::*;
import HashFunction::*;
import HashTable::*;

module mkMatchTable (Server#(RequestType, ResponseType));

    function RequestType backup (RequestType currReq);
        return RequestType {
            key : currReq.key,
            value : currReq.value,
            op : currReq.op,
            addrIdx : currReq.addrIdx
        };
    endfunction

    Vector#(MATCH_TABLE_ASSOCIATIVITY, Server#(RequestType, ResponseType)) hTable <-
                replicateM(mkHashTable);

    FIFOF#(RequestType) requestFIFO <- mkSizedBypassFIFOF(10);
    FIFOF#(ResponseType) responseFIFO <- mkBypassFIFOF;

    Reg#(RequestType) currReq <- mkReg(defaultValue);
    Reg#(RequestType) currReq_backup <- mkReg(defaultValue);
    Vector#(MATCH_TABLE_ASSOCIATIVITY, Reg#(Bit#(1))) free <- replicateM(mkReg(1));
    Reg#(Bit#(1)) putInProgress <- mkReg(0);
    FIFOF#(Bit#(1)) fsm_start_signal_fifo <- mkFIFOF;

    for (Integer i=0; i<fromInteger(valueof(MATCH_TABLE_ASSOCIATIVITY)); i=i+1)
    begin
        rule response_from_hTable;
            ResponseType res <- hTable[i].response.get;
            if (res.tag == VALID && res.op == GET)
                responseFIFO.enq(res);
        endrule
    end

    Stmt putFSM = (seq
    action
    endaction
    action
    endaction
    par
        action
            ResponseType res <- hTable[0].response.get;
            if (res.op == NON_EMPTY_SLOTS && res.tag == VALID)
                free[0] <= 0;
        endaction
        action
            ResponseType res <- hTable[1].response.get;
            if (res.op == NON_EMPTY_SLOTS && res.tag == VALID)
                free[1] <= 0;
        endaction
        action
            ResponseType res <- hTable[2].response.get;
            if (res.op == NON_EMPTY_SLOTS && res.tag == VALID)
                free[2] <= 0;
        endaction
        action
            ResponseType res <- hTable[3].response.get;
            if (res.op == NON_EMPTY_SLOTS && res.tag == VALID)
                free[3] <= 0;
        endaction
        action
            ResponseType res <- hTable[4].response.get;
            if (res.op == NON_EMPTY_SLOTS && res.tag == VALID)
                free[4] <= 0;
        endaction
        action
            ResponseType res <- hTable[5].response.get;
            if (res.op == NON_EMPTY_SLOTS && res.tag == VALID)
                free[5] <= 0;
        endaction
        action
            ResponseType res <- hTable[6].response.get;
            if (res.op == NON_EMPTY_SLOTS && res.tag == VALID)
                free[6] <= 0;
        endaction
        action
            ResponseType res <- hTable[7].response.get;
            if (res.op == NON_EMPTY_SLOTS && res.tag == VALID)
                free[7] <= 0;
        endaction
    endpar
    action
        Integer found = 0;
        for (Integer i=0; i<fromInteger(valueof(MATCH_TABLE_ASSOCIATIVITY)); i=i+1)
        begin
            if (found == 0 && free[i] == 1)
            begin
                $display("Putting at index = %d", i);
                hTable[i].request.put(currReq_backup);
                found = 1;
            end
        end
        putInProgress <= 0;
    endaction
    endseq);

    FSM fsm <- mkFSM(putFSM);

    rule start (putInProgress == 0);
        let currReq <- toGet(requestFIFO).get;
        AddrIndex addrIdx = hash_function(currReq.key);
        currReq.addrIdx = addrIdx;
        currReq_backup <= backup(currReq);
        if (currReq.op == PUT)
        begin
            for (Integer i=0; i<fromInteger(valueof(MATCH_TABLE_ASSOCIATIVITY));i=i+1)
                free[i] <= 1;
            putInProgress <= 1;
            currReq.op = NON_EMPTY_SLOTS;
            fsm_start_signal_fifo.enq(1);
        end
        for (Integer i=0; i<fromInteger(valueof(MATCH_TABLE_ASSOCIATIVITY)); i=i+1)
            hTable[i].request.put(currReq);
    endrule

    rule startFSM;
        let x <- toGet(fsm_start_signal_fifo).get;
        fsm.start();
    endrule

    interface Put request = toPut(requestFIFO);
    interface Get response = toGet(responseFIFO);
endmodule


removed bram completely

removed bram completely

Change-Id: I64d04f928d429066722b65bcccf891d97adbce32

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

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

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

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

import FIFOF::*;
import GetPut::*;
import Vector::*;
import BRAM::*;
import GetPut::*;
import Connectable::*;
import Pipe::*;
import MemTypes::*;
import MemreadEngine::*;
import MemwriteEngine::*;

interface NandSimRequest;
   method Action startRead(Bit#(32) drampointer, Bit#(32) dramOffset, Bit#(32) nandAddr, Bit#(32) numBytes, Bit#(32) burstLen);
   method Action startWrite(Bit#(32) drampointer, Bit#(32) dramOffset, Bit#(32) nandAddr, Bit#(32) numBytes, Bit#(32) burstLen);
   method Action startErase(Bit#(32) nandAddr, Bit#(32) numBytes);
   method Action configureNand(Bit#(32) ptr, Bit#(32) numBytes);
endinterface

interface NandSimIndication;
   method Action readDone(Bit#(32) tag);
   method Action writeDone(Bit#(32) tag);
   method Action eraseDone(Bit#(32) tag);
   method Action configureNandDone();
endinterface

interface NandSim;
   interface NandSimRequest request;
   interface ObjectReadClient#(64) readClient;
   interface ObjectWriteClient#(64) writeClient;
endinterface

module mkNandSim#(NandSimIndication indication) (NandSim);

   MemreadEngineV#(64, 1, 2)     re <- mkMemreadEngine();
   MemwriteEngineV#(64, 1, 3)    we <- mkMemwriteEngine();

   Server#(MemengineCmd,Bool)  dramReadServer = re.readServers[0];
   Server#(MemengineCmd,Bool)  nandReadServer = re.readServers[1];

   Server#(MemengineCmd,Bool) dramWriteServer = we.writeServers[0];
   Server#(MemengineCmd,Bool) nandWriteServer = we.writeServers[1];
   Server#(MemengineCmd,Bool) nandEraseServer = we.writeServers[2];

   Reg#(Bit#(32))  nandPointer   <- mkReg(0);
   Reg#(Bit#(32))  nandLen       <- mkReg(0);

   Reg#(Bit#(32)) nandWriteCount <- mkReg(0);
   // rule traceNandWrite;
   //    let v <- toGet(re.dataPipes[0]).get();
   //    $display("count=%d v=%h", nandWriteCount, v);
   //    we.dataPipes[1].enq(v);
   //    nandWriteCount <= nandWriteCount + 8;
   // endrule
   mkConnection(re.dataPipes[0], we.dataPipes[1]);
   mkConnection(re.dataPipes[1], we.dataPipes[0]);

   PipeOut#(Bit#(64)) erasePipe = (interface PipeOut#(Bit#(64));
				       method Bit#(64) first(); return fromInteger(-1); endmethod
				       method Action deq(); endmethod
				       method Bool notEmpty(); return True; endmethod
				   endinterface);
   mkConnection(erasePipe, we.dataPipes[2]);

   rule eraseDone;
      let done <- nandEraseServer.response.get();
      $display("eraseDone");
      indication.eraseDone(0);
   endrule

   rule writeDone;
      let nandWriteDone <- nandWriteServer.response.get();
      let dramReadDone <- dramReadServer.response.get();
      $display("writeDone");
      indication.writeDone(0);
   endrule

   rule readDone;
      let nandReadDone <- nandReadServer.response.get();
      let dramWriteDone <- dramWriteServer.response.get();
      $display("readDone");
      indication.readDone(0);
   endrule

   interface NandSimRequest request;
      /*!
      * Reads from NAND and writes to DRAM
      */
      method Action startRead(Bit#(32) pointer, Bit#(32) dramOffset, Bit#(32) nandAddr,Bit#(32) numBytes, Bit#(32) burstLen);
	 $display("startRead numBytes=%d burstLen=%d", numBytes, burstLen);
	 nandReadServer.request.put(MemengineCmd {pointer: nandPointer, base: extend(nandAddr), burstLen: truncate(burstLen), len: extend(numBytes)});
	 dramWriteServer.request.put(MemengineCmd {pointer: pointer, base: extend(dramOffset), burstLen: truncate(burstLen), len: extend(numBytes)});
      endmethod

      /*!
      * Reads from DRAM and writes to NAND
      */
      method Action startWrite(Bit#(32) pointer, Bit#(32) dramOffset, Bit#(32) nandAddr,Bit#(32) numBytes, Bit#(32) burstLen);
	 nandWriteCount <= 0;
	 $display("startWrite numBytes=%d burstLen=%d", numBytes, burstLen);
	 nandWriteServer.request.put(MemengineCmd {pointer: nandPointer, base: extend(nandAddr), burstLen: truncate(burstLen), len: extend(numBytes)});
	 dramReadServer.request.put(MemengineCmd {pointer: pointer, base: extend(dramOffset), burstLen: truncate(burstLen), len: extend(numBytes)});
      endmethod

      method Action startErase(Bit#(32) nandAddr, Bit#(32) numBytes);
	 $display("startErase numBytes=%d burstLen=%d", numBytes, 16);
	 nandEraseServer.request.put(MemengineCmd {pointer: nandPointer, base: extend(nandAddr), burstLen: 16, len: extend(numBytes)});
      endmethod

      method Action configureNand(Bit#(32) ptr, Bit#(32) numBytes);
	 nandPointer <= ptr;
	 nandLen <= numBytes;
	 indication.configureNandDone();
	 $display("configureNand ptr=%d", ptr);
      endmethod

   endinterface

   interface ObjectReadClient readClient = re.dmaClient;
   interface ObjectWriteClient writeClient = we.dmaClient;

endmodule

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

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

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

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

import FIFOF::*;
import GetPut::*;
import Vector::*;
import BRAM::*;
import GetPut::*;
import Connectable::*;
import Pipe::*;
import MemTypes::*;
import MemreadEngine::*;
import MemwriteEngine::*;

interface NandSimRequest;
   method Action startRead(Bit#(32) drampointer, Bit#(32) dramOffset, Bit#(32) nandAddr, Bit#(32) numBytes, Bit#(32) burstLen);
   method Action startWrite(Bit#(32) drampointer, Bit#(32) dramOffset, Bit#(32) nandAddr, Bit#(32) numBytes, Bit#(32) burstLen);
   method Action startErase(Bit#(32) nandAddr, Bit#(32) numBytes);
   method Action configureNand(Bit#(32) ptr, Bit#(32) numBytes);
endinterface

interface NandSimIndication;
   method Action readDone(Bit#(32) tag);
   method Action writeDone(Bit#(32) tag);
   method Action eraseDone(Bit#(32) tag);
   method Action configureNandDone();
endinterface

interface NandSim;
   interface NandSimRequest request;
   interface ObjectReadClient#(64) readClient;
   interface ObjectWriteClient#(64) writeClient;
endinterface

// Asz useded to be a type parameter to mkNandSim, but bsc couldn't handle that much polymorphism (mdk)
//typedef 14 Asz;

//module mkNandSim#(NandSimIndication indication, BRAMServer#(Bit#(Asz), Bit#(64)) br) (NandSim);
module mkNandSim#(NandSimIndication indication) (NandSim);

   MemreadEngineV#(64, 1, 2)     re <- mkMemreadEngine();
   MemwriteEngineV#(64, 1, 3)    we <- mkMemwriteEngine();

   Server#(MemengineCmd,Bool)  dramReadServer = re.readServers[0];
   Server#(MemengineCmd,Bool)  nandReadServer = re.readServers[1];

   Server#(MemengineCmd,Bool) dramWriteServer = we.writeServers[0];
   Server#(MemengineCmd,Bool) nandWriteServer = we.writeServers[1];
   Server#(MemengineCmd,Bool) nandEraseServer = we.writeServers[2];

   Reg#(Bit#(32))  nandPointer   <- mkReg(0);
   Reg#(Bit#(32))  nandLen       <- mkReg(0);
   //Reg#(Bit#(Asz)) nandEraseAddr <- mkReg(0);
   //Reg#(Bit#(Asz)) nandEraseLimit <- mkReg(0);
   //Reg#(Bit#(Asz)) nandEraseCnt <- mkReg(0);

   Reg#(Bit#(32)) nandWriteCount <- mkReg(0);
   // rule traceNandWrite;
   //    let v <- toGet(re.dataPipes[0]).get();
   //    $display("count=%d v=%h", nandWriteCount, v);
   //    we.dataPipes[1].enq(v);
   //    nandWriteCount <= nandWriteCount + 8;
   // endrule
   mkConnection(re.dataPipes[0], we.dataPipes[1]);
   mkConnection(re.dataPipes[1], we.dataPipes[0]);

   PipeOut#(Bit#(64)) erasePipe = (interface PipeOut#(Bit#(64));
				       method Bit#(64) first(); return fromInteger(-1); endmethod
				       method Action deq(); endmethod
				       method Bool notEmpty(); return True; endmethod
				   endinterface);
   mkConnection(erasePipe, we.dataPipes[2]);

   rule eraseDone;
      let done <- nandEraseServer.response.get();
      $display("eraseDone");
      indication.eraseDone(0);
   endrule

   rule writeDone;
      let nandWriteDone <- nandWriteServer.response.get();
      let dramReadDone <- dramReadServer.response.get();
      $display("writeDone");
      indication.writeDone(0);
   endrule

   rule readDone;
      let nandReadDone <- nandReadServer.response.get();
      let dramWriteDone <- dramWriteServer.response.get();
      $display("readDone");
      indication.readDone(0);
   endrule

   interface NandSimRequest request;
      /*!
      * Reads from NAND and writes to DRAM
      */
      method Action startRead(Bit#(32) pointer, Bit#(32) dramOffset, Bit#(32) nandAddr,Bit#(32) numBytes, Bit#(32) burstLen);
	 $display("startRead numBytes=%d burstLen=%d", numBytes, burstLen);
	 nandReadServer.request.put(MemengineCmd {pointer: nandPointer, base: extend(nandAddr), burstLen: truncate(burstLen), len: extend(numBytes)});
	 dramWriteServer.request.put(MemengineCmd {pointer: pointer, base: extend(dramOffset), burstLen: truncate(burstLen), len: extend(numBytes)});
      endmethod

      /*!
      * Reads from DRAM and writes to NAND
      */
      method Action startWrite(Bit#(32) pointer, Bit#(32) dramOffset, Bit#(32) nandAddr,Bit#(32) numBytes, Bit#(32) burstLen);
	 nandWriteCount <= 0;
	 $display("startWrite numBytes=%d burstLen=%d", numBytes, burstLen);
	 nandWriteServer.request.put(MemengineCmd {pointer: nandPointer, base: extend(nandAddr), burstLen: truncate(burstLen), len: extend(numBytes)});
	 dramReadServer.request.put(MemengineCmd {pointer: pointer, base: extend(dramOffset), burstLen: truncate(burstLen), len: extend(numBytes)});
      endmethod

      method Action startErase(Bit#(32) nandAddr, Bit#(32) numBytes);
	 $display("startErase numBytes=%d burstLen=%d", numBytes, 16);
	 nandEraseServer.request.put(MemengineCmd {pointer: nandPointer, base: extend(nandAddr), burstLen: 16, len: extend(numBytes)});
      endmethod

      method Action configureNand(Bit#(32) ptr, Bit#(32) numBytes);
	 nandPointer <= ptr;
	 nandLen <= numBytes;
	 indication.configureNandDone();
	 $display("configureNand ptr=%d", ptr);
      endmethod

   endinterface

   interface ObjectReadClient readClient = re.dmaClient;
   interface ObjectWriteClient writeClient = we.dmaClient;

endmodule


use vec instead of cons

use vec instead of cons

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

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

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

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
import ConnectalConfig::*;
import Vector::*;
import BuildVector::*;
import Portal::*;
import HostInterface::*;
import MMU::*;
import MemServer::*;
import MemTypes::*;
import CtrlMux::*;
import FIFO::*;
import GetPut::*;
import SpecialFIFOs::*;
import Pipe::*;
import ConnectalMemory::*;
import MMURequest::*;
import MMUIndication::*;
import MemServerIndication::*;
import MemServerRequest::*;
import IfcNames::*;
`include "ConnectalProjectConfig.bsv"
import `PinTypeInclude::*;

interface Platform;
   interface PhysMemSlave#(32,32) slave;
   interface Vector#(NumberOfMasters,PhysMemMaster#(PhysAddrWidth, DataBusWidth)) masters;
   interface Vector#(MaxNumberOfPortals,ReadOnly#(Bool)) interrupt;
   interface `PinType pins;
endinterface

typedef TMax#(TLog#(TSub#(NumberOfTiles,1)),1) TileTagBits;
function Bit#(TSub#(MemTagSize,TileTagBits)) tagLsb(Bit#(MemTagSize) tag); return truncate(tag); endfunction
function Bit#(TileTagBits) tagMsb(Bit#(MemTagSize) tag); return truncate(tag >> valueOf(TSub#(MemTagSize,TileTagBits))); endfunction

module renameReads#(Integer tile, MemReadClient#(DataBusWidth) reader, MemServerIndication err)(MemReadClient#(DataBusWidth));
   interface Get readReq;
      method ActionValue#(MemRequest) get;
	 let req <- reader.readReq.get;
	 Bit#(TSub#(MemTagSize,TileTagBits)) lsb = tagLsb(req.tag);
	 Bit#(TileTagBits) msb = tagMsb(req.tag);
	 if(req.tag != extend(lsb) && valueOf(NumberOfTiles) > 2) begin // one mgmt tile and one user tile
	    $display("renameReads tile tag out of range: 'h%h", req.tag);
	    err.error(extend(pack(DmaErrorTileTagOutOfRange)), req.sglId, extend(req.tag), fromInteger(tile));
	 end
	 req.tag = {fromInteger(tile),lsb};
	 return req;
      endmethod
   endinterface
   interface Put readData;
      method Action put(MemData#(DataBusWidth) v);
	 reader.readData.put(MemData{data:v.data, tag:{0,tagLsb(v.tag)}, last:v.last});
      endmethod
   endinterface
endmodule

module renameWrites#(Integer tile, MemWriteClient#(DataBusWidth) writer, MemServerIndication err)(MemWriteClient#(DataBusWidth));
   interface Get writeReq;
      method ActionValue#(MemRequest) get;
	 let req <- writer.writeReq.get;
	 Bit#(TSub#(MemTagSize,TileTagBits)) lsb = tagLsb(req.tag);
	 Bit#(TileTagBits) msb = tagMsb(req.tag);
	 if(req.tag != extend(lsb) && valueOf(NumberOfTiles) > 2) begin // one mgmt tile and one user tile
	    $display("renameWrites tile tag out of range: 'h%h", req.tag);
	    err.error(extend(pack(DmaErrorTileTagOutOfRange)), req.sglId, extend(req.tag), fromInteger(tile));
	 end
	 req.tag = {fromInteger(tile),lsb};
	 return req;
      endmethod
   endinterface
   interface Get writeData;
      method ActionValue#(MemData#(DataBusWidth)) get;
	 let rv <- writer.writeData.get;
   	 return MemData{data:rv.data, tag:{0,tagLsb(rv.tag)}, last:rv.last};
      endmethod
   endinterface
   interface Put writeDone;
      method Action put(Bit#(MemTagSize) v);
	 writer.writeDone.put({0,tagLsb(v)});
      endmethod
   endinterface
endmodule

module mkPlatform#(Vector#(NumberOfUserTiles, ConnectalTop) tiles)(Platform);
   /////////////////////////////////////////////////////////////
   // connecting up the tiles

   Vector#(NumberOfUserTiles, PhysMemSlave#(18,32)) tile_slaves;
   Vector#(NumberOfUserTiles, ReadOnly#(Bool)) tile_interrupts;
   Vector#(NumberOfUserTiles, Vector#(NumReadClients, MemReadClient#(DataBusWidth))) tile_read_clients;
   Vector#(NumberOfUserTiles, Vector#(NumWriteClients, MemWriteClient#(DataBusWidth))) tile_write_clients;
   for(Integer i = 0; i < valueOf(NumberOfUserTiles); i=i+1) begin
      tile_slaves[i] = tiles[i].slave;
      let imux <- mkInterruptMux(tiles[i].interrupt);
      //ReadOnly#(Bool) imux = tiles[i].interrupt;
      tile_interrupts[i] = imux;
      tile_read_clients[i] = tiles[i].readers;
      tile_write_clients[i] = tiles[i].writers;
   end

   /////////////////////////////////////////////////////////////
   // framework internal portals

   MMUIndicationProxy lMMUIndicationProxy <- mkMMUIndicationProxy(PlatformIfcNames_MMUIndicationH2S);
   MemServerIndicationProxy lMemServerIndicationProxy <- mkMemServerIndicationProxy(PlatformIfcNames_MemServerIndicationH2S);

   MMU#(PhysAddrWidth) lMMU <- mkMMU(0,True, lMMUIndicationProxy.ifc);
   Vector#(TMul#(NumberOfUserTiles,NumReadClients), MemReadClient#(DataBusWidth)) tile_read_clients_renamed <- zipWith3M(renameReads, genVector, concat(tile_read_clients), replicate(lMemServerIndicationProxy.ifc));
   Vector#(TMul#(NumberOfUserTiles,NumWriteClients), MemWriteClient#(DataBusWidth)) tile_write_clients_renamed <- zipWith3M(renameWrites, genVector, concat(tile_write_clients), replicate(lMemServerIndicationProxy.ifc));
   MemServer#(PhysAddrWidth,DataBusWidth,NumberOfMasters) lMemServer <- mkMemServer(tile_read_clients_renamed, nil, vec(lMMU), lMemServerIndicationProxy.ifc);

   MMURequestWrapper lMMURequestWrapper <- mkMMURequestWrapper(PlatformIfcNames_MMURequestS2H, lMMU.request);
   MemServerRequestWrapper lMemServerRequestWrapper <- mkMemServerRequestWrapper(PlatformIfcNames_MemServerRequestS2H, lMemServer.request);

   Vector#(4,StdPortal) framework_portals;
   framework_portals[0] = lMMUIndicationProxy.portalIfc;
   framework_portals[1] = lMemServerIndicationProxy.portalIfc;
   framework_portals[2] = lMMURequestWrapper.portalIfc;
   framework_portals[3] = lMemServerRequestWrapper.portalIfc;
   PhysMemSlave#(18,32) framework_ctrl_mux <- mkSlaveMux(framework_portals);
   let framework_intr <- mkInterruptMux(getInterruptVector(framework_portals));

   /////////////////////////////////////////////////////////////
   // expose interface to top

   PhysMemSlave#(32,32) ctrl_mux <- mkMemPortalMux(cons(framework_ctrl_mux,tile_slaves));
   Vector#(MaxNumberOfPortals, ReadOnly#(Bool)) interrupts = replicate(interface ReadOnly; method Bool _read(); return False; endmethod endinterface);
   interrupts[0] = framework_intr;
   for (Integer i = 1; i < valueOf(NumberOfTiles); i = i + 1)
      interrupts[i] = tile_interrupts[i-1];
   interface interrupt = interrupts;
   interface slave = ctrl_mux;
   interface masters = lMemServer.masters;
   interface pins = tiles[0].pins;
endmodule

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

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

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

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
import ConnectalConfig::*;
import Vector::*;
import Portal::*;
import HostInterface::*;
import MMU::*;
import MemServer::*;
import MemTypes::*;
import CtrlMux::*;
import FIFO::*;
import GetPut::*;
import SpecialFIFOs::*;
import Pipe::*;
import ConnectalMemory::*;
import MMURequest::*;
import MMUIndication::*;
import MemServerIndication::*;
import MemServerRequest::*;
import IfcNames::*;
`include "ConnectalProjectConfig.bsv"
import `PinTypeInclude::*;

interface Platform;
   interface PhysMemSlave#(32,32) slave;
   interface Vector#(NumberOfMasters,PhysMemMaster#(PhysAddrWidth, DataBusWidth)) masters;
   interface Vector#(MaxNumberOfPortals,ReadOnly#(Bool)) interrupt;
   interface `PinType pins;
endinterface

typedef TMax#(TLog#(TSub#(NumberOfTiles,1)),1) TileTagBits;
function Bit#(TSub#(MemTagSize,TileTagBits)) tagLsb(Bit#(MemTagSize) tag); return truncate(tag); endfunction
function Bit#(TileTagBits) tagMsb(Bit#(MemTagSize) tag); return truncate(tag >> valueOf(TSub#(MemTagSize,TileTagBits))); endfunction

module renameReads#(Integer tile, MemReadClient#(DataBusWidth) reader, MemServerIndication err)(MemReadClient#(DataBusWidth));
   interface Get readReq;
      method ActionValue#(MemRequest) get;
	 let req <- reader.readReq.get;
	 Bit#(TSub#(MemTagSize,TileTagBits)) lsb = tagLsb(req.tag);
	 Bit#(TileTagBits) msb = tagMsb(req.tag);
	 if(req.tag != extend(lsb) && valueOf(NumberOfTiles) > 2) begin // one mgmt tile and one user tile
	    $display("renameReads tile tag out of range: 'h%h", req.tag);
	    err.error(extend(pack(DmaErrorTileTagOutOfRange)), req.sglId, extend(req.tag), fromInteger(tile));
	 end
	 req.tag = {fromInteger(tile),lsb};
	 return req;
      endmethod
   endinterface
   interface Put readData;
      method Action put(MemData#(DataBusWidth) v);
	 reader.readData.put(MemData{data:v.data, tag:{0,tagLsb(v.tag)}, last:v.last});
      endmethod
   endinterface
endmodule

module renameWrites#(Integer tile, MemWriteClient#(DataBusWidth) writer, MemServerIndication err)(MemWriteClient#(DataBusWidth));
   interface Get writeReq;
      method ActionValue#(MemRequest) get;
	 let req <- writer.writeReq.get;
	 Bit#(TSub#(MemTagSize,TileTagBits)) lsb = tagLsb(req.tag);
	 Bit#(TileTagBits) msb = tagMsb(req.tag);
	 if(req.tag != extend(lsb) && valueOf(NumberOfTiles) > 2) begin // one mgmt tile and one user tile
	    $display("renameWrites tile tag out of range: 'h%h", req.tag);
	    err.error(extend(pack(DmaErrorTileTagOutOfRange)), req.sglId, extend(req.tag), fromInteger(tile));
	 end
	 req.tag = {fromInteger(tile),lsb};
	 return req;
      endmethod
   endinterface
   interface Get writeData;
      method ActionValue#(MemData#(DataBusWidth)) get;
	 let rv <- writer.writeData.get;
   	 return MemData{data:rv.data, tag:{0,tagLsb(rv.tag)}, last:rv.last};
      endmethod
   endinterface
   interface Put writeDone;
      method Action put(Bit#(MemTagSize) v);
	 writer.writeDone.put({0,tagLsb(v)});
      endmethod
   endinterface
endmodule

module mkPlatform#(Vector#(NumberOfUserTiles, ConnectalTop) tiles)(Platform);
   /////////////////////////////////////////////////////////////
   // connecting up the tiles

   Vector#(NumberOfUserTiles, PhysMemSlave#(18,32)) tile_slaves;
   Vector#(NumberOfUserTiles, ReadOnly#(Bool)) tile_interrupts;
   Vector#(NumberOfUserTiles, Vector#(NumReadClients, MemReadClient#(DataBusWidth))) tile_read_clients;
   Vector#(NumberOfUserTiles, Vector#(NumWriteClients, MemWriteClient#(DataBusWidth))) tile_write_clients;
   for(Integer i = 0; i < valueOf(NumberOfUserTiles); i=i+1) begin
      tile_slaves[i] = tiles[i].slave;
      let imux <- mkInterruptMux(tiles[i].interrupt);
      //ReadOnly#(Bool) imux = tiles[i].interrupt;
      tile_interrupts[i] = imux;
      tile_read_clients[i] = tiles[i].readers;
      tile_write_clients[i] = tiles[i].writers;
   end

   /////////////////////////////////////////////////////////////
   // framework internal portals

   MMUIndicationProxy lMMUIndicationProxy <- mkMMUIndicationProxy(PlatformIfcNames_MMUIndicationH2S);
   MemServerIndicationProxy lMemServerIndicationProxy <- mkMemServerIndicationProxy(PlatformIfcNames_MemServerIndicationH2S);

   MMU#(PhysAddrWidth) lMMU <- mkMMU(0,True, lMMUIndicationProxy.ifc);
   Vector#(TMul#(NumberOfUserTiles,NumReadClients), MemReadClient#(DataBusWidth)) tile_read_clients_renamed <- zipWith3M(renameReads, genVector, concat(tile_read_clients), replicate(lMemServerIndicationProxy.ifc));
   Vector#(TMul#(NumberOfUserTiles,NumWriteClients), MemWriteClient#(DataBusWidth)) tile_write_clients_renamed <- zipWith3M(renameWrites, genVector, concat(tile_write_clients), replicate(lMemServerIndicationProxy.ifc));
   MemServer#(PhysAddrWidth,DataBusWidth,NumberOfMasters) lMemServer <- mkMemServer(tile_read_clients_renamed, tile_write_clients_renamed, cons(lMMU,nil), lMemServerIndicationProxy.ifc);

   MMURequestWrapper lMMURequestWrapper <- mkMMURequestWrapper(PlatformIfcNames_MMURequestS2H, lMMU.request);
   MemServerRequestWrapper lMemServerRequestWrapper <- mkMemServerRequestWrapper(PlatformIfcNames_MemServerRequestS2H, lMemServer.request);

   Vector#(4,StdPortal) framework_portals;
   framework_portals[0] = lMMUIndicationProxy.portalIfc;
   framework_portals[1] = lMemServerIndicationProxy.portalIfc;
   framework_portals[2] = lMMURequestWrapper.portalIfc;
   framework_portals[3] = lMemServerRequestWrapper.portalIfc;
   PhysMemSlave#(18,32) framework_ctrl_mux <- mkSlaveMux(framework_portals);
   let framework_intr <- mkInterruptMux(getInterruptVector(framework_portals));

   /////////////////////////////////////////////////////////////
   // expose interface to top

   PhysMemSlave#(32,32) ctrl_mux <- mkMemPortalMux(cons(framework_ctrl_mux,tile_slaves));
   Vector#(MaxNumberOfPortals, ReadOnly#(Bool)) interrupts = replicate(interface ReadOnly; method Bool _read(); return False; endmethod endinterface);
   interrupts[0] = framework_intr;
   for (Integer i = 1; i < valueOf(NumberOfTiles); i = i + 1)
      interrupts[i] = tile_interrupts[i-1];
   interface interrupt = interrupts;
   interface slave = ctrl_mux;
   interface masters = lMemServer.masters;
   interface pins = tiles[0].pins;
endmodule