factored out Trace{Read,Write}Client

factored out Trace{Read,Write}Client

import BuildVector::*;
import Clocks::*;
import Connectable::*;
import GetPut::*;
import FIFOF::*;
import BRAM::*;
import BRAMFIFO::*;
import Probe::*;
import StmtFSM::*;
import TriState::*;
import Vector::*;
import XilinxCells::*;
import Probe::*;

import ConnectalXilinxCells::*;
import ConnectalBramFifo::*;
import ConnectalConfig::*;
import GetPutWithClocks::*;
import CtrlMux::*;
import HostInterface::*;
import MemTypes::*;
import Pipe::*;
import AxiBits::*;
import PhysMemToBram::*;
import TraceMemClient::*;

import BpiFlash::*;
import AxiIntcBvi::*;
import AxiIic::*;
import AxiSpiBvi::*;
import AxiUart::*;
`ifdef EthernetSgmii
import AxiEthBvi::*;
`else
//import AxiEth1000BaseX::*;
import AxiEthSubsystem::*;
import TriModeMacBvi::*;
import GigEthPcsPmaBvi::*;
import AxiEthBufferBvi::*;
import AxiEth1000BaseX::*; // for interfaces
`endif
import AxiDmaBvi::*;
import SpikeHwPins::*;
import SpikeHwIfc::*;

`include "ConnectalProjectConfig.bsv"

interface SpikeHw;
   interface SpikeHwRequest request;
   interface Vector#(2, MemReadClient#(DataBusWidth)) dmaReadClient;
   interface Vector#(2, MemWriteClient#(DataBusWidth)) dmaWriteClient;
   interface SpikeHwPins pins;
endinterface

typedef 65536 BootRomBytes;
typedef TDiv#(BootRomBytes,4) BootRomEntries;

module mkBramBootRom(Server#(BRAMRequest#(Bit#(TLog#(BootRomEntries)),Bit#(32)),Bit#(32)));
   BRAM_Configure cfg = defaultValue;
   cfg.memorySize = valueOf(BootRomEntries); // 128KB (32K x 4bytes)
   cfg.latency = 2;
   cfg.loadFormat = tagged Hex "bootromx4.hex";

   BRAM1Port#(Bit#(TLog#(BootRomEntries)), Bit#(32)) bram <- mkBRAM1Server(cfg);
   return bram.portA;
endmodule

module mkSpikeHw#(HostInterface host, SpikeHwIndication ind)(SpikeHw);

   let clock <- exposeCurrentClock();
   let reset <- exposeCurrentReset();

   let newReset <- mkReset(10, True, clock);

   BUFRParams bufrParams = defaultValue;
`ifndef BOARD_miniitx100
   bufrParams.bufr_divide = "2";
   Clock clk_125mhz <- mkClockBUFR(bufrParams, clocked_by clock);
`endif
   bufrParams.bufr_divide = "4";
   Clock uartClk <- mkClockBUFR(bufrParams, clocked_by host.derivedClock);

   let bootRom    <- mkBramBootRom();
`ifdef IncludeFlash
   let bpiFlash   <- mkBpiFlash();
`endif
   let axiIntcBvi <- mkAxiIntcBvi(clock, newReset.new_rst);
   let axiIicBvi  <- mkAxiIicBvi(clock, newReset.new_rst);
//   let axiSpiBvi  <- mkAxiSpiBvi(clock, clock, newReset.new_rst);
   let axiUartBvi <- mkAxiUartBvi(clock, newReset.new_rst, uartClk);
`ifdef IncludeEthernet
//   let axiEthBvi <- mkAxiEthBvi(clock, host.tsys_clk_200mhz_buf, clock,
//				newReset.new_rst, newReset.new_rst, newReset.new_rst, newReset.new_rst, newReset.new_rst);
   let axiEthBvi <- AxiEthSubsystem::mkAxiEthBvi(clock, host.tsys_clk_200mhz_buf, reset_by newReset.new_rst);

`endif

   Reg#(Bit#(32)) objId <- mkReg(0);
   Reg#(Bit#(1))  iicResetReg <- mkReg(0);
   Reg#(Bit#(1))  eth_los <- mkReg(0);

   let irqLevel <- mkReg(0);
   let intrLevel <- mkReg(0);

   function Bit#(16) intr();
      Bit#(16) _intr = 0;
      _intr[0] = axiUartBvi.ip2intc_irpt();
      _intr[1] = axiEthBvi.s2mm_dma.introut(); // rx
      _intr[2] = axiEthBvi.mm2s_dma.introut(); // tx
`ifdef IncludeEthernet
      _intr[3] = axiEthBvi.mac.irq();
//      _intr[4] = axiEthBvi.interrupt();
`endif
      _intr[5] = axiIicBvi.iic2intc_irpt();
//      _intr[6] = axiSpiBvi.ip2intc_irpt();
      return _intr;
   endfunction

   rule rl_intr;

      axiIntcBvi.intr(intr());
   endrule

   FIFOF#(Tuple2#(Bit#(1),Bit#(16))) irqChangeFifo <- mkSizedFIFOF(8);
   rule rl_irq_levels_changed;
      let irq = axiIntcBvi.irq;
      let levels = intr();

      if (irq != irqLevel) begin
	 $display("irq changed irq=%h intr sources %h", irq, levels);
	 irqLevel <= irq;
	 intrLevel <= levels;
	 irqChangeFifo.enq(tuple2(irq, levels));
      end
   endrule

   rule rl_intr_indication;
      match { .irq, .levels } <- toGet(irqChangeFifo).get();
      ind.irqChanged(irq, levels);
   endrule

   Reg#(Bit#(32)) cycles <- mkReg(0);
   Reg#(Bool)     mmcm_lock <- mkReg(False);
   rule rl_cycles;
      cycles <= cycles+1;
   endrule

   FIFOF#(BRAMRequest#(Bit#(32),Bit#(32))) reqFifo <- mkSizedFIFOF(4);
   FIFOF#(Bit#(32))                       dataFifo <- mkSizedFIFOF(16);

   Axi4MasterBits#(32,DataBusWidth,MemTagSize,Empty) m_axi_mm2s = toAxi4MasterBits(axiEthBvi.m_axi_mm2s);
   Axi4MasterBits#(32,DataBusWidth,MemTagSize,Empty) m_axi_s2mm = toAxi4MasterBits(axiEthBvi.m_axi_s2mm);
   Axi4MasterBits#(32,DataBusWidth,MemTagSize,Empty) m_axi_sg = toAxi4MasterBits(axiEthBvi.m_axi_sg);

   Axi4SlaveLiteBits#(12,32) axiUartSlaveLite = toAxi4SlaveBits(axiUartBvi.s_axi);
   PhysMemSlave#(12,32) axiUartMemSlave      <- mkPhysMemSlave(axiUartSlaveLite);

   Axi4SlaveLiteBits#(9,32) axiIntcSlaveLite = toAxi4SlaveBits(axiIntcBvi.s_axi);
   PhysMemSlave#(12,32) axiIntcMemSlave      <- mkPhysMemSlave(axiIntcSlaveLite);

   Axi4SlaveLiteBits#(9,32) axiIicSlaveLite  = toAxi4SlaveBits(axiIicBvi.s_axi);
   PhysMemSlave#(12,32) axiIicMemSlave       <- mkPhysMemSlave(axiIicSlaveLite);

//   Axi4SlaveLiteBits#(7,32) axiSpiSlaveLite  = toAxi4SlaveBits(axiSpiBvi.s_axi);
//   PhysMemSlave#(12,32) axiSpiMemSlave       <- mkPhysMemSlave(axiSpiSlaveLite);

`ifdef IncludeEthernet
   PhysMemSlave#(12,32) axiDmaMemSlave       <- mkPhysMemSlave(axiEthBvi.s_axi_dma);

   Axi4SlaveLiteBits#(12,32) axiEthSlaveLite = toAxi4SlaveBits(axiEthBvi.s_axi_mac);
   PhysMemSlave#(12,32) axiEthMemSlave       <- mkPhysMemSlave(axiEthSlaveLite);
   PhysMemSlave#(20,32) deviceSlaveMux       <- mkPhysMemSlaveMux(vec(axiUartMemSlave, axiIntcMemSlave, axiIicMemSlave,
								      axiDmaMemSlave, axiEthMemSlave)); // , axiSpiMemSlave
`else
   PhysMemSlave#(20,32) deviceSlaveMux       <- mkPhysMemSlaveMux(vec(axiUartMemSlave, axiIntcMemSlave, axiIicMemSlave));
`endif

   PhysMemSlave#(20,32) bootRomMemSlave      <- mkPhysMemToBram(bootRom);
   PhysMemSlave#(21,32) memSlaveMux          <- mkPhysMemSlaveMux(vec(bootRomMemSlave, deviceSlaveMux));

   let memReadClients  <- mapM(mkMemReadClient(objId), vec(m_axi_mm2s, m_axi_sg));
   let memWriteClients <- mapM(mkMemWriteClient(objId), vec(m_axi_s2mm, m_axi_sg));

`ifdef IncludeFlash
   PhysMemSlave#(26,16) bpiFlashSlave <- mkPhysMemToBram(bpiFlash.server);
`endif
   FIFOF#(Bit#(32)) dfifo <- mkFIFOF();
   FIFOF#(Bit#(32)) flashdfifo <- mkFIFOF();

`ifdef IncludeEthernet
   rule rl_axieth;
      axiEthBvi.signal.detect(1); // drive to 1 if not using optical transceiver, else use signal from transceiver
   endrule
`endif

   rule rl_rdata;
      let rdata <- memSlaveMux.read_server.readData.get();
      ind.readDone(rdata.data);
   endrule

   rule rl_wdata;
      let wdata <- toGet(dfifo).get();
       memSlaveMux.write_server.writeData.put(MemData {data: wdata, tag: 0, last: True});
   endrule

   rule rl_writeDone;
      let tag <- memSlaveMux.write_server.writeDone.get();
      ind.writeDone();
   endrule

   rule rl_bpiflash_rdata;
`ifdef IncludeFlash
      let rdata <- bpiFlashSlave.read_server.readData.get();
      ind.readFlashDone(extend(rdata.data));
`endif
   endrule

   rule rl_bpiflash_wdata;
`ifdef IncludeFlash
      let wdata <- toGet(flashdfifo).get();
       bpiFlashSlave.write_server.writeData.put(MemData {data: truncate(wdata), tag: 0, last: True});
`endif
   endrule

   rule rl_bpiflash_writeDone;
`ifdef IncludeFlash
      let tag <- bpiFlashSlave.write_server.writeDone.get();
      ind.writeFlashDone();
`endif
   endrule

`ifndef BOARD_miniitx100
   DiffClock sfp_rec_clk_buf <- mkClockOBUFDS(defaultValue, clocked_by clk_125mhz);
`endif
   IOBUF sdaIOBuf <- mkIOBUF(axiIicBvi.sda.t, axiIicBvi.sda.o);
   IOBUF sclIOBuf <- mkIOBUF(axiIicBvi.scl.t, axiIicBvi.scl.o);
   // No probe for .o because they are tied to ground -- I2C operates open collector
   Probe#(Bit#(1)) sda_i_probe <- mkProbe();
   Probe#(Bit#(1)) sda_t_probe <- mkProbe();
   Probe#(Bit#(1)) scl_i_probe <- mkProbe();
   Probe#(Bit#(1)) scl_t_probe <- mkProbe();

   rule iic_o;
      sda_i_probe <= sdaIOBuf.o;
      sda_t_probe <= axiIicBvi.sda.t;
      scl_i_probe <= sclIOBuf.o;
      scl_t_probe <= axiIicBvi.scl.t;

      axiIicBvi.sda.i(sdaIOBuf.o);
      axiIicBvi.scl.i(sclIOBuf.o);
   endrule

   // IOBUF spiSckIOBuf  <- mkIOBUF(axiSpiBvi.sck.t, axiSpiBvi.sck.o);
   // IOBUF spiSsIOBuf   <- mkIOBUF(axiSpiBvi.ss.t, axiSpiBvi.ss.o);
   // IOBUF spiMosiIOBuf <- mkIOBUF(axiSpiBvi.io0.t, axiSpiBvi.io0.o);
   // IOBUF spiMisoIOBuf <- mkIOBUF(axiSpiBvi.io1.t, axiSpiBvi.io1.o);
   // rule spi_o;
   //    axiSpiBvi.sck.i(spiSckIOBuf.o);
   //    axiSpiBvi.ss.i(spiSsIOBuf.o);
   //    axiSpiBvi.io0.i(spiMosiIOBuf.o);
   //    axiSpiBvi.io1.i(spiMisoIOBuf.o);
   // endrule

   // Probe#(Bit#(1)) spi_sck_i_probe <- mkProbe();
   // Probe#(Bit#(1)) spi_sck_o_probe <- mkProbe();
   // Probe#(Bit#(1)) spi_sck_t_probe <- mkProbe();
   // Probe#(Bit#(1)) spi_ss_i_probe <- mkProbe();
   // Probe#(Bit#(1)) spi_ss_o_probe <- mkProbe();
   // Probe#(Bit#(1)) spi_ss_t_probe <- mkProbe();
   // Probe#(Bit#(1)) spi_miso_i_probe <- mkProbe();
   // Probe#(Bit#(1)) spi_miso_o_probe <- mkProbe();
   // Probe#(Bit#(1)) spi_miso_t_probe <- mkProbe();
   // Probe#(Bit#(1)) spi_mosi_i_probe <- mkProbe();
   // Probe#(Bit#(1)) spi_mosi_o_probe <- mkProbe();
   // Probe#(Bit#(1)) spi_mosi_t_probe <- mkProbe();
   // rule rl_spi_trace;
   //    spi_sck_i_probe <= spiSckIOBuf.o;
   //    spi_sck_o_probe <= axiSpiBvi.sck.o;
   //    spi_sck_t_probe <= axiSpiBvi.sck.t;
   //    spi_ss_i_probe <= spiSsIOBuf.o;
   //    spi_ss_o_probe <= axiSpiBvi.ss.o;
   //    spi_ss_t_probe <= axiSpiBvi.ss.t;
   //    spi_miso_i_probe <= spiMisoIOBuf.o;
   //    spi_miso_o_probe <= axiSpiBvi.io1.o;
   //    spi_miso_t_probe <= axiSpiBvi.io1.t;
   //    spi_mosi_i_probe <= spiMosiIOBuf.o;
   //    spi_mosi_o_probe <= axiSpiBvi.io0.o;
   //    spi_mosi_t_probe <= axiSpiBvi.io0.t;
   // endrule

   FIFOF#(Tuple3#(DmaChannel,Bool,MemRequest)) traceFifo <- mkDualClockBramFIFOF(clock, reset, clock, reset);
   FIFOF#(Tuple3#(DmaChannel,Bool,MemRequest)) traceFifo0 <- mkFIFOF();
   FIFOF#(Tuple3#(DmaChannel,Bool,MemRequest)) traceFifo1 <- mkFIFOF();
   PipeIn#(Tuple3#(DmaChannel,Bool,MemRequest)) tracePipe = toPipeIn(traceFifo0);
   FIFOF#(Tuple3#(DmaChannel,Bool,MemData#(DataBusWidth))) traceDataFifo <- mkDualClockBramFIFOF(clock, reset, clock, reset);
   FIFOF#(Tuple3#(DmaChannel,Bool,MemData#(DataBusWidth))) traceDataFifo0 <- mkFIFOF();
   FIFOF#(Tuple3#(DmaChannel,Bool,MemData#(DataBusWidth))) traceDataFifo1 <- mkFIFOF();
   PipeIn#(Tuple3#(DmaChannel,Bool,MemData#(DataBusWidth))) traceDataPipe = toPipeIn(traceDataFifo0);
   let trace0Cnx <- mkConnection(toGet(traceFifo0), toPut(traceFifo));
   let trace1Cnx <- mkConnection(toGet(traceFifo), toPut(traceFifo1));
   rule rl_trace1;
      match { .chan, .write, .req } <- toGet(traceFifo1).get();
      ind.traceDmaRequest(chan, write, truncate(req.sglId), truncate(req.offset), extend(req.burstLen));
   endrule
   let traceData0Cnx <- mkConnection(toGet(traceDataFifo0), toPut(traceDataFifo));
   let traceData1Cnx <- mkConnection(toGet(traceDataFifo), toPut(traceDataFifo1));
   rule rl_trace_data;
      match { .chan, .write, .md } <- toGet(traceDataFifo1).get();
      ind.traceDmaData(chan, write, md.data, md.last);
   endrule

   let traceReadClients <- mapM(uncurry(mkTraceReadClient(tracePipe,traceDataPipe)),
				zip(vec(DMA_TX, DMA_SG),
				    memReadClients));
   let traceWriteClients <- mapM(uncurry(mkTraceWriteClient(tracePipe,traceDataPipe)),
				 zip(vec(DMA_RX, DMA_SG),
				     memWriteClients));

   interface SpikeHwRequest request;
      method Action reset();
	 newReset.assertReset();
      endmethod
      method Action setupDma(Bit#(32) memref);
	 objId <= memref;
      endmethod
      method Action read(Bit#(32) addr);
	 memSlaveMux.read_server.readReq.put(PhysMemRequest { addr: truncate(addr), burstLen: 4, tag: 0 });
      endmethod
      method Action write(Bit#(32) addr, Bit#(32) value);
	 memSlaveMux.write_server.writeReq.put(PhysMemRequest { addr: truncate(addr), burstLen: 4, tag: 0 });
	 dfifo.enq(value);
      endmethod
      method Action setFlashParameters(Bit#(16) cycles);
`ifdef IncludeFlash
	 bpiFlash.setParameters(cycles, False);
`endif
      endmethod
      method Action readFlash(Bit#(32) addr);
`ifdef IncludeFlash
	 bpiFlashSlave.read_server.readReq.put(PhysMemRequest { addr: truncate(addr), burstLen: 2, tag: 0 });
`endif
      endmethod
      method Action writeFlash(Bit#(32) addr, Bit#(32) value);
`ifdef IncludeFlash
	 bpiFlashSlave.write_server.writeReq.put(PhysMemRequest { addr: truncate(addr), burstLen: 2, tag: 0 });
	 flashdfifo.enq(value);
`endif
      endmethod
      method Action status();
	 ind.status(
		    pack(newReset.isAsserted),
`ifdef IncludeEthernet
		    axiEthBvi.mmcm.locked_out(), eth_los,
`else
		    0, eth_los,
`endif

	    axiIntcBvi.irq, intr());
      endmethod
      method Action iicReset(Bit#(1) rst);
	 iicResetReg <= rst;
      endmethod
   endinterface
   interface SpikeHwPins pins;
`ifdef IncludeEthernet
      interface EthPins eth;
	 interface AxiethbviMgt mgt   = axiEthBvi.mgt;
`ifdef EthernetSgmii
	 interface AxiethbviSgmii sgmii = axiEthBvi.sgmii;
`else
	 interface AxiethbviSfp sfp = axiEthBvi.sfp;
`endif
         method Bit#(1) tx_disable();
	    return 0;
	 endmethod
         method Action rx_los(Bit#(1) v);
            eth_los <= v;
	 endmethod
      endinterface
`else
      interface EthPins eth;
         method Bit#(1) tx_disable();
	    return 0;
	 endmethod
         method Action rx_los(Bit#(1) v);
            eth_los <= v;
	 endmethod
      endinterface
`endif
`ifdef IncludeFlash
      interface flash = bpiFlash.flash;
`endif
      interface SpikeUartPins uart;
`ifndef BOARD_miniitx100
	 method tx  = axiUartBvi.sout;
	 method rx  = axiUartBvi.sin;
`endif
`ifdef UART_HAX_RTS_CTS
	 method rts = axiUartBvi.rtsn;
	 method cts = axiUartBvi.ctsn;
`endif
      endinterface
      interface SpikeIicPins iic;
         interface scl = sclIOBuf.io;
         interface sda = sdaIOBuf.io;
	 method mux_reset = iicResetReg;
      endinterface
      // interface SpikeSpiPins spi;
      //    interface sck  = spiSckIOBuf.io;
      //    interface ss   = spiSsIOBuf.io;
      //    interface miso = spiMisoIOBuf.io;
      //    interface mosi = spiMosiIOBuf.io;
      // endinterface
      interface Clock deleteme_unused_clock = clock;
      interface Reset deleteme_unused_reset = reset;
`ifndef BOARD_miniitx100
      interface Clock sfp_rec_clk_p = sfp_rec_clk_buf.p;
      interface Clock sfp_rec_clk_n = sfp_rec_clk_buf.n;
`endif
   endinterface

   interface Vector dmaReadClient = traceReadClients;
   interface Vector dmaWriteClient = traceWriteClients;
endmodule

import BuildVector::*;
import Clocks::*;
import Connectable::*;
import GetPut::*;
import FIFOF::*;
import BRAM::*;
import BRAMFIFO::*;
import Probe::*;
import StmtFSM::*;
import TriState::*;
import Vector::*;
import XilinxCells::*;
import Probe::*;

import ConnectalXilinxCells::*;
import ConnectalBramFifo::*;
import ConnectalConfig::*;
import GetPutWithClocks::*;
import CtrlMux::*;
import HostInterface::*;
import MemTypes::*;
import Pipe::*;
import AxiBits::*;
import PhysMemToBram::*;

import BpiFlash::*;
import AxiIntcBvi::*;
import AxiIic::*;
import AxiSpiBvi::*;
import AxiUart::*;
`ifdef EthernetSgmii
import AxiEthBvi::*;
`else
//import AxiEth1000BaseX::*;
import AxiEthSubsystem::*;
import TriModeMacBvi::*;
import GigEthPcsPmaBvi::*;
import AxiEthBufferBvi::*;
import AxiEth1000BaseX::*; // for interfaces
`endif
import AxiDmaBvi::*;
import SpikeHwPins::*;
import SpikeHwIfc::*;

`include "ConnectalProjectConfig.bsv"

interface SpikeHw;
   interface SpikeHwRequest request;
   interface Vector#(2, MemReadClient#(DataBusWidth)) dmaReadClient;
   interface Vector#(2, MemWriteClient#(DataBusWidth)) dmaWriteClient;
   interface SpikeHwPins pins;
endinterface

typedef 65536 BootRomBytes;
typedef TDiv#(BootRomBytes,4) BootRomEntries;

module mkBramBootRom(Server#(BRAMRequest#(Bit#(TLog#(BootRomEntries)),Bit#(32)),Bit#(32)));
   BRAM_Configure cfg = defaultValue;
   cfg.memorySize = valueOf(BootRomEntries); // 128KB (32K x 4bytes)
   cfg.latency = 2;
   cfg.loadFormat = tagged Hex "bootromx4.hex";

   BRAM1Port#(Bit#(TLog#(BootRomEntries)), Bit#(32)) bram <- mkBRAM1Server(cfg);
   return bram.portA;
endmodule

module mkTraceReadClient#(PipeIn#(Tuple3#(DmaChannel,Bool,MemRequest)) tracePipe,
			  PipeIn#(Tuple3#(DmaChannel,Bool,MemData#(dataWidth))) traceDataPipe,
			  DmaChannel chan,
			  MemReadClient#(dataWidth) m)
   (MemReadClient#(dataWidth));

   let reqFifo  <- mkFIFOF();
   let dataFifo <- mkFIFOF();

   rule rl_req;
      let mr <- m.readReq.get();
      tracePipe.enq(tuple3(chan, False, mr));
      reqFifo.enq(mr);
   endrule

   rule rl_data;
      let md <- toGet(dataFifo).get();
      traceDataPipe.enq(tuple3(chan, False, md));
      m.readData.put(md);
   endrule

   interface Get readReq = toGet(reqFifo);
   interface Put readData = toPut(dataFifo);
endmodule

module mkTraceWriteClient#(PipeIn#(Tuple3#(DmaChannel,Bool,MemRequest)) tracePipe,
			   PipeIn#(Tuple3#(DmaChannel,Bool,MemData#(dataWidth))) traceDataPipe,
			   DmaChannel chan, MemWriteClient#(dataWidth) m)
   (MemWriteClient#(dataWidth));

   let reqFifo <- mkFIFOF();
   let dataFifo <- mkFIFOF();

   rule rl_req;
      let mr <- m.writeReq.get();
      tracePipe.enq(tuple3(chan, True, mr));
      reqFifo.enq(mr);
   endrule

   rule rl_data;
      let md <- m.writeData.get();
      traceDataPipe.enq(tuple3(chan, True, md));
      dataFifo.enq(md);
   endrule

   interface Get writeReq = toGet(reqFifo);
   interface Get writeData = toGet(dataFifo);
   interface Put writeDone = m.writeDone;
endmodule

module mkSpikeHw#(HostInterface host, SpikeHwIndication ind)(SpikeHw);

   let clock <- exposeCurrentClock();
   let reset <- exposeCurrentReset();

   let newReset <- mkReset(10, True, clock);

   BUFRParams bufrParams = defaultValue;
`ifndef BOARD_miniitx100
   bufrParams.bufr_divide = "2";
   Clock clk_125mhz <- mkClockBUFR(bufrParams, clocked_by clock);
`endif
   bufrParams.bufr_divide = "4";
   Clock uartClk <- mkClockBUFR(bufrParams, clocked_by host.derivedClock);

   let bootRom    <- mkBramBootRom();
`ifdef IncludeFlash
   let bpiFlash   <- mkBpiFlash();
`endif
   let axiIntcBvi <- mkAxiIntcBvi(clock, newReset.new_rst);
   let axiIicBvi  <- mkAxiIicBvi(clock, newReset.new_rst);
//   let axiSpiBvi  <- mkAxiSpiBvi(clock, clock, newReset.new_rst);
   let axiUartBvi <- mkAxiUartBvi(clock, newReset.new_rst, uartClk);
`ifdef IncludeEthernet
//   let axiEthBvi <- mkAxiEthBvi(clock, host.tsys_clk_200mhz_buf, clock,
//				newReset.new_rst, newReset.new_rst, newReset.new_rst, newReset.new_rst, newReset.new_rst);
   let axiEthBvi <- AxiEthSubsystem::mkAxiEthBvi(clock, host.tsys_clk_200mhz_buf, reset_by newReset.new_rst);

`endif

   Reg#(Bit#(32)) objId <- mkReg(0);
   Reg#(Bit#(1))  iicResetReg <- mkReg(0);
   Reg#(Bit#(1))  eth_los <- mkReg(0);

   let irqLevel <- mkReg(0);
   let intrLevel <- mkReg(0);

   function Bit#(16) intr();
      Bit#(16) _intr = 0;
      _intr[0] = axiUartBvi.ip2intc_irpt();
      _intr[1] = axiEthBvi.s2mm_dma.introut(); // rx
      _intr[2] = axiEthBvi.mm2s_dma.introut(); // tx
`ifdef IncludeEthernet
      _intr[3] = axiEthBvi.mac.irq();
//      _intr[4] = axiEthBvi.interrupt();
`endif
      _intr[5] = axiIicBvi.iic2intc_irpt();
//      _intr[6] = axiSpiBvi.ip2intc_irpt();
      return _intr;
   endfunction

   rule rl_intr;

      axiIntcBvi.intr(intr());
   endrule

   FIFOF#(Tuple2#(Bit#(1),Bit#(16))) irqChangeFifo <- mkSizedFIFOF(8);
   rule rl_irq_levels_changed;
      let irq = axiIntcBvi.irq;
      let levels = intr();

      if (irq != irqLevel) begin
	 $display("irq changed irq=%h intr sources %h", irq, levels);
	 irqLevel <= irq;
	 intrLevel <= levels;
	 irqChangeFifo.enq(tuple2(irq, levels));
      end
   endrule

   rule rl_intr_indication;
      match { .irq, .levels } <- toGet(irqChangeFifo).get();
      ind.irqChanged(irq, levels);
   endrule

   Reg#(Bit#(32)) cycles <- mkReg(0);
   Reg#(Bool)     mmcm_lock <- mkReg(False);
   rule rl_cycles;
      cycles <= cycles+1;
   endrule

   FIFOF#(BRAMRequest#(Bit#(32),Bit#(32))) reqFifo <- mkSizedFIFOF(4);
   FIFOF#(Bit#(32))                       dataFifo <- mkSizedFIFOF(16);

   Axi4MasterBits#(32,DataBusWidth,MemTagSize,Empty) m_axi_mm2s = toAxi4MasterBits(axiEthBvi.m_axi_mm2s);
   Axi4MasterBits#(32,DataBusWidth,MemTagSize,Empty) m_axi_s2mm = toAxi4MasterBits(axiEthBvi.m_axi_s2mm);
   Axi4MasterBits#(32,DataBusWidth,MemTagSize,Empty) m_axi_sg = toAxi4MasterBits(axiEthBvi.m_axi_sg);

   Axi4SlaveLiteBits#(12,32) axiUartSlaveLite = toAxi4SlaveBits(axiUartBvi.s_axi);
   PhysMemSlave#(12,32) axiUartMemSlave      <- mkPhysMemSlave(axiUartSlaveLite);

   Axi4SlaveLiteBits#(9,32) axiIntcSlaveLite = toAxi4SlaveBits(axiIntcBvi.s_axi);
   PhysMemSlave#(12,32) axiIntcMemSlave      <- mkPhysMemSlave(axiIntcSlaveLite);

   Axi4SlaveLiteBits#(9,32) axiIicSlaveLite  = toAxi4SlaveBits(axiIicBvi.s_axi);
   PhysMemSlave#(12,32) axiIicMemSlave       <- mkPhysMemSlave(axiIicSlaveLite);

//   Axi4SlaveLiteBits#(7,32) axiSpiSlaveLite  = toAxi4SlaveBits(axiSpiBvi.s_axi);
//   PhysMemSlave#(12,32) axiSpiMemSlave       <- mkPhysMemSlave(axiSpiSlaveLite);

`ifdef IncludeEthernet
   PhysMemSlave#(12,32) axiDmaMemSlave       <- mkPhysMemSlave(axiEthBvi.s_axi_dma);

   Axi4SlaveLiteBits#(12,32) axiEthSlaveLite = toAxi4SlaveBits(axiEthBvi.s_axi_mac);
   PhysMemSlave#(12,32) axiEthMemSlave       <- mkPhysMemSlave(axiEthSlaveLite);
   PhysMemSlave#(20,32) deviceSlaveMux       <- mkPhysMemSlaveMux(vec(axiUartMemSlave, axiIntcMemSlave, axiIicMemSlave,
								      axiDmaMemSlave, axiEthMemSlave)); // , axiSpiMemSlave
`else
   PhysMemSlave#(20,32) deviceSlaveMux       <- mkPhysMemSlaveMux(vec(axiUartMemSlave, axiIntcMemSlave, axiIicMemSlave));
`endif

   PhysMemSlave#(20,32) bootRomMemSlave      <- mkPhysMemToBram(bootRom);
   PhysMemSlave#(21,32) memSlaveMux          <- mkPhysMemSlaveMux(vec(bootRomMemSlave, deviceSlaveMux));

   let memReadClients  <- mapM(mkMemReadClient(objId), vec(m_axi_mm2s, m_axi_sg));
   let memWriteClients <- mapM(mkMemWriteClient(objId), vec(m_axi_s2mm, m_axi_sg));

`ifdef IncludeFlash
   PhysMemSlave#(26,16) bpiFlashSlave <- mkPhysMemToBram(bpiFlash.server);
`endif
   FIFOF#(Bit#(32)) dfifo <- mkFIFOF();
   FIFOF#(Bit#(32)) flashdfifo <- mkFIFOF();

`ifdef IncludeEthernet
   rule rl_axieth;
      axiEthBvi.signal.detect(1); // drive to 1 if not using optical transceiver, else use signal from transceiver
   endrule
`endif

   rule rl_rdata;
      let rdata <- memSlaveMux.read_server.readData.get();
      ind.readDone(rdata.data);
   endrule

   rule rl_wdata;
      let wdata <- toGet(dfifo).get();
       memSlaveMux.write_server.writeData.put(MemData {data: wdata, tag: 0, last: True});
   endrule

   rule rl_writeDone;
      let tag <- memSlaveMux.write_server.writeDone.get();
      ind.writeDone();
   endrule

   rule rl_bpiflash_rdata;
`ifdef IncludeFlash
      let rdata <- bpiFlashSlave.read_server.readData.get();
      ind.readFlashDone(extend(rdata.data));
`endif
   endrule

   rule rl_bpiflash_wdata;
`ifdef IncludeFlash
      let wdata <- toGet(flashdfifo).get();
       bpiFlashSlave.write_server.writeData.put(MemData {data: truncate(wdata), tag: 0, last: True});
`endif
   endrule

   rule rl_bpiflash_writeDone;
`ifdef IncludeFlash
      let tag <- bpiFlashSlave.write_server.writeDone.get();
      ind.writeFlashDone();
`endif
   endrule

`ifndef BOARD_miniitx100
   DiffClock sfp_rec_clk_buf <- mkClockOBUFDS(defaultValue, clocked_by clk_125mhz);
`endif
   IOBUF sdaIOBuf <- mkIOBUF(axiIicBvi.sda.t, axiIicBvi.sda.o);
   IOBUF sclIOBuf <- mkIOBUF(axiIicBvi.scl.t, axiIicBvi.scl.o);
   // No probe for .o because they are tied to ground -- I2C operates open collector
   Probe#(Bit#(1)) sda_i_probe <- mkProbe();
   Probe#(Bit#(1)) sda_t_probe <- mkProbe();
   Probe#(Bit#(1)) scl_i_probe <- mkProbe();
   Probe#(Bit#(1)) scl_t_probe <- mkProbe();

   rule iic_o;
      sda_i_probe <= sdaIOBuf.o;
      sda_t_probe <= axiIicBvi.sda.t;
      scl_i_probe <= sclIOBuf.o;
      scl_t_probe <= axiIicBvi.scl.t;

      axiIicBvi.sda.i(sdaIOBuf.o);
      axiIicBvi.scl.i(sclIOBuf.o);
   endrule

   // IOBUF spiSckIOBuf  <- mkIOBUF(axiSpiBvi.sck.t, axiSpiBvi.sck.o);
   // IOBUF spiSsIOBuf   <- mkIOBUF(axiSpiBvi.ss.t, axiSpiBvi.ss.o);
   // IOBUF spiMosiIOBuf <- mkIOBUF(axiSpiBvi.io0.t, axiSpiBvi.io0.o);
   // IOBUF spiMisoIOBuf <- mkIOBUF(axiSpiBvi.io1.t, axiSpiBvi.io1.o);
   // rule spi_o;
   //    axiSpiBvi.sck.i(spiSckIOBuf.o);
   //    axiSpiBvi.ss.i(spiSsIOBuf.o);
   //    axiSpiBvi.io0.i(spiMosiIOBuf.o);
   //    axiSpiBvi.io1.i(spiMisoIOBuf.o);
   // endrule

   // Probe#(Bit#(1)) spi_sck_i_probe <- mkProbe();
   // Probe#(Bit#(1)) spi_sck_o_probe <- mkProbe();
   // Probe#(Bit#(1)) spi_sck_t_probe <- mkProbe();
   // Probe#(Bit#(1)) spi_ss_i_probe <- mkProbe();
   // Probe#(Bit#(1)) spi_ss_o_probe <- mkProbe();
   // Probe#(Bit#(1)) spi_ss_t_probe <- mkProbe();
   // Probe#(Bit#(1)) spi_miso_i_probe <- mkProbe();
   // Probe#(Bit#(1)) spi_miso_o_probe <- mkProbe();
   // Probe#(Bit#(1)) spi_miso_t_probe <- mkProbe();
   // Probe#(Bit#(1)) spi_mosi_i_probe <- mkProbe();
   // Probe#(Bit#(1)) spi_mosi_o_probe <- mkProbe();
   // Probe#(Bit#(1)) spi_mosi_t_probe <- mkProbe();
   // rule rl_spi_trace;
   //    spi_sck_i_probe <= spiSckIOBuf.o;
   //    spi_sck_o_probe <= axiSpiBvi.sck.o;
   //    spi_sck_t_probe <= axiSpiBvi.sck.t;
   //    spi_ss_i_probe <= spiSsIOBuf.o;
   //    spi_ss_o_probe <= axiSpiBvi.ss.o;
   //    spi_ss_t_probe <= axiSpiBvi.ss.t;
   //    spi_miso_i_probe <= spiMisoIOBuf.o;
   //    spi_miso_o_probe <= axiSpiBvi.io1.o;
   //    spi_miso_t_probe <= axiSpiBvi.io1.t;
   //    spi_mosi_i_probe <= spiMosiIOBuf.o;
   //    spi_mosi_o_probe <= axiSpiBvi.io0.o;
   //    spi_mosi_t_probe <= axiSpiBvi.io0.t;
   // endrule

   FIFOF#(Tuple3#(DmaChannel,Bool,MemRequest)) traceFifo <- mkDualClockBramFIFOF(clock, reset, clock, reset);
   FIFOF#(Tuple3#(DmaChannel,Bool,MemRequest)) traceFifo0 <- mkFIFOF();
   FIFOF#(Tuple3#(DmaChannel,Bool,MemRequest)) traceFifo1 <- mkFIFOF();
   PipeIn#(Tuple3#(DmaChannel,Bool,MemRequest)) tracePipe = toPipeIn(traceFifo0);
   FIFOF#(Tuple3#(DmaChannel,Bool,MemData#(DataBusWidth))) traceDataFifo <- mkDualClockBramFIFOF(clock, reset, clock, reset);
   FIFOF#(Tuple3#(DmaChannel,Bool,MemData#(DataBusWidth))) traceDataFifo0 <- mkFIFOF();
   FIFOF#(Tuple3#(DmaChannel,Bool,MemData#(DataBusWidth))) traceDataFifo1 <- mkFIFOF();
   PipeIn#(Tuple3#(DmaChannel,Bool,MemData#(DataBusWidth))) traceDataPipe = toPipeIn(traceDataFifo0);
   let trace0Cnx <- mkConnection(toGet(traceFifo0), toPut(traceFifo));
   let trace1Cnx <- mkConnection(toGet(traceFifo), toPut(traceFifo1));
   rule rl_trace1;
      match { .chan, .write, .req } <- toGet(traceFifo1).get();
      ind.traceDmaRequest(chan, write, truncate(req.sglId), truncate(req.offset), extend(req.burstLen));
   endrule
   let traceData0Cnx <- mkConnection(toGet(traceDataFifo0), toPut(traceDataFifo));
   let traceData1Cnx <- mkConnection(toGet(traceDataFifo), toPut(traceDataFifo1));
   rule rl_trace_data;
      match { .chan, .write, .md } <- toGet(traceDataFifo1).get();
      ind.traceDmaData(chan, write, md.data, md.last);
   endrule

   let traceReadClients <- mapM(uncurry(mkTraceReadClient(tracePipe,traceDataPipe)),
				zip(vec(DMA_TX, DMA_SG),
				    memReadClients));
   let traceWriteClients <- mapM(uncurry(mkTraceWriteClient(tracePipe,traceDataPipe)),
				 zip(vec(DMA_RX, DMA_SG),
				     memWriteClients));

   interface SpikeHwRequest request;
      method Action reset();
	 newReset.assertReset();
      endmethod
      method Action setupDma(Bit#(32) memref);
	 objId <= memref;
      endmethod
      method Action read(Bit#(32) addr);
	 memSlaveMux.read_server.readReq.put(PhysMemRequest { addr: truncate(addr), burstLen: 4, tag: 0 });
      endmethod
      method Action write(Bit#(32) addr, Bit#(32) value);
	 memSlaveMux.write_server.writeReq.put(PhysMemRequest { addr: truncate(addr), burstLen: 4, tag: 0 });
	 dfifo.enq(value);
      endmethod
      method Action setFlashParameters(Bit#(16) cycles);
`ifdef IncludeFlash
	 bpiFlash.setParameters(cycles, False);
`endif
      endmethod
      method Action readFlash(Bit#(32) addr);
`ifdef IncludeFlash
	 bpiFlashSlave.read_server.readReq.put(PhysMemRequest { addr: truncate(addr), burstLen: 2, tag: 0 });
`endif
      endmethod
      method Action writeFlash(Bit#(32) addr, Bit#(32) value);
`ifdef IncludeFlash
	 bpiFlashSlave.write_server.writeReq.put(PhysMemRequest { addr: truncate(addr), burstLen: 2, tag: 0 });
	 flashdfifo.enq(value);
`endif
      endmethod
      method Action status();
	 ind.status(
		    pack(newReset.isAsserted),
`ifdef IncludeEthernet
		    axiEthBvi.mmcm.locked_out(), eth_los,
`else
		    0, eth_los,
`endif

	    axiIntcBvi.irq, intr());
      endmethod
      method Action iicReset(Bit#(1) rst);
	 iicResetReg <= rst;
      endmethod
   endinterface
   interface SpikeHwPins pins;
`ifdef IncludeEthernet
      interface EthPins eth;
	 interface AxiethbviMgt mgt   = axiEthBvi.mgt;
`ifdef EthernetSgmii
	 interface AxiethbviSgmii sgmii = axiEthBvi.sgmii;
`else
	 interface AxiethbviSfp sfp = axiEthBvi.sfp;
`endif
         method Bit#(1) tx_disable();
	    return 0;
	 endmethod
         method Action rx_los(Bit#(1) v);
            eth_los <= v;
	 endmethod
      endinterface
`else
      interface EthPins eth;
         method Bit#(1) tx_disable();
	    return 0;
	 endmethod
         method Action rx_los(Bit#(1) v);
            eth_los <= v;
	 endmethod
      endinterface
`endif
`ifdef IncludeFlash
      interface flash = bpiFlash.flash;
`endif
      interface SpikeUartPins uart;
`ifndef BOARD_miniitx100
	 method tx  = axiUartBvi.sout;
	 method rx  = axiUartBvi.sin;
`endif
`ifdef UART_HAX_RTS_CTS
	 method rts = axiUartBvi.rtsn;
	 method cts = axiUartBvi.ctsn;
`endif
      endinterface
      interface SpikeIicPins iic;
         interface scl = sclIOBuf.io;
         interface sda = sdaIOBuf.io;
	 method mux_reset = iicResetReg;
      endinterface
      // interface SpikeSpiPins spi;
      //    interface sck  = spiSckIOBuf.io;
      //    interface ss   = spiSsIOBuf.io;
      //    interface miso = spiMisoIOBuf.io;
      //    interface mosi = spiMosiIOBuf.io;
      // endinterface
      interface Clock deleteme_unused_clock = clock;
      interface Reset deleteme_unused_reset = reset;
`ifndef BOARD_miniitx100
      interface Clock sfp_rec_clk_p = sfp_rec_clk_buf.p;
      interface Clock sfp_rec_clk_n = sfp_rec_clk_buf.n;
`endif
   endinterface

   interface Vector dmaReadClient = traceReadClients;
   interface Vector dmaWriteClient = traceWriteClients;
endmodule


p value available 5 cycles after input

p value available 5 cycles after input

import Clocks::*;

interface Dsp48E1;
   method Bit#(48) p();
// Control: 4-bit (each) input: Control Inputs/Status Bits
   method Action alumode(Bit#(4) v);		// 4-bit input: ALU control input
   method Action carryinsel(Bit#(3) v);		// 3-bit input: Carry select input
   method Action inmode(Bit#(5) v);		// 5-bit input: INMODE control input
   method Action opmode(Bit#(7) v);		// 7-bit input: Operation mode input
   method Action a(Bit#(30) v);
   method Action b(Bit#(18) v);
   method Action c(Bit#(48) v);
   method Action d(Bit#(25) v);
   method Action last(Bit#(1) v);
endinterface

(* always_ready, always_enabled *)
interface PRIM_DSP48E1;
   method Bit#(48) p();
// Control: 4-bit (each) input: Control Inputs/Status Bits
   method Action alumode(Bit#(4) v);		// 4-bit input: ALU control input
   method Action carryinsel(Bit#(3) v);		// 3-bit input: Carry select input
   method Action inmode(Bit#(5) v);		// 5-bit input: INMODE control input
   method Action opmode(Bit#(7) v);		// 7-bit input: Operation mode input
   method Action a(Bit#(30) v);
   method Action b(Bit#(18) v);
   method Action c(Bit#(48) v);
   method Action d(Bit#(25) v);
   method Action acin(Bit#(30) v);
   method Action bcin(Bit#(18) v);
   method Action carrycascin(Bit#(1) v);
   method Action carryin(Bit#(1) v);
   method Action multsignin(Bit#(1) v);
   method Action pcin(Bit#(48) v);

   method Action cea1(Bit#(1) en);		// 1-bit input: Clock enable input for 1st stage AREG
   method Action cea2(Bit#(1) en);		// 1-bit input: Clock enable input for 2nd stage AREG
   method Action cead(Bit#(1) en);		// 1-bit input: Clock enable input for ADREG
   method Action ceb1(Bit#(1) en);		// 1-bit input: Clock enable input for 1st stage BREG
   method Action ceb2(Bit#(1) en);		// 1-bit input: Clock enable input for 2nd stage BREG
   method Action cealumode(Bit#(1) en);		// 1-bit input: Clock enable input for ALUMODE
   method Action cec(Bit#(1) en);		// 1-bit input: Clock enable input for CREG
   method Action cecarryin(Bit#(1) en);		// 1-bit input: Clock enable input for CARRYINREG
   method Action cectrl(Bit#(1) en);		// 1-bit input: Clock enable input for OPMODEREG and CARRYINSELREG
   method Action ced(Bit#(1) en);		// 1-bit input: Clock enable input for DREG
   method Action ceinmode(Bit#(1) en);		// 1-bit input: Clock enable input for INMODEREG
   method Action cem(Bit#(1) en);		// 1-bit input: Clock enable input for MREG
   method Action cep(Bit#(1) en);		// 1-bit input: Clock enable input for PREG
endinterface

import "BVI" DSP48E1 =
module vmkDSP48E1(PRIM_DSP48E1);
   let currentReset <- exposeCurrentReset;
   let invertedReset <- mkResetInverter(currentReset);
   default_clock clk(CLK);

   default_reset rsta(RSTA) = invertedReset;
   input_reset rstb(RSTB) = invertedReset;
   input_reset rstc(RSTC) = invertedReset;
   input_reset rstd(RSTD) = invertedReset;
   input_reset rstallcarryin(RSTALLCARRYIN) = invertedReset;
   input_reset rstalumode(RSTALUMODE) = invertedReset;
   input_reset rstctrl(RSTCTRL) = invertedReset;
   input_reset rstinmode(RSTINMODE) = invertedReset;
   input_reset rstm(RSTM) = invertedReset;
   input_reset rstp(RSTP) = invertedReset;

   method P p();
   method alumode(ALUMODE) enable ((*inhigh*)EN_alumode);
   method carryinsel(CARRYINSEL) enable ((*inhigh*)EN_carryinsel);
   method inmode(INMODE) enable ((*inhigh*)EN_inmode);
   method opmode(OPMODE) enable ((*inhigh*)EN_opmode);
   method a(A) enable ((*inhigh*)EN_a);
   method b(B) enable ((*inhigh*)EN_b);
   method c(C) enable ((*inhigh*)EN_c);
   method d(D) enable ((*inhigh*)EN_d);
   method acin(ACIN) enable ((*inhigh*)EN_acin);
   method bcin(BCIN) enable ((*inhigh*)EN_bcin);
   method carrycascin(CARRYCASCIN) enable ((*inhigh*)EN_carrycascin);
   method carryin(CARRYIN) enable ((*inhigh*)EN_carryin);
   method multsignin(MULTSIGNIN) enable ((*inhigh*)EN_multsignin);
   method pcin(PCIN) enable ((*inhigh*)EN_pcin);

   method cea1(CEA1) enable ((*inhigh*)EN_cea1);
   method cea2(CEA2) enable ((*inhigh*)EN_cea2);
   method cead(CEAD) enable ((*inhigh*)EN_cead);
   method ceb1(CEB1) enable ((*inhigh*)EN_ceb1);
   method ceb2(CEB2) enable ((*inhigh*)EN_ceb2);
   method cealumode(CEALUMODE) enable ((*inhigh*)EN_cealumode);
   method cec(CEC) enable ((*inhigh*)EN_cec);
   method cecarryin(CECARRYIN) enable ((*inhigh*)EN_cecarryin);
   method cectrl(CECTRL) enable ((*inhigh*)EN_cectrl);
   method ced(CED) enable ((*inhigh*)EN_ced);
   method ceinmode(CEINMODE) enable ((*inhigh*)EN_ceinmode);
   method cem(CEM) enable ((*inhigh*)EN_cem);
   method cep(CEP) enable ((*inhigh*)EN_cep);
   schedule (alumode,carryinsel,inmode,opmode,a,b,c,d,acin,bcin,carrycascin,carryin,multsignin,pcin,cea1,cea2,cead,ceb1,ceb2,cealumode,cec,cecarryin,cectrl,ced,ceinmode,cem,cep,p)
      CF (alumode,carryinsel,inmode,opmode,a,b,c,d,acin,bcin,carrycascin,carryin,multsignin,pcin,cea1,cea2,cead,ceb1,ceb2,cealumode,cec,cecarryin,cectrl,ced,ceinmode,cem,cep,p);
endmodule

(* synthesize *)
module mkDsp48E1(Dsp48E1);
   let dsp <- vmkDSP48E1();
   let defaultReset <- exposeCurrentReset;
   let optionalReset = defaultReset; // noReset
   Wire#(Bit#(4)) alumodeWire <- mkDWire(0);
   Reg#(Bit#(4)) alumodeReg <- mkReg(0);
   Wire#(Bit#(3)) carryinselWire <- mkDWire(0);
   Wire#(Bit#(5)) inmodeWire <- mkDWire(0);
   Wire#(Bit#(7)) opmodeWire <- mkDWire(7'h35);
   Reg#(Bit#(7)) opmodeReg <- mkReg(7'h35);

   Wire#(Bit#(30)) aWire <- mkDWire(0);
   Wire#(Bit#(18)) bWire <- mkDWire(0);
   Wire#(Bit#(48)) cWire <- mkDWire(0);
   Wire#(Bit#(25)) dWire <- mkDWire(0);

   Wire#(Bit#(1)) ce1Wire <- mkDWire(0);
   Reg#(Bit#(1)) ce2Reg <- mkReg(0, reset_by optionalReset);
   Reg#(Bit#(1)) cepReg <- mkReg(0, reset_by optionalReset);
   Wire#(Bit#(1)) last1Wire <- mkDWire(0);
   Reg#(Bit#(1))  last2Reg  <- mkReg(0, reset_by optionalReset);
   Reg#(Bit#(1))  last3Reg  <- mkReg(0, reset_by optionalReset);
   Reg#(Bit#(1))  last4Reg  <- mkReg(0, reset_by optionalReset);
   Reg#(Bit#(1))  last5Reg  <- mkReg(0, reset_by optionalReset);
   Reg#(Bit#(1))  last6Reg  <- mkReg(0, reset_by optionalReset);

   rule clock_enable_and_reset;
      ce2Reg <= ce1Wire;
      cepReg <= ce2Reg;

      last2Reg <= last1Wire;
      last3Reg <= last2Reg;
      last4Reg <= last3Reg;
      last5Reg <= last4Reg;
      last6Reg <= last5Reg;

      dsp.cea1(1); // (ce1Wire);
      dsp.cea2(1); // (ce2Reg);
      dsp.cead(1);
      dsp.ceb1(1); // (ce1Wire);
      dsp.ceb2(1); // (ce2Reg);
      dsp.cealumode(1); // (ce1Wire);
      dsp.cec(1);
      dsp.cecarryin(1);
      dsp.cectrl(1);
      dsp.ced(1);
      dsp.ceinmode(1);
      dsp.cem(1);
      dsp.cep(1); // (cepReg);

   endrule

   rule driveInputs;
      opmodeReg <= opmodeWire;
      alumodeReg <= alumodeWire;

      dsp.alumode(alumodeReg);
      dsp.carryinsel(carryinselWire);
      dsp.inmode(inmodeWire);
      dsp.opmode(opmodeReg);
      //dsp.a(aWire);
      //dsp.b(bWire);
      //dsp.c(cWire);
      //dsp.d(dWire);

      dsp.acin(0);
      dsp.bcin(0);
      dsp.carrycascin(0);
      dsp.carryin(0);
      dsp.pcin(0);
   endrule

   method Action alumode(Bit#(4) v);
      alumodeWire <= v;
   endmethod
   method Action carryinsel(Bit#(3) v);
      carryinselWire <= v;
   endmethod
   method Action inmode(Bit#(5) v);
      inmodeWire <= v;
   endmethod
   method Action opmode(Bit#(7) v);
      opmodeWire <= v;
   endmethod
   method Action a(Bit#(30) v);
      ce1Wire <= 1;
      dsp.a(v);
   endmethod
   method Action b(Bit#(18) v);
      dsp.b(v);
   endmethod
   method Action c(Bit#(48) v);
      dsp.c(v);
   endmethod
   method Action d(Bit#(25) v);
      dsp.d(v);
   endmethod
   method Bit#(48) p() if (last6Reg == 1);
      return dsp.p();
   endmethod
   method Action last(Bit#(1) v);
      last1Wire <= v;
   endmethod
endmodule

import Clocks::*;

interface Dsp48E1;
   method Bit#(48) p();
// Control: 4-bit (each) input: Control Inputs/Status Bits
   method Action alumode(Bit#(4) v);		// 4-bit input: ALU control input
   method Action carryinsel(Bit#(3) v);		// 3-bit input: Carry select input
   method Action inmode(Bit#(5) v);		// 5-bit input: INMODE control input
   method Action opmode(Bit#(7) v);		// 7-bit input: Operation mode input
   method Action a(Bit#(30) v);
   method Action b(Bit#(18) v);
   method Action c(Bit#(48) v);
   method Action d(Bit#(25) v);
   method Action last(Bit#(1) v);
endinterface

(* always_ready, always_enabled *)
interface PRIM_DSP48E1;
   method Bit#(48) p();
// Control: 4-bit (each) input: Control Inputs/Status Bits
   method Action alumode(Bit#(4) v);		// 4-bit input: ALU control input
   method Action carryinsel(Bit#(3) v);		// 3-bit input: Carry select input
   method Action inmode(Bit#(5) v);		// 5-bit input: INMODE control input
   method Action opmode(Bit#(7) v);		// 7-bit input: Operation mode input
   method Action a(Bit#(30) v);
   method Action b(Bit#(18) v);
   method Action c(Bit#(48) v);
   method Action d(Bit#(25) v);
   method Action acin(Bit#(30) v);
   method Action bcin(Bit#(18) v);
   method Action carrycascin(Bit#(1) v);
   method Action carryin(Bit#(1) v);
   method Action multsignin(Bit#(1) v);
   method Action pcin(Bit#(48) v);

   method Action cea1(Bit#(1) en);		// 1-bit input: Clock enable input for 1st stage AREG
   method Action cea2(Bit#(1) en);		// 1-bit input: Clock enable input for 2nd stage AREG
   method Action cead(Bit#(1) en);		// 1-bit input: Clock enable input for ADREG
   method Action ceb1(Bit#(1) en);		// 1-bit input: Clock enable input for 1st stage BREG
   method Action ceb2(Bit#(1) en);		// 1-bit input: Clock enable input for 2nd stage BREG
   method Action cealumode(Bit#(1) en);		// 1-bit input: Clock enable input for ALUMODE
   method Action cec(Bit#(1) en);		// 1-bit input: Clock enable input for CREG
   method Action cecarryin(Bit#(1) en);		// 1-bit input: Clock enable input for CARRYINREG
   method Action cectrl(Bit#(1) en);		// 1-bit input: Clock enable input for OPMODEREG and CARRYINSELREG
   method Action ced(Bit#(1) en);		// 1-bit input: Clock enable input for DREG
   method Action ceinmode(Bit#(1) en);		// 1-bit input: Clock enable input for INMODEREG
   method Action cem(Bit#(1) en);		// 1-bit input: Clock enable input for MREG
   method Action cep(Bit#(1) en);		// 1-bit input: Clock enable input for PREG
endinterface

import "BVI" DSP48E1 =
module vmkDSP48E1(PRIM_DSP48E1);
   let currentReset <- exposeCurrentReset;
   let invertedReset <- mkResetInverter(currentReset);
   default_clock clk(CLK);

   default_reset rsta(RSTA) = invertedReset;
   input_reset rstb(RSTB) = invertedReset;
   input_reset rstc(RSTC) = invertedReset;
   input_reset rstd(RSTD) = invertedReset;
   input_reset rstallcarryin(RSTALLCARRYIN) = invertedReset;
   input_reset rstalumode(RSTALUMODE) = invertedReset;
   input_reset rstctrl(RSTCTRL) = invertedReset;
   input_reset rstinmode(RSTINMODE) = invertedReset;
   input_reset rstm(RSTM) = invertedReset;
   input_reset rstp(RSTP) = invertedReset;

   method P p();
   method alumode(ALUMODE) enable ((*inhigh*)EN_alumode);
   method carryinsel(CARRYINSEL) enable ((*inhigh*)EN_carryinsel);
   method inmode(INMODE) enable ((*inhigh*)EN_inmode);
   method opmode(OPMODE) enable ((*inhigh*)EN_opmode);
   method a(A) enable ((*inhigh*)EN_a);
   method b(B) enable ((*inhigh*)EN_b);
   method c(C) enable ((*inhigh*)EN_c);
   method d(D) enable ((*inhigh*)EN_d);
   method acin(ACIN) enable ((*inhigh*)EN_acin);
   method bcin(BCIN) enable ((*inhigh*)EN_bcin);
   method carrycascin(CARRYCASCIN) enable ((*inhigh*)EN_carrycascin);
   method carryin(CARRYIN) enable ((*inhigh*)EN_carryin);
   method multsignin(MULTSIGNIN) enable ((*inhigh*)EN_multsignin);
   method pcin(PCIN) enable ((*inhigh*)EN_pcin);

   method cea1(CEA1) enable ((*inhigh*)EN_cea1);
   method cea2(CEA2) enable ((*inhigh*)EN_cea2);
   method cead(CEAD) enable ((*inhigh*)EN_cead);
   method ceb1(CEB1) enable ((*inhigh*)EN_ceb1);
   method ceb2(CEB2) enable ((*inhigh*)EN_ceb2);
   method cealumode(CEALUMODE) enable ((*inhigh*)EN_cealumode);
   method cec(CEC) enable ((*inhigh*)EN_cec);
   method cecarryin(CECARRYIN) enable ((*inhigh*)EN_cecarryin);
   method cectrl(CECTRL) enable ((*inhigh*)EN_cectrl);
   method ced(CED) enable ((*inhigh*)EN_ced);
   method ceinmode(CEINMODE) enable ((*inhigh*)EN_ceinmode);
   method cem(CEM) enable ((*inhigh*)EN_cem);
   method cep(CEP) enable ((*inhigh*)EN_cep);
   schedule (alumode,carryinsel,inmode,opmode,a,b,c,d,acin,bcin,carrycascin,carryin,multsignin,pcin,cea1,cea2,cead,ceb1,ceb2,cealumode,cec,cecarryin,cectrl,ced,ceinmode,cem,cep,p)
      CF (alumode,carryinsel,inmode,opmode,a,b,c,d,acin,bcin,carrycascin,carryin,multsignin,pcin,cea1,cea2,cead,ceb1,ceb2,cealumode,cec,cecarryin,cectrl,ced,ceinmode,cem,cep,p);
endmodule

(* synthesize *)
module mkDsp48E1(Dsp48E1);
   let dsp <- vmkDSP48E1();
   let defaultReset <- exposeCurrentReset;
   let optionalReset = defaultReset; // noReset
   Wire#(Bit#(4)) alumodeWire <- mkDWire(0);
   Reg#(Bit#(4)) alumodeReg <- mkReg(0);
   Wire#(Bit#(3)) carryinselWire <- mkDWire(0);
   Wire#(Bit#(5)) inmodeWire <- mkDWire(0);
   Wire#(Bit#(7)) opmodeWire <- mkDWire(7'h35);
   Reg#(Bit#(7)) opmodeReg <- mkReg(7'h35);

   Wire#(Bit#(30)) aWire <- mkDWire(0);
   Wire#(Bit#(18)) bWire <- mkDWire(0);
   Wire#(Bit#(48)) cWire <- mkDWire(0);
   Wire#(Bit#(25)) dWire <- mkDWire(0);

   Wire#(Bit#(1)) ce1Wire <- mkDWire(0);
   Reg#(Bit#(1)) ce2Reg <- mkReg(0, reset_by optionalReset);
   Reg#(Bit#(1)) cepReg <- mkReg(0, reset_by optionalReset);
   Wire#(Bit#(1)) last1Wire <- mkDWire(0);
   Reg#(Bit#(1))  last2Reg  <- mkReg(0, reset_by optionalReset);
   Reg#(Bit#(1))  last3Reg  <- mkReg(0, reset_by optionalReset);
   Reg#(Bit#(1))  last4Reg  <- mkReg(0, reset_by optionalReset);

   rule clock_enable_and_reset;
      ce2Reg <= ce1Wire;
      cepReg <= ce2Reg;

      last2Reg <= last1Wire;
      last3Reg <= last2Reg;
      last4Reg <= last3Reg;

      dsp.cea1(1); // (ce1Wire);
      dsp.cea2(1); // (ce2Reg);
      dsp.cead(1);
      dsp.ceb1(1); // (ce1Wire);
      dsp.ceb2(1); // (ce2Reg);
      dsp.cealumode(1); // (ce1Wire);
      dsp.cec(1);
      dsp.cecarryin(1);
      dsp.cectrl(1);
      dsp.ced(1);
      dsp.ceinmode(1);
      dsp.cem(1);
      dsp.cep(1); // (cepReg);

   endrule

   rule driveInputs;
      opmodeReg <= opmodeWire;
      alumodeReg <= alumodeWire;

      dsp.alumode(alumodeReg);
      dsp.carryinsel(carryinselWire);
      dsp.inmode(inmodeWire);
      dsp.opmode(opmodeReg);
      //dsp.a(aWire);
      //dsp.b(bWire);
      //dsp.c(cWire);
      //dsp.d(dWire);

      dsp.acin(0);
      dsp.bcin(0);
      dsp.carrycascin(0);
      dsp.carryin(0);
      dsp.pcin(0);
   endrule

   method Action alumode(Bit#(4) v);
      alumodeWire <= v;
   endmethod
   method Action carryinsel(Bit#(3) v);
      carryinselWire <= v;
   endmethod
   method Action inmode(Bit#(5) v);
      inmodeWire <= v;
   endmethod
   method Action opmode(Bit#(7) v);
      opmodeWire <= v;
   endmethod
   method Action a(Bit#(30) v);
      ce1Wire <= 1;
      dsp.a(v);
   endmethod
   method Action b(Bit#(18) v);
      dsp.b(v);
   endmethod
   method Action c(Bit#(48) v);
      dsp.c(v);
   endmethod
   method Action d(Bit#(25) v);
      dsp.d(v);
   endmethod
   method Bit#(48) p() if (last2Reg == 1 || last3Reg == 1 || last4Reg == 1);
      return dsp.p();
   endmethod
   method Action last(Bit#(1) v);
      last1Wire <= v;
   endmethod
endmodule


convert DmaVectorSink to use mkMemwriteEngine

Change-Id: I47cee0ab86b3edad25bf41b817710d60073c15ed

// 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 GetPut::*;
import FIFOF::*;
import PortalMemory::*;
import Dma::*;
import MemreadEngine::*;
import MemwriteEngine::*;
import Adapter::*;
import BRAM::*;
import Pipe::*;

interface VectorSource#(numeric type dsz, type a);
   interface PipeOut#(a) pipe;
   method Action start(ObjectPointer h, Bit#(ObjectOffsetSize) a, Bit#(ObjectOffsetSize) l);
   method ActionValue#(Bool) finish();
endinterface

interface DmaVectorSource#(numeric type dsz, type a);
   interface ObjectReadClient#(dsz) dmaClient;
   interface VectorSource#(dsz, a) vector;
endinterface

function ObjectReadClient#(asz) getSourceReadClient(DmaVectorSource#(asz,a) s); return s.dmaClient; endfunction
function ObjectWriteClient#(asz) getSinkWriteClient(DmaVectorSink#(asz,a) s); return s.dmaClient; endfunction
function VectorSource#(dsz, dtype) dmaVectorSourceVector(DmaVectorSource#(dsz,dtype) dmavs); return dmavs.vector; endfunction

module [Module] mkDmaVectorSource(DmaVectorSource#(asz, a))
   provisos (Bits#(a,asz),
	     Div#(asz,8,abytes),
	     Log#(abytes,ashift),
	     Mul#(abytes, 8, asz)
	     );

   Bool verbose = True;

   let asz = valueOf(asz);
   let abytes = valueOf(abytes);
   let ashift = valueOf(ashift);
   let burstLen = 1;

   FIFOF#(Bit#(asz)) dfifo <- mkSizedFIFOF(8);
   MemreadEngine#(asz) memreadEngine <- mkMemreadEngine(2, dfifo);

   interface ObjectReadClient dmaClient = memreadEngine.dmaClient;
   interface VectorSource vector;
       method Action start(ObjectPointer p, Bit#(ObjectOffsetSize) a, Bit#(ObjectOffsetSize) l);
	  if (verbose) $display("DmaVectorSource.start h=%d a=%h l=%h ashift=%d", p, a, l, ashift);
          memreadEngine.start(p, a << ashift, truncate(l << ashift), 1 << ashift);
       endmethod
      method ActionValue#(Bool) finish();
	 let b <- memreadEngine.finish();
	 return b;
      endmethod
       interface PipeOut pipe;
	  method first();
	     return unpack(dfifo.first());
	  endmethod
	  method Action deq();
	     if (verbose) $display("ObjectReadClient pipe.deq() data=%h", dfifo.first);
	     dfifo.deq;
	  endmethod
	  method notEmpty = dfifo.notEmpty;
       endinterface
   endinterface
endmodule

interface VectorSink#(numeric type dsz, type a);
   interface PipeOut#(Bool) pipe;
   method Action start(ObjectPointer h, Bit#(ObjectOffsetSize) a, Bit#(ObjectOffsetSize) l);
endinterface
interface DmaVectorSink#(numeric type dsz, type a);
   interface ObjectWriteClient#(dsz) dmaClient;
   interface VectorSink#(dsz, a) vector;
endinterface

module [Module] mkDmaVectorSink#(PipeOut#(a) pipe_in)(DmaVectorSink#(asz, a))
   provisos (Bits#(a,asz),
	     Div#(asz,8,abytes),
	     Log#(abytes,ashift),
	     Mul#(abytes,8,asz));

   let asz = valueOf(asz);
   let abytes = valueOf(abytes);
   let ashift = valueOf(ashift);
   let burstLen = 1;

   Bool verbose = False;

   FIFOF#(Bit#(asz)) fifo_in = (interface FIFOF;
				    method Bit#(asz) first(); return pack(pipe_in.first()); endmethod
				    method Bool notEmpty(); return pipe_in.notEmpty(); endmethod
				    method Action enq(Bit#(asz) v); endmethod
				    method Bool notFull(); return False; endmethod
				endinterface);
   MemwriteEngine#(asz) memwriteEngine <- mkMemwriteEngine(2, fifo_in);

   FIFOF#(Bool) rfifo <- mkSizedFIFOF(8);
   rule memwriteDoneRule;
      let b <- memwriteEngine.finish();
      rfifo.enq(True);
   endrule

   interface ObjectWriteClient dmaClient = memwriteEngine.dmaClient;
   interface VectorSink vector;
       method Action start(ObjectPointer p, Bit#(ObjectOffsetSize) a, Bit#(ObjectOffsetSize) l);
	  if (verbose) $display("DmaVectorSink.start   p=%d offset=%h l=%h", p, a, l);
	  memwriteEngine.start(p, a << ashift, truncate(l << ashift), 1 << ashift);
       endmethod
       interface PipeOut pipe = toPipeOut(rfifo);
   endinterface
endmodule

interface BramVectorSource#(numeric type addrsz, numeric type dsz, type dtype);
   interface BRAMClient#(Bit#(addrsz), dtype) bramClient;
   interface VectorSource#(dsz, dtype) vector;
endinterface

module [Module] mkBramVectorSource(BramVectorSource#(addrsz, dsz, dtype))
   provisos (Bits#(dtype,dsz),
	     Add#(a__, addrsz, ObjectOffsetSize)
	     );

   Bool verbose = False;

   let dsz = valueOf(dsz);

   FIFOF#(dtype) dfifo <- mkFIFOF();
   Reg#(Bit#(addrsz)) offset <- mkReg(0);
   Reg#(Bit#(addrsz)) limit <- mkReg(0);

   interface BRAMClient bramClient;
      interface Get request;
	 method ActionValue#(BRAMRequest#(Bit#(addrsz),dtype)) get() if (offset < limit);
	    if (verbose) $display("BramVectorSource.readReq offset=%h limit=%h", offset, limit);
	    offset <= offset + 1;
	    return BRAMRequest { write: False, responseOnWrite: False, address: offset, datain: unpack(0) };
	 endmethod
      endinterface
      interface Put response;
	 method Action put(dtype dmaval);
	    if (verbose) $display("BramVectorSource.readData dmaval=%h", dmaval);
	    dfifo.enq(dmaval);
	 endmethod
      endinterface
   endinterface : bramClient
   interface VectorSource vector;
       method Action start(ObjectPointer pointer, Bit#(ObjectOffsetSize) a, Bit#(ObjectOffsetSize) l) if (offset >= limit);
	  if (verbose) $display("BramVectorSource.start a=%h l=%h", a, l);
	  offset <= truncate(a);
	  limit <= truncate(l);
       endmethod
       interface PipeOut pipe;
	  method first = dfifo.first;
	  method Action deq();
	     if (verbose) $display("BramVectorSource pipe.deq() data=%h", dfifo.first);
	     dfifo.deq;
	  endmethod
	  method notEmpty = dfifo.notEmpty;
       endinterface
   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 GetPut::*;
import FIFOF::*;
import PortalMemory::*;
import Dma::*;
import MemreadEngine::*;
import Adapter::*;
import BRAM::*;
import Pipe::*;

interface VectorSource#(numeric type dsz, type a);
   interface PipeOut#(a) pipe;
   method Action start(ObjectPointer h, Bit#(ObjectOffsetSize) a, Bit#(ObjectOffsetSize) l);
   method ActionValue#(Bool) finish();
endinterface

interface DmaVectorSource#(numeric type dsz, type a);
   interface ObjectReadClient#(dsz) dmaClient;
   interface VectorSource#(dsz, a) vector;
endinterface

function ObjectReadClient#(asz) getSourceReadClient(DmaVectorSource#(asz,a) s); return s.dmaClient; endfunction
function ObjectWriteClient#(asz) getSinkWriteClient(DmaVectorSink#(asz,a) s); return s.dmaClient; endfunction
function VectorSource#(dsz, dtype) dmaVectorSourceVector(DmaVectorSource#(dsz,dtype) dmavs); return dmavs.vector; endfunction

module [Module] mkDmaVectorSource(DmaVectorSource#(asz, a))
   provisos (Bits#(a,asz),
	     Div#(asz,8,abytes),
	     Log#(abytes,ashift),
	     Mul#(abytes, 8, asz)
	     );

   Bool verbose = True;

   let asz = valueOf(asz);
   let abytes = valueOf(abytes);
   let ashift = valueOf(ashift);
   let burstLen = 1;

   FIFOF#(Bit#(asz)) dfifo <- mkSizedFIFOF(8);
   MemreadEngine#(asz) memreadEngine <- mkMemreadEngine(2, dfifo);

   interface ObjectReadClient dmaClient = memreadEngine.dmaClient;
   interface VectorSource vector;
       method Action start(ObjectPointer p, Bit#(ObjectOffsetSize) a, Bit#(ObjectOffsetSize) l);
	  if (verbose) $display("DmaVectorSource.start h=%d a=%h l=%h ashift=%d", p, a, l, ashift);
          memreadEngine.start(p, a << ashift, truncate(l << ashift), 1 << ashift);
       endmethod
      method ActionValue#(Bool) finish();
	 let b <- memreadEngine.finish();
	 return b;
      endmethod
       interface PipeOut pipe;
	  method first();
	     return unpack(dfifo.first());
	  endmethod
	  method Action deq();
	     if (verbose) $display("ObjectReadClient pipe.deq() data=%h", dfifo.first);
	     dfifo.deq;
	  endmethod
	  method notEmpty = dfifo.notEmpty;
       endinterface
   endinterface
endmodule

interface VectorSink#(numeric type dsz, type a);
   interface PipeOut#(Bool) pipe;
   method Action start(ObjectPointer h, Bit#(ObjectOffsetSize) a, Bit#(ObjectOffsetSize) l);
endinterface
interface DmaVectorSink#(numeric type dsz, type a);
   interface ObjectWriteClient#(dsz) dmaClient;
   interface VectorSink#(dsz, a) vector;
endinterface

module [Module] mkDmaVectorSink#(PipeOut#(a) pipe_in)(DmaVectorSink#(asz, a))
   provisos (Bits#(a,asz));

   let asz = valueOf(asz);
   let abytes = asz / 8;
   let burstLen = 1;

   Bool verbose = False;

   FIFOF#(Bool) rfifo <- mkFIFOF();
   Reg#(ObjectPointer) pointer <- mkReg(0);
   Reg#(Bit#(ObjectOffsetSize)) offset <- mkReg(0);
   Reg#(Bit#(ObjectOffsetSize)) doneoffset <- mkReg(0);
   Reg#(Bit#(ObjectOffsetSize)) limit <- mkReg(0);

   interface ObjectWriteClient dmaClient;
      interface Get writeReq;
	  method ActionValue#(ObjectRequest) get if (offset < limit && pipe_in.notEmpty());
	     if (verbose) $display("DmaVectorSink writeReq h=%d offset=%h burstlen=%d pipein.notEmpty=%d rfifo.notFull=%d", pointer, offset, burstLen, pipe_in.notEmpty(), rfifo.notFull());
	     offset <= offset + fromInteger(abytes)*burstLen;
	     return ObjectRequest { pointer: pointer, offset: offset, burstLen: burstLen, tag: 0 };
	  endmethod
      endinterface : writeReq
      interface Get writeData;
	 method ActionValue#(ObjectData#(asz)) get();
	    let v = pipe_in.first;
	    pipe_in.deq;
	    if (verbose) $display("DmaVectorSink.writeBack offset=%h v=%h", offset, v);
	    return ObjectData { data: pack(v), tag: 0 };
	 endmethod
      endinterface : writeData
      interface Put writeDone;
	 method Action put(Bit#(6) tag);
	    //$display("DmaVectorSink writeDone tag=%h", tag);
	    let da = doneoffset + fromInteger(abytes)*burstLen;
	    if (da >= limit)
	       rfifo.enq(?);
	    doneoffset <= da;
	 endmethod
      endinterface : writeDone
   endinterface : dmaClient

   interface VectorSink vector;
       method Action start(ObjectPointer h, Bit#(ObjectOffsetSize) a, Bit#(ObjectOffsetSize) l) if (doneoffset >= limit);
	  pointer <= h;
	  offset <= a*fromInteger(abytes);
	  doneoffset <= a*fromInteger(abytes);
	  limit <= l*fromInteger(abytes);
	  if (verbose) $display("DmaVectorSink.start   h=%d offset=%h l=%h", h, a, l);
       endmethod
       interface PipeOut pipe = toPipeOut(rfifo);
   endinterface
endmodule

interface BramVectorSource#(numeric type addrsz, numeric type dsz, type dtype);
   interface BRAMClient#(Bit#(addrsz), dtype) bramClient;
   interface VectorSource#(dsz, dtype) vector;
endinterface

module [Module] mkBramVectorSource(BramVectorSource#(addrsz, dsz, dtype))
   provisos (Bits#(dtype,dsz),
	     Add#(a__, addrsz, ObjectOffsetSize)
	     );

   Bool verbose = False;

   let dsz = valueOf(dsz);

   FIFOF#(dtype) dfifo <- mkFIFOF();
   Reg#(Bit#(addrsz)) offset <- mkReg(0);
   Reg#(Bit#(addrsz)) limit <- mkReg(0);

   interface BRAMClient bramClient;
      interface Get request;
	 method ActionValue#(BRAMRequest#(Bit#(addrsz),dtype)) get() if (offset < limit);
	    if (verbose) $display("BramVectorSource.readReq offset=%h limit=%h", offset, limit);
	    offset <= offset + 1;
	    return BRAMRequest { write: False, responseOnWrite: False, address: offset, datain: unpack(0) };
	 endmethod
      endinterface
      interface Put response;
	 method Action put(dtype dmaval);
	    if (verbose) $display("BramVectorSource.readData dmaval=%h", dmaval);
	    dfifo.enq(dmaval);
	 endmethod
      endinterface
   endinterface : bramClient
   interface VectorSource vector;
       method Action start(ObjectPointer pointer, Bit#(ObjectOffsetSize) a, Bit#(ObjectOffsetSize) l) if (offset >= limit);
	  if (verbose) $display("BramVectorSource.start a=%h l=%h", a, l);
	  offset <= truncate(a);
	  limit <= truncate(l);
       endmethod
       interface PipeOut pipe;
	  method first = dfifo.first;
	  method Action deq();
	     if (verbose) $display("BramVectorSource pipe.deq() data=%h", dfifo.first);
	     dfifo.deq;
	  endmethod
	  method notEmpty = dfifo.notEmpty;
       endinterface
   endinterface
endmodule