fix clock on reset

fix clock on reset

// 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 Clocks::*;
import Vector::*;
import FIFO::*;
import FIFOF::*;
import BRAMFIFO::*;
import CBus::*; // extendNP and truncateNP

import Arith::*;

(* always_ready, always_enabled *)
interface X7FifoSyncMacro#(numeric type data_width);
   method Bit#(1) empty();
   method Bit#(1) full();
   method Action din(Bit#(data_width) v);
   method Action wren(Bit#(1) wren);
   method Bit#(data_width) dout();
   method Action rden(Bit#(1) rden);
   method Bit#(9) wrcount();
   method Bit#(9) rdcount();
endinterface

import "BVI" FIFO_DUALCLOCK_MACRO =
module  vmkBramFifo#(String fifo_size, Clock wrClock, Reset wrReset, Clock rdClock, Reset rdReset)(X7FifoSyncMacro#(data_width));
   let invertReset <- mkResetInverter(wrReset, clocked_by wrClock);
   parameter DEVICE = "7SERIES";
   parameter DATA_WIDTH = valueOf(data_width);
   parameter FIFO_SIZE = fifo_size;
   parameter FIRST_WORD_FALL_THROUGH = 1;
   default_clock wrClock(WRCLK) = wrClock;
   no_reset;
   input_reset wrReset(RST) = invertReset;
   input_clock rdClock(RDCLK) = rdClock;
   method EMPTY empty() clocked_by (rdClock) reset_by (wrReset);
   method FULL full() clocked_by (wrClock) reset_by (wrReset);
   method din(DI) enable ((*inhigh*)EN_di) clocked_by (wrClock) reset_by (wrReset);
   method wren(WREN) enable ((*inhigh*)EN_wren) clocked_by (wrClock) reset_by (wrReset);
   method DO dout() clocked_by (rdClock) reset_by (wrReset);
   method rden(RDEN) enable ((*inhigh*)EN_rden) clocked_by (rdClock) reset_by (wrReset);
   // wrcount and rdcount ports are needed for xsim
   method WRCOUNT wrcount() clocked_by (wrClock) reset_by (wrReset);
   method RDCOUNT rdcount() clocked_by (rdClock) reset_by (wrReset);
   schedule (empty, full, dout, din, wren, rden, wrcount, rdcount) CF (empty, full, dout, din, wren, rden, wrcount, rdcount);
endmodule

module mkDualClockBramFIFOF#(Clock srcClock, Reset srcReset, Clock dstClock, Reset dstReset)(FIFOF#(t))
   provisos (Bits#(t,sizet),
	     Add#(1,a__,sizet));
   String fifo_size = "18Kb";
   Vector#(TDiv#(sizet,36),X7FifoSyncMacro#(36)) fifos <- replicateM(vmkBramFifo(fifo_size, srcClock, srcReset, dstClock, dstReset));
   Wire#(Bit#(1)) rdenWire <- mkDWire(0, clocked_by dstClock, reset_by dstReset);
   Wire#(Bit#(1)) wrenWire <- mkDWire(0, clocked_by srcClock, reset_by srcReset);
   Vector#(TDiv#(sizet,36),Wire#(Bit#(36))) dinWires <- replicateM(mkDWire(0, clocked_by srcClock, reset_by srcReset));

   for (Integer i = 0; i < valueOf(TDiv#(sizet,36)); i = i+1) begin
      Reg#(Bit#(9)) rdcount <- mkReg(0, clocked_by dstClock, reset_by dstReset);
      Reg#(Bit#(9)) wrcount <- mkReg(0, clocked_by srcClock, reset_by srcReset);
      rule rdenRule;
	 fifos[i].rden(rdenWire);
      endrule
      rule wrenRule;
	 fifos[i].wren(wrenWire);
      endrule
      rule inputs;
	 fifos[i].din(dinWires[i]);
      endrule
      rule countrds;
	 rdcount <= fifos[i].rdcount();
      endrule
      rule countwrs;
	 wrcount <= fifos[i].wrcount();
      endrule
   end

   function Bool fifoNotEmpty(Integer i); return fifos[i].empty == 0; endfunction
   function Bool fifoNotFull(Integer i); return fifos[i].full == 0; endfunction
   Vector#(TDiv#(sizet,36), Bool) vNotEmpty = genWith(fifoNotEmpty);
   Vector#(TDiv#(sizet,36), Bool) vNotFull = genWith(fifoNotFull);

   method t first() if (fifos[0].empty == 0);
      function Bit#(36) fifoFirst(Integer i); return fifos[i].dout(); endfunction
      Vector#(TDiv#(sizet,36), Bit#(36)) v = genWith(fifoFirst);
      return unpack(truncateNP(pack(v)));
   endmethod
   method Action deq() if (fifos[0].empty == 0);
      rdenWire <= 1;
   endmethod
   method notEmpty = (fifos[0].empty == 0);
   method Action enq(t v) if (fifos[0].full == 0);
      Vector#(TDiv#(sizet,36), Bit#(36)) vs = unpack(extendNP(pack(v)));
      Vector#(TDiv#(sizet,36), Integer) indices = genVector();
      function Action fifoEnq(Integer i); action dinWires[i] <= vs[i]; endaction endfunction
      mapM_(fifoEnq, indices);
      wrenWire <= 1;
   endmethod
   method notFull = (fifos[0].full == 0);
endmodule

module mkSizedBRAMFIFOF#(Integer m)(FIFOF#(t))
   provisos (Bits#(t,sizet),
	     Add#(1,a__,sizet));
   let clock <- exposeCurrentClock();
   let reset <- exposeCurrentReset();
   let fifo <- mkDualClockBramFIFOF(clock, reset, clock, reset);
   return fifo;
endmodule
module mkSizedBRAMFIFO#(Integer m)(FIFO#(t))
   provisos (Bits#(t,sizet),
	     Add#(1,a__,sizet));
   let clock <- exposeCurrentClock();
   let reset <- exposeCurrentReset();
   let fifo <- mkDualClockBramFIFOF(clock, reset, clock, reset);
   method first = fifo.first;
   method deq = fifo.deq;
   method enq = fifo.enq;
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 Clocks::*;
import Vector::*;
import FIFO::*;
import FIFOF::*;
import BRAMFIFO::*;
import CBus::*; // extendNP and truncateNP

import Arith::*;

(* always_ready, always_enabled *)
interface X7FifoSyncMacro#(numeric type data_width);
   method Bit#(1) empty();
   method Bit#(1) full();
   method Action din(Bit#(data_width) v);
   method Action wren(Bit#(1) wren);
   method Bit#(data_width) dout();
   method Action rden(Bit#(1) rden);
   method Bit#(9) wrcount();
   method Bit#(9) rdcount();
endinterface

import "BVI" FIFO_DUALCLOCK_MACRO =
module  vmkBramFifo#(String fifo_size, Clock wrClock, Reset wrReset, Clock rdClock, Reset rdReset)(X7FifoSyncMacro#(data_width));
   let invertReset <- mkResetInverter(wrReset);
   parameter DEVICE = "7SERIES";
   parameter DATA_WIDTH = valueOf(data_width);
   parameter FIFO_SIZE = fifo_size;
   parameter FIRST_WORD_FALL_THROUGH = 1;
   default_clock wrClock(WRCLK) = wrClock;
   default_reset wrReset(RST) = invertReset;
   input_clock rdClock(RDCLK) = rdClock;
   method EMPTY empty() clocked_by (rdClock) reset_by (wrReset);
   method FULL full() clocked_by (wrClock) reset_by (wrReset);
   method din(DI) enable ((*inhigh*)EN_di) clocked_by (wrClock) reset_by (wrReset);
   method wren(WREN) enable ((*inhigh*)EN_wren) clocked_by (wrClock) reset_by (wrReset);
   method DO dout() clocked_by (rdClock) reset_by (wrReset);
   method rden(RDEN) enable ((*inhigh*)EN_rden) clocked_by (rdClock) reset_by (wrReset);
   // wrcount and rdcount ports are needed for xsim
   method WRCOUNT wrcount() clocked_by (wrClock) reset_by (wrReset);
   method RDCOUNT rdcount() clocked_by (rdClock) reset_by (wrReset);
   schedule (empty, full, dout, din, wren, rden, wrcount, rdcount) CF (empty, full, dout, din, wren, rden, wrcount, rdcount);
endmodule

module mkDualClockBramFIFOF#(Clock srcClock, Reset srcReset, Clock dstClock, Reset dstReset)(FIFOF#(t))
   provisos (Bits#(t,sizet),
	     Add#(1,a__,sizet));
   String fifo_size = "18Kb";
   Vector#(TDiv#(sizet,36),X7FifoSyncMacro#(36)) fifos <- replicateM(vmkBramFifo(fifo_size, srcClock, srcReset, dstClock, dstReset));
   Wire#(Bit#(1)) rdenWire <- mkDWire(0, clocked_by dstClock, reset_by dstReset);
   Wire#(Bit#(1)) wrenWire <- mkDWire(0, clocked_by srcClock, reset_by srcReset);
   Vector#(TDiv#(sizet,36),Wire#(Bit#(36))) dinWires <- replicateM(mkDWire(0, clocked_by srcClock, reset_by srcReset));

   for (Integer i = 0; i < valueOf(TDiv#(sizet,36)); i = i+1) begin
      Reg#(Bit#(9)) rdcount <- mkReg(0, clocked_by dstClock, reset_by dstReset);
      Reg#(Bit#(9)) wrcount <- mkReg(0, clocked_by srcClock, reset_by srcReset);
      rule rdenRule;
	 fifos[i].rden(rdenWire);
      endrule
      rule wrenRule;
	 fifos[i].wren(wrenWire);
      endrule
      rule inputs;
	 fifos[i].din(dinWires[i]);
      endrule
      rule countrds;
	 rdcount <= fifos[i].rdcount();
      endrule
      rule countwrs;
	 wrcount <= fifos[i].wrcount();
      endrule
   end

   function Bool fifoNotEmpty(Integer i); return fifos[i].empty == 0; endfunction
   function Bool fifoNotFull(Integer i); return fifos[i].full == 0; endfunction
   Vector#(TDiv#(sizet,36), Bool) vNotEmpty = genWith(fifoNotEmpty);
   Vector#(TDiv#(sizet,36), Bool) vNotFull = genWith(fifoNotFull);

   method t first() if (fifos[0].empty == 0);
      function Bit#(36) fifoFirst(Integer i); return fifos[i].dout(); endfunction
      Vector#(TDiv#(sizet,36), Bit#(36)) v = genWith(fifoFirst);
      return unpack(truncateNP(pack(v)));
   endmethod
   method Action deq() if (fifos[0].empty == 0);
      rdenWire <= 1;
   endmethod
   method notEmpty = (fifos[0].empty == 0);
   method Action enq(t v) if (fifos[0].full == 0);
      Vector#(TDiv#(sizet,36), Bit#(36)) vs = unpack(extendNP(pack(v)));
      Vector#(TDiv#(sizet,36), Integer) indices = genVector();
      function Action fifoEnq(Integer i); action dinWires[i] <= vs[i]; endaction endfunction
      mapM_(fifoEnq, indices);
      wrenWire <= 1;
   endmethod
   method notFull = (fifos[0].full == 0);
endmodule

module mkSizedBRAMFIFOF#(Integer m)(FIFOF#(t))
   provisos (Bits#(t,sizet),
	     Add#(1,a__,sizet));
   let clock <- exposeCurrentClock();
   let reset <- exposeCurrentReset();
   let fifo <- mkDualClockBramFIFOF(clock, reset, clock, reset);
   return fifo;
endmodule
module mkSizedBRAMFIFO#(Integer m)(FIFO#(t))
   provisos (Bits#(t,sizet),
	     Add#(1,a__,sizet));
   let clock <- exposeCurrentClock();
   let reset <- exposeCurrentReset();
   let fifo <- mkDualClockBramFIFOF(clock, reset, clock, reset);
   method first = fifo.first;
   method deq = fifo.deq;
   method enq = fifo.enq;
endmodule


change get/set addresses t 64 bits, because DmaOffsetSize is 40, which is > 32

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

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

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

import FIFO::*;
import FIFOF::*;
import BRAMFIFO::*;
import GetPut::*;
import StmtFSM::*;
import ClientServer::*;

import PortalMemory::*;
import Dma::*;
import GetPutF::*;

import RingTypes::*;
import RingBuffer::*;
import CopyEngine::*;
import EchoEngine::*;
import NopEngine::*;

interface RingRequest;
   method Action set(Bit#(1) cmd, Bit#(3) regist, Bit#(64) addr);
   method Action get(Bit#(1) cmd, Bit#(3) regist);
   method Action hwenable(Bit#(1) en);
   method Action doCommandIndirect(Bit#(64) addr);
   method Action doCommandImmediate(Bit#(64) data);
endinterface

interface RingIndication;
   method Action setResult(Bit#(1) cmd, Bit#(3) regist, Bit#(64) addr);
   method Action getResult(Bit#(1) cmd, Bit#(3) regist, Bit#(64) addr);
   method Action completion(Bit#(32) command, Bit#(32) tag);
endinterface

module mkRingRequest#(RingIndication indication,
		      DmaReadServer#(64) dma_read_chan,
		      DmaWriteServer#(64) dma_write_chan,
		      DmaReadServer#(64) cmd_read_chan,
		      DmaWriteServer#(64) status_write_chan )(RingRequest);

   ServerF#(Bit#(64), Bit#(64)) copyEngine <- mkCopyEngine(dma_read_chan, dma_write_chan);
   ServerF#(Bit#(64), Bit#(64)) nopEngine <- mkNopEngine();
   ServerF#(Bit#(64), Bit#(64)) echoEngine <- mkEchoEngine();

   RingBuffer cmdRing <- mkRingBuffer;
   RingBuffer statusRing <- mkRingBuffer;
   Reg#(Bool) hwenabled <- mkReg(False);
   Reg#(Bool) cmdBusy <- mkReg(False);
   Reg#(DmaData#(64)) cmd <- mkReg(DmaData{data:0, tag:0});
   Reg#(Bit#(4)) ii <- mkReg(0);
   Reg#(Bit#(4)) respCtr <- mkReg(0);
   Reg#(Bit#(4)) dispCtr <- mkReg(0);
   Reg#(Bit#(6)) cmdFetchTag <- mkReg(0);
   Reg#(Bit#(6)) statusTag <- mkReg(0);
   Reg#(Bool) cmdFetchEn <- mkReg(False);

   let engineselect = cmd.data[63:56];
   function ServerF#(Bit#(64), Bit#(64)) cmdifc();
      if (engineselect == zeroExtend(pack(CmdNOP)))
	 return nopEngine;
      else if (engineselect == zeroExtend(pack(CmdCOPY)))
	 return copyEngine;
      else if (engineselect == zeroExtend(pack(CmdECHO)))
	 return echoEngine;
      else
	 return nopEngine;
   endfunction

   Stmt cmdFetch =
   seq
//      $display("cmdFetch FSM TOP");
      while (True)
	 seq
	    if (hwenabled)
	       seq
	       if (cmdRing.bufferfirst != cmdRing.bufferlast)
		  seq
		     //$display ("cmdFetch handle=%h address=%h burst=%h tag=%h", cmdRing.memhandle, cmdRing.bufferlast, 8, cmdFetchTag);
		     cmd_read_chan.readReq.put(
			DmaRequest{handle: cmdRing.memhandle,
			   address: cmdRing.bufferlast, burstLen: 8, tag: cmdFetchTag});
		     cmdRing.pop(64);
		     cmdFetchTag <= cmdFetchTag + 1;
		  endseq
	       endseq
	 endseq
   endseq;

   Stmt cmdDispatch =
   seq
      while (True) seq
//	 $display("cmdDispatch FSM TOP");
	 seq
	    action
	       let rv <- cmd_read_chan.readData.get();
	       cmd <= rv;
	    endaction
	    // wait a cycle so cmd is valid!
	    //$display("cmdDispatch 0 tag=%h %h", cmd.tag, cmd.data);
	    cmdifc.request.put(cmd.data);
	 endseq
	 for (dispCtr <= 1; dispCtr < 8; dispCtr <= dispCtr + 1)
	    action
	       let rv <- cmd_read_chan.readData.get();
	       //$display("  cmdDispatch %h tag=%h %h", dispCtr, rv.tag, rv.data);
	       cmdifc.request.put(rv.data);
	    endaction
      endseq
   endseq;

   Stmt responseArbiter =
   seq
      while(True) seq
	 if (statusRing.notFull() && copyEngine.response.notEmpty())
	    seq
	       //$display("responseArbiter copyEngine completion");
	       //$display("status write handle=%d address=%h burst=%h tag=%h",
	//	  statusRing.memhandle, statusRing.bufferfirst, 8, statusTag);
	       status_write_chan.writeReq.put(
		  DmaRequest{handle: statusRing.memhandle,
		     address: statusRing.bufferfirst, burstLen: 8, tag: statusTag});
	       for (respCtr <= 0; respCtr < 8; respCtr <= respCtr + 1)
		  action
		     let rv <- copyEngine.response.get();
		     status_write_chan.writeData.put(DmaData{data: rv, tag: statusTag});
		  endaction
	       statusRing.push(64);
	       statusTag <= statusTag + 1;
	    endseq

	 if (statusRing.notFull() && echoEngine.response.notEmpty())
	    seq
	       //$display("responseArbiter echoEngine completion");
	       //$display("status write handle=%d address=%h burst=%h tag=%h",
	//	  statusRing.memhandle, statusRing.bufferfirst, 8, statusTag);
	       status_write_chan.writeReq.put(
		  DmaRequest{handle: statusRing.memhandle,
		     address: statusRing.bufferfirst, burstLen: 8, tag: statusTag});
	       for (respCtr <= 0; respCtr < 8; respCtr <= respCtr + 1)
		  action
		     let rv <- echoEngine.response.get();
		     status_write_chan.writeData.put(DmaData{data: rv, tag: statusTag});
		  endaction
	       statusRing.push(64);
	       statusTag <= statusTag + 1;
	    endseq

      endseq
   endseq;

   rule writeAck;
      let tag <- status_write_chan.writeDone.get();
      //$display("status write done tag=%h", tag);
   endrule

   mkAutoFSM (cmdFetch);
   mkAutoFSM (cmdDispatch);
   mkAutoFSM (responseArbiter);

      // to start a command, doCommand fires off a memory read to the
      // specified address. when it comes back, the doCommandRule will
      // handle it
      method Action doCommandIndirect(Bit#(64) addr);
	 cmd_read_chan.readReq.put(
				   DmaRequest{handle: addr[63:32],
	 address: truncate(addr[31:0]), burstLen: 8, tag: cmdFetchTag});
   	 cmdFetchTag <= cmdFetchTag + 1;
      endmethod

      method Action doCommandImmediate(Bit#(64) data);
      	 $display("doCommandImmediate %h", data);
      endmethod

      method Action set(Bit#(1) _cmd, Bit#(3) regist, Bit#(64) addr);
	 if (_cmd == 0)
	    cmdRing.configifc.set(regist, truncate(addr));
	 else
	    statusRing.configifc.set(regist, truncate(addr));
	 indication.setResult(_cmd, regist, addr);
      endmethod

      method Action get(Bit#(1) _cmd, Bit#(3) regist);
	 if (_cmd == 0)
	    indication.getResult(0, regist,
	       zeroextend(cmdRing.configifc.get(regist)));
	 else
	    indication.getResult(0, regist,
	       zeroextend(statusRing.configifc.get(regist)));
      endmethod

      method Action hwenable(Bit#(1) en);
	 $display ("hwenable set to %h", en);
	 hwenabled <= en == 1;
      endmethod

endmodule

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

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

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

import FIFO::*;
import FIFOF::*;
import BRAMFIFO::*;
import GetPut::*;
import StmtFSM::*;
import ClientServer::*;

import PortalMemory::*;
import Dma::*;
import GetPutF::*;

import RingTypes::*;
import RingBuffer::*;
import CopyEngine::*;
import EchoEngine::*;
import NopEngine::*;

interface RingRequest;
   method Action set(Bit#(1) cmd, Bit#(3) regist, Bit#(32) addr);
   method Action get(Bit#(1) cmd, Bit#(3) regist);
   method Action hwenable(Bit#(1) en);
   method Action doCommandIndirect(Bit#(64) addr);
   method Action doCommandImmediate(Bit#(64) data);
endinterface

interface RingIndication;
   method Action setResult(Bit#(1) cmd, Bit#(3) regist, Bit#(32) addr);
   method Action getResult(Bit#(1) cmd, Bit#(3) regist, Bit#(32) addr);
   method Action completion(Bit#(32) command, Bit#(32) tag);
endinterface

module mkRingRequest#(RingIndication indication,
		      DmaReadServer#(64) dma_read_chan,
		      DmaWriteServer#(64) dma_write_chan,
		      DmaReadServer#(64) cmd_read_chan,
		      DmaWriteServer#(64) status_write_chan )(RingRequest);

   ServerF#(Bit#(64), Bit#(64)) copyEngine <- mkCopyEngine(dma_read_chan, dma_write_chan);
   ServerF#(Bit#(64), Bit#(64)) nopEngine <- mkNopEngine();
   ServerF#(Bit#(64), Bit#(64)) echoEngine <- mkEchoEngine();

   RingBuffer cmdRing <- mkRingBuffer;
   RingBuffer statusRing <- mkRingBuffer;
   Reg#(Bool) hwenabled <- mkReg(False);
   Reg#(Bool) cmdBusy <- mkReg(False);
   Reg#(DmaData#(64)) cmd <- mkReg(DmaData{data:0, tag:0});
   Reg#(Bit#(4)) ii <- mkReg(0);
   Reg#(Bit#(4)) respCtr <- mkReg(0);
   Reg#(Bit#(4)) dispCtr <- mkReg(0);
   Reg#(Bit#(6)) cmdFetchTag <- mkReg(0);
   Reg#(Bit#(6)) statusTag <- mkReg(0);
   Reg#(Bool) cmdFetchEn <- mkReg(False);

   let engineselect = cmd.data[63:56];
   function ServerF#(Bit#(64), Bit#(64)) cmdifc();
      if (engineselect == zeroExtend(pack(CmdNOP)))
	 return nopEngine;
      else if (engineselect == zeroExtend(pack(CmdCOPY)))
	 return copyEngine;
      else if (engineselect == zeroExtend(pack(CmdECHO)))
	 return echoEngine;
      else
	 return nopEngine;
   endfunction

   Stmt cmdFetch =
   seq
//      $display("cmdFetch FSM TOP");
      while (True)
	 seq
	    if (hwenabled)
	       seq
	       if (cmdRing.bufferfirst != cmdRing.bufferlast)
		  seq
		     //$display ("cmdFetch handle=%h address=%h burst=%h tag=%h", cmdRing.memhandle, cmdRing.bufferlast, 8, cmdFetchTag);
		     cmd_read_chan.readReq.put(
			DmaRequest{handle: cmdRing.memhandle,
			   address: cmdRing.bufferlast, burstLen: 8, tag: cmdFetchTag});
		     cmdRing.pop(64);
		     cmdFetchTag <= cmdFetchTag + 1;
		  endseq
	       endseq
	 endseq
   endseq;

   Stmt cmdDispatch =
   seq
      while (True) seq
//	 $display("cmdDispatch FSM TOP");
	 seq
	    action
	       let rv <- cmd_read_chan.readData.get();
	       cmd <= rv;
	    endaction
	    // wait a cycle so cmd is valid!
	    //$display("cmdDispatch 0 tag=%h %h", cmd.tag, cmd.data);
	    cmdifc.request.put(cmd.data);
	 endseq
	 for (dispCtr <= 1; dispCtr < 8; dispCtr <= dispCtr + 1)
	    action
	       let rv <- cmd_read_chan.readData.get();
	       //$display("  cmdDispatch %h tag=%h %h", dispCtr, rv.tag, rv.data);
	       cmdifc.request.put(rv.data);
	    endaction
      endseq
   endseq;

   Stmt responseArbiter =
   seq
      while(True) seq
	 if (statusRing.notFull() && copyEngine.response.notEmpty())
	    seq
	       //$display("responseArbiter copyEngine completion");
	       //$display("status write handle=%d address=%h burst=%h tag=%h",
	//	  statusRing.memhandle, statusRing.bufferfirst, 8, statusTag);
	       status_write_chan.writeReq.put(
		  DmaRequest{handle: statusRing.memhandle,
		     address: statusRing.bufferfirst, burstLen: 8, tag: statusTag});
	       for (respCtr <= 0; respCtr < 8; respCtr <= respCtr + 1)
		  action
		     let rv <- copyEngine.response.get();
		     status_write_chan.writeData.put(DmaData{data: rv, tag: statusTag});
		  endaction
	       statusRing.push(64);
	       statusTag <= statusTag + 1;
	    endseq

	 if (statusRing.notFull() && echoEngine.response.notEmpty())
	    seq
	       //$display("responseArbiter echoEngine completion");
	       //$display("status write handle=%d address=%h burst=%h tag=%h",
	//	  statusRing.memhandle, statusRing.bufferfirst, 8, statusTag);
	       status_write_chan.writeReq.put(
		  DmaRequest{handle: statusRing.memhandle,
		     address: statusRing.bufferfirst, burstLen: 8, tag: statusTag});
	       for (respCtr <= 0; respCtr < 8; respCtr <= respCtr + 1)
		  action
		     let rv <- echoEngine.response.get();
		     status_write_chan.writeData.put(DmaData{data: rv, tag: statusTag});
		  endaction
	       statusRing.push(64);
	       statusTag <= statusTag + 1;
	    endseq

      endseq
   endseq;

   rule writeAck;
      let tag <- status_write_chan.writeDone.get();
      //$display("status write done tag=%h", tag);
   endrule

   mkAutoFSM (cmdFetch);
   mkAutoFSM (cmdDispatch);
   mkAutoFSM (responseArbiter);

      // to start a command, doCommand fires off a memory read to the
      // specified address. when it comes back, the doCommandRule will
      // handle it
      method Action doCommandIndirect(Bit#(64) addr);
	 cmd_read_chan.readReq.put(
				   DmaRequest{handle: addr[63:32],
	 address: truncate(addr[31:0]), burstLen: 8, tag: cmdFetchTag});
   	 cmdFetchTag <= cmdFetchTag + 1;
      endmethod

      method Action doCommandImmediate(Bit#(64) data);
      	 $display("doCommandImmediate %h", data);
      endmethod

      method Action set(Bit#(1) _cmd, Bit#(3) regist, Bit#(32) addr);
	 if (_cmd == 0)
	    cmdRing.configifc.set(regist, addr);
	 else
	    statusRing.configifc.set(regist, addr);
	 indication.setResult(_cmd, regist, addr);
      endmethod

      method Action get(Bit#(1) _cmd, Bit#(3) regist);
	 if (_cmd == 0)
	    indication.getResult(0, regist,
	       cmdRing.configifc.get(regist));
	 else
	    indication.getResult(0, regist,
	       statusRing.configifc.get(regist));
      endmethod

      method Action hwenable(Bit#(1) en);
	 $display ("hwenable set to %h", en);
	 hwenabled <= en == 1;
      endmethod

endmodule


Zynq is still using Axi3Master rather than Axi3Client

// 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 Vector            :: *;
import Connectable       :: *;
import Portal            :: *;
import Leds              :: *;
import Top               :: *;
import AxiMasterSlave    :: *;

interface ZynqTop#(type pins);
   interface StdAxi3Slave     ctrl;
   interface StdAxi3Master    m_axi;
   interface ReadOnly#(Bool)  interrupt;
   interface LEDS             leds;
   interface pins             pins;
endinterface

typedef (function Module#(PortalTop#(nmasters, ipins)) mkpt()) MkPortalTop#(numeric type nmasters, type ipins);

module [Module] mkZynqTopFromPortal#(MkPortalTop#(nmasters,ipins) constructor)(ZynqTop#(ipins));
   let defaultClock <- exposeCurrentClock;
   let top <- constructor(clocked_by defaultClock);
   StdAxi3Master master = ?;
   if (valueOf(nmasters) > 0) begin
      let m <- mkAxi3Master(top.m_axi[0]);
      master = m;
   end

   interface ctrl = top.ctrl;
   interface m_axi = master;
   interface interrupt = top.interrupt;
   interface leds = top.leds;
   interface pins = top.pins;
endmodule

module mkZynqTop(ZynqTop#(Empty));
   let top <- mkZynqTopFromPortal(mkPortalTop);
   return top;
endmodule

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

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

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

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

import Vector            :: *;
import Connectable       :: *;
import Portal            :: *;
import Leds              :: *;
import Top               :: *;

interface ZynqTop#(type pins);
   interface StdAxi3Slave     ctrl;
   interface StdAxi3Client    m_axi;
   interface ReadOnly#(Bool)  interrupt;
   interface LEDS             leds;
   interface pins             pins;
endinterface

typedef (function Module#(PortalTop#(nmasters, ipins)) mkpt()) MkPortalTop#(numeric type nmasters, type ipins);

module [Module] mkZynqTopFromPortal#(MkPortalTop#(nmasters,ipins) constructor)(ZynqTop#(ipins));
   let defaultClock <- exposeCurrentClock;
   let top <- constructor(clocked_by defaultClock);
   StdAxi3Client master = ?;
   if (valueOf(nmasters) > 0)
      master = top.m_axi[0];

   interface ctrl = top.ctrl;
   interface m_axi = master;
   interface interrupt = top.interrupt;
   interface leds = top.leds;
   interface pins = top.pins;
endmodule

module mkZynqTop(ZynqTop#(Empty));
   let top <- mkZynqTopFromPortal(mkPortalTop);
   return top;
endmodule


add setPhaseAdvance

add setPhaseAdvance

// 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 DDS::*;
import Gearbox::*;
import ChannelSelect::*;

import Complex::*;
import SDRTypes::*;
import FPCMult::*;
import FixedPoint::*;
import Pipe::*;
import Vector::*;
import ChannelSelectTestInterfaces::*;

module mkChannelSelectTestRequest#(ChannelSelectTestIndication indication) (ChannelSelectTestRequest)
   provisos(Bits#(CoeffData, a__),
	    Bits#(ProductData, b__),
	    Bits#(MulData, c__));
   Clock clk <- exposeCurrentClock;
   Reset rst <- exposeCurrentReset;
   Gearbox#(1, 2, Complex#(Signal)) gb <- mk1toNGearbox(clk, rst, clk, rst);
   DDS dds <- mkDDS();
   ChannelSelect cs <- mkChannelSelect(4, dds);

   rule processRF;
      let data = gb.first();
      gb.deq();
      cs.rfreq.enq(data);
   endrule

   rule processIF;
      let data = cs.ifreq.first();
      cs.ifreq.deq();
      indication.ifreqData(zeroExtend(pack(data.rel)), zeroExtend(pack(data.img)));
   endrule

   method Action rfreqDataWrite(Bit#(32) dataRe, Bit#(32) dataIm);
      Signal re = unpack(truncate(dataRe));
      Signal im = unpack(truncate(dataIm));
      Vector#(1, Complex#(Signal)) x = newVector();
      x[0] = Complex{rel: re, img: im};
      gb.enq(x);
      indication.setDataResp();
   endmethod

   method Action setCoeff(Bit#(11) addr, Bit#(32) valueRe, Bit#(32) valueIm);
    FixedPoint#(2, 23) re = unpack(pack(truncate(valueRe)));
    FixedPoint#(2, 23) im = unpack(pack(truncate(valueIm)));
      cs.setCoeff(addr, Complex{rel: re, img:im});
      indication.setCoeffResp();
   endmethod

   method Action setPhaseAdvance(Bit#(32) i, Bit#(32) f);
    dds.setPhaseAdvance(FixedPoint{i: truncate(i), f: f});
      indication.setPhaseResp();
   endmethod
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 DDS::*;
import Gearbox::*;
import ChannelSelect::*;

import Complex::*;
import SDRTypes::*;
import FPCMult::*;
import FixedPoint::*;
import Pipe::*;
import Vector::*;
import ChannelSelectTestInterfaces::*;

module mkChannelSelectTestRequest#(ChannelSelectTestIndication indication) (ChannelSelectTestRequest)
   provisos(Bits#(CoeffData, a__),
	    Bits#(ProductData, b__),
	    Bits#(MulData, c__));
   Clock clk <- exposeCurrentClock;
   Reset rst <- exposeCurrentReset;
   Gearbox#(1, 2, Complex#(Signal)) gb <- mk1toNGearbox(clk, rst, clk, rst);
   DDS dds <- mkDDS();
   ChannelSelect cs <- mkChannelSelect(4, dds);

   rule processRF;
      let data = gb.first();
      gb.deq();
      cs.rfreq.enq(data);
   endrule

   rule processIF;
      let data = cs.ifreq.first();
      cs.ifreq.deq();
      indication.ifreqData(zeroExtend(pack(data.rel)), zeroExtend(pack(data.img)));
   endrule

   method Action rfreqDataWrite(Bit#(32) dataRe, Bit#(32) dataIm);
      Signal re = unpack(truncate(dataRe));
      Signal im = unpack(truncate(dataIm));
      Vector#(1, Complex#(Signal)) x = newVector();
      x[0] = Complex{rel: re, img: im};
      gb.enq(x);
      indication.setDataResp();
   endmethod

   method Action setCoeff(Bit#(11) addr, Bit#(32) valueRe, Bit#(32) valueIm);
    FixedPoint#(2, 23) re = unpack(pack(truncate(valueRe)));
    FixedPoint#(2, 23) im = unpack(pack(truncate(valueIm)));
      cs.setCoeff(addr, Complex{rel: re, img:im});
      indication.setCoeffResp();
   endmethod
endmodule


implement a rule waiting for fsm completion that sends an indication

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

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

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

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

import FIFO::*;
import FIFOF::*;
import SpecialFIFOs::*;
import GetPut::*;
import StmtFSM::*;
//import Vector::*;
import BRAM::*;
//import Gearbox::*;
import Connectable::*;

//import AxiMasterSlave::*;
import Dma::*;
import DmaUtils::*;
import Dma2BRAM::*;

// algorithm
import HirschA::*;
import Hirsch::*;

/* This module solves the maximum common subsequence problem.
 * It finds the longest subsequence of characters present in both input strings
 * the subsequence does not have to be contiguous and the characters can have different locations
 * and offsets in the two strings, just so long as they occur in the same order
 *
 *  To initialize, load string A with request setupA, and wait for indication setup complete
 * Then load string B with request setupB, and wait for indication setup complete
 * To start the unit, signal start, and wait for searchResult, which will tell you the length
 * To retreive the result, use fetch and wait for fetchComplete
 */

/* First pass implements Hirschberg Algorithm A and the fetch call returns the L matrix
 */
interface MaxcommonsubseqRequest;
   method Action setupA(Bit#(32) strPointer, Bit#(32) strLen);
   method Action setupB(Bit#(32) strPointer, Bit#(32) strLen);
   method Action fetch(Bit#(32) strPointer, Bit#(32) dest, Bit#(32) src, Bit#(32) strLen);
   method Action start(Bit#(32) alg);
endinterface

interface MaxcommonsubseqIndication;
   method Action searchResult(Int#(32) v);
   method Action setupAComplete();
   method Action setupBComplete();
   method Action fetchComplete();
endinterface

typedef Bit#(64) DWord;
typedef Bit#(32) Word;

typedef 128 MaxStringLen;
typedef 16384 MaxFetchLen;
typedef TLog#(MaxStringLen) StringIdxWidth;
typedef Bit#(StringIdxWidth) StringIdx;
typedef TLog#(MaxFetchLen) LIdxWidth;
typedef Bit#(LIdxWidth) LIdx;

module mkMaxcommonsubseqRequest#(MaxcommonsubseqIndication indication,
			DmaReadServer#(busWidth)   setupA_read_server,
			DmaReadServer#(busWidth)   setupB_read_server,
			DmaWriteServer#(busWidth)   fetch_write_server )(MaxcommonsubseqRequest)

   provisos(Add#(a__, 8, busWidth),
	    Div#(busWidth,8,nc),
	    Mul#(nc,8,busWidth),
	    Add#(1, b__, nc),
	    Add#(c__, 32, busWidth),
	    Add#(1, d__, TDiv#(busWidth, 32)),
	    Mul#(TDiv#(busWidth, 32), 32, busWidth),
            Mul#(TDiv#(busWidth, 16), 16, busWidth),
            Add#(1, e__, TDiv#(busWidth, 16)),
            Add#(1, f__, TMul#(2, TDiv#(busWidth, 16))),
            Add#(TDiv#(busWidth, 16), g__, TMul#(2, TDiv#(busWidth, 16))));

  Reg#(Bit#(7)) aLenReg <- mkReg(0);
  Reg#(Bit#(7)) bLenReg <- mkReg(0);
  Reg#(Bit#(14)) rLenReg <- mkReg(0);
  Reg#(Bit#(7)) ii <- mkReg(0);
  Reg#(Bit#(7)) jj <- mkReg(0);
   Reg#(Bit#(8)) aData <- mkReg(0);
   Reg#(Bit#(8)) bData <- mkReg(0);
   Reg#(Bit#(16)) lim1jm1 <- mkReg(0);
   Reg#(Bit#(16)) lim1j <- mkReg(0);
   Reg#(Bit#(16)) lijm1 <- mkReg(0);
   BRAM2Port#(StringIdx, Bit#(8)) strA  <- mkBRAM2Server(defaultValue);
   BRAM2Port#(StringIdx, Bit#(8)) strB <- mkBRAM2Server(defaultValue);
   BRAM2Port#(LIdx, Bit#(16)) matL <- mkBRAM2Server(defaultValue);

   BRAMReadClient#(StringIdxWidth,busWidth) n2a <- mkBRAMReadClient(strA.portB);
   mkConnection(n2a.dmaClient, setupA_read_server);
   BRAMReadClient#(StringIdxWidth,busWidth) n2b <- mkBRAMReadClient(strB.portB);
   mkConnection(n2b.dmaClient, setupB_read_server);
   BRAMWriteClient#(LIdxWidth, busWidth) l2n <- mkBRAMWriteClient(matL.portB);
   mkConnection(l2n.dmaClient, fetch_write_server);

   FIFOF#(void) aReady <- mkFIFOF;
   FIFOF#(void) bReady <- mkFIFOF;
   FIFOF#(void) mReady <- mkFIFOF;

   Reg#(Bool) hirschARunning <- mkReg(False);

   FSM hirschA <- mkHirschA(strA.portA, strB.portA, matL.portA);
   FSM hirschB <- mkHirschB(strA.portA, strB.portA, matL.portA);

   // create BRAM Write client for matL

   rule finish_setupA;
      $display("finish setupA");
      let x <- n2a.finish;
      aReady.enq(?);
      indication.setupAComplete();
   endrule

   rule finish_setupB;
      $display("finish setupB");
      let x <- n2b.finish;
      bReady.enq(?);
      indication.setupBComplete();
   endrule

   rule finish_fetch;
      $display("finish fetch");
      let x <- l2n.finish;
      indication.fetchComplete();
   endrule

   rule hirschA_completion (hirschARunning && hirschA.done);
      hirschARunning <= False;
      indication.searchResult(22);
      endrule

   method Action setupA(Bit#(32) strPointer, Bit#(32) strLen);
      aLenReg <= truncate(strLen);
      $display("setupA %h %d", strPointer, strLen);
      n2a.start(strPointer, 0, 0, pack(truncate(strLen-1)));
   endmethod

   method Action setupB(Bit#(32) strPointer, Bit#(32) strLen);
      bLenReg <= truncate(strLen);
      $display("setupB %h %d", strPointer, strLen);
      n2b.start(strPointer, 0, 0, pack(truncate(strLen-1)));
   endmethod

   method Action fetch(Bit#(32) strPointer, Bit#(32) dest, Bit#(32) src, Bit#(32) strLen);
      //rLenReg <= truncate(strLen);
      $display("fetch %h %h %h %h", strPointer, dest, src, strLen);
      let bram_start_idx = pack(truncate(src));
      let bram_finish_idx = bram_start_idx+pack(truncate(strLen-1));
      l2n.start(strPointer, zeroExtend(dest), bram_start_idx, bram_finish_idx);
   endmethod

   method Action start(Bit#(32) alg);
      $display ("start %d", alg);
      case (alg)
	 0: begin
	       hirschA.start();
	       hirschARunning <= True;
	       end
	 1: hirschB.start();
//	 2: hirschC.start();
      endcase
   endmethod

endmodule

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

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

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

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

import FIFO::*;
import FIFOF::*;
import SpecialFIFOs::*;
import GetPut::*;
import StmtFSM::*;
//import Vector::*;
import BRAM::*;
//import Gearbox::*;
import Connectable::*;

//import AxiMasterSlave::*;
import Dma::*;
import DmaUtils::*;
import Dma2BRAM::*;

// algorithm
import HirschA::*;
import Hirsch::*;

/* This module solves the maximum common subsequence problem.
 * It finds the longest subsequence of characters present in both input strings
 * the subsequence does not have to be contiguous and the characters can have different locations
 * and offsets in the two strings, just so long as they occur in the same order
 *
 *  To initialize, load string A with request setupA, and wait for indication setup complete
 * Then load string B with request setupB, and wait for indication setup complete
 * To start the unit, signal start, and wait for searchResult, which will tell you the length
 * To retreive the result, use fetch and wait for fetchComplete
 */

/* First pass implements Hirschberg Algorithm A and the fetch call returns the L matrix
 */
interface MaxcommonsubseqRequest;
   method Action setupA(Bit#(32) strPointer, Bit#(32) strLen);
   method Action setupB(Bit#(32) strPointer, Bit#(32) strLen);
   method Action fetch(Bit#(32) strPointer, Bit#(32) dest, Bit#(32) src, Bit#(32) strLen);
   method Action start(Bit#(32) alg);
endinterface

interface MaxcommonsubseqIndication;
   method Action searchResult(Int#(32) v);
   method Action setupAComplete();
   method Action setupBComplete();
   method Action fetchComplete();
endinterface

typedef Bit#(64) DWord;
typedef Bit#(32) Word;

typedef 128 MaxStringLen;
typedef 16384 MaxFetchLen;
typedef TLog#(MaxStringLen) StringIdxWidth;
typedef Bit#(StringIdxWidth) StringIdx;
typedef TLog#(MaxFetchLen) LIdxWidth;
typedef Bit#(LIdxWidth) LIdx;

module mkMaxcommonsubseqRequest#(MaxcommonsubseqIndication indication,
			DmaReadServer#(busWidth)   setupA_read_server,
			DmaReadServer#(busWidth)   setupB_read_server,
			DmaWriteServer#(busWidth)   fetch_write_server )(MaxcommonsubseqRequest)

   provisos(Add#(a__, 8, busWidth),
	    Div#(busWidth,8,nc),
	    Mul#(nc,8,busWidth),
	    Add#(1, b__, nc),
	    Add#(c__, 32, busWidth),
	    Add#(1, d__, TDiv#(busWidth, 32)),
	    Mul#(TDiv#(busWidth, 32), 32, busWidth),
            Mul#(TDiv#(busWidth, 16), 16, busWidth),
            Add#(1, e__, TDiv#(busWidth, 16)),
            Add#(1, f__, TMul#(2, TDiv#(busWidth, 16))),
            Add#(TDiv#(busWidth, 16), g__, TMul#(2, TDiv#(busWidth, 16))));

  Reg#(Bit#(7)) aLenReg <- mkReg(0);
  Reg#(Bit#(7)) bLenReg <- mkReg(0);
  Reg#(Bit#(14)) rLenReg <- mkReg(0);
  Reg#(Bit#(7)) ii <- mkReg(0);
  Reg#(Bit#(7)) jj <- mkReg(0);
   Reg#(Bit#(8)) aData <- mkReg(0);
   Reg#(Bit#(8)) bData <- mkReg(0);
   Reg#(Bit#(16)) lim1jm1 <- mkReg(0);
   Reg#(Bit#(16)) lim1j <- mkReg(0);
   Reg#(Bit#(16)) lijm1 <- mkReg(0);
   BRAM2Port#(StringIdx, Bit#(8)) strA  <- mkBRAM2Server(defaultValue);
   BRAM2Port#(StringIdx, Bit#(8)) strB <- mkBRAM2Server(defaultValue);
   BRAM2Port#(LIdx, Bit#(16)) matL <- mkBRAM2Server(defaultValue);

   BRAMReadClient#(StringIdxWidth,busWidth) n2a <- mkBRAMReadClient(strA.portB);
   mkConnection(n2a.dmaClient, setupA_read_server);
   BRAMReadClient#(StringIdxWidth,busWidth) n2b <- mkBRAMReadClient(strB.portB);
   mkConnection(n2b.dmaClient, setupB_read_server);
   BRAMWriteClient#(LIdxWidth, busWidth) l2n <- mkBRAMWriteClient(matL.portB);
   mkConnection(l2n.dmaClient, fetch_write_server);

   FIFOF#(void) aReady <- mkFIFOF;
   FIFOF#(void) bReady <- mkFIFOF;
   FIFOF#(void) mReady <- mkFIFOF;

   // create BRAM Write client for matL

   rule finish_setupA;
      $display("finish setupA");
      let x <- n2a.finish;
      aReady.enq(?);
      indication.setupAComplete();
   endrule

   rule finish_setupB;
      $display("finish setupB");
      let x <- n2b.finish;
      bReady.enq(?);
      indication.setupBComplete();
   endrule

   rule finish_fetch;
      $display("finish fetch");
      let x <- l2n.finish;
      indication.fetchComplete();
   endrule

   mkHirschA(strA.portA, strB.portA, matL.portA);

   method Action setupA(Bit#(32) strPointer, Bit#(32) strLen);
      aLenReg <= truncate(strLen);
      $display("setupA %h %d", strPointer, strLen);
      n2a.start(strPointer, 0, 0, pack(truncate(strLen-1)));
   endmethod

   method Action setupB(Bit#(32) strPointer, Bit#(32) strLen);
      bLenReg <= truncate(strLen);
      $display("setupB %h %d", strPointer, strLen);
      n2b.start(strPointer, 0, 0, pack(truncate(strLen-1)));
   endmethod

   method Action fetch(Bit#(32) strPointer, Bit#(32) dest, Bit#(32) src, Bit#(32) strLen);
      //rLenReg <= truncate(strLen);
      $display("fetch %h %h %h %h", strPointer, dest, src, strLen);
      let bram_start_idx = pack(truncate(src));
      let bram_finish_idx = bram_start_idx+pack(truncate(strLen-1));
      l2n.start(strPointer, zeroExtend(dest), bram_start_idx, bram_finish_idx);
   endmethod

   method Action start(Bit#(32) alg);
      case (alg)
	 0: hirschA.start();
	 1: hirschB.start();
//	 2: hirschC.start();
      endcase
   endmethod

endmodule


pipelined header serializer to improve timing

// Copyright (c) 2016 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.

import BUtils::*;
import ClientServer::*;
import Connectable::*;
import CBus::*;
import ConfigReg::*;
import DbgDefs::*;
import DefaultValue::*;
import Ethernet::*;
import EthMac::*;
import GetPut::*;
import FIFOF::*;
import MemMgmt::*;
import MemTypes::*;
import MIMO::*;
import Pipe::*;
import PacketBuffer::*;
import PrintTrace::*;
import StoreAndForward::*;
import Stream::*;
import SpecialFIFOs::*;
import SharedBuff::*;
`include "ConnectalProjectConfig.bsv"
`include "Debug.defines"

typedef Bit#(9) EgressPort;

interface HeaderSerializer;
   interface PipeIn#(EgressPort) metadata;
   interface PipeIn#(ByteStream#(16)) writeServer;
   interface PipeOut#(ByteStream#(16)) writeClient;
   method Action set_verbosity(int verbosity);
endinterface

typedef TDiv#(PktDataWidth, 8) MaskWidth;
typedef TLog#(PktDataWidth) DataSize;
typedef TLog#(TDiv#(PktDataWidth, 8)) MaskSize;
typedef TAdd#(DataSize, 1) NumBits;
typedef TAdd#(MaskSize, 1) NumBytes;

typedef struct {
   UInt#(TAdd#(MaskSize, 1)) byte_shift;
   UInt#(TAdd#(DataSize, 1)) bit_shift;
   ByteStream#(16) flit;
} ReqT deriving (Bits);

(* synthesize *)
module mkHeaderSerializer(HeaderSerializer);
   `PRINT_DEBUG_MSG

   Reg#(Bit#(PktDataWidth)) data_buffered <- mkReg(0);
   Reg#(Bit#(MaskWidth)) mask_buffered <- mkReg(0);
   Reg#(UInt#(TAdd#(MaskSize, 1))) n_bytes_buffered <- mkReg(0);
   Reg#(UInt#(TAdd#(DataSize, 1))) n_bits_buffered <- mkReg(0);

   FIFOF#(ByteStream#(16)) data_in_ff <- mkSizedFIFOF(4);
   FIFOF#(ByteStream#(16)) data_out_ff <- mkSizedFIFOF(4);
   FIFOF#(EgressPort) meta_in_ff <- mkSizedFIFOF(16);

   FIFOF#(ReqT) send_frame_ff <- mkFIFOF;
   FIFOF#(ReqT) buff_frame_ff <- mkFIFOF;
   FIFOF#(ReqT) send_last2_ff <- mkFIFOF;
   FIFOF#(ReqT) send_last1_ff <- mkFIFOF;

   Array#(Reg#(Bool)) sop_buff <- mkCReg(2, False);

   rule rl_serialize_stage1;
      let v = data_in_ff.first;
      data_in_ff.deq;

      UInt#(NumBytes) n_bytes_used = countOnes(data_in_ff.first.mask);
      UInt#(NumBits) n_bits_used = cExtend(n_bytes_used) << 3;
      let total_bytes = n_bytes_buffered + n_bytes_used;
      let total_bits = n_bits_buffered + n_bits_used;

      if (v.sop) begin
         sop_buff[0] <= True;
      end

      // keep track of n_bytes_used and n_bytes_buffered, and decide what to do next.
      if (!v.eop) begin
         // new byte + existing byte more than one flit?
         if (total_bytes >= fromInteger(valueOf(MaskWidth))) begin
            $display("(%0d) send_frame %d ", $time, total_bytes);
            let req = ReqT {byte_shift: n_bytes_buffered, bit_shift: n_bits_buffered, flit: v};
            n_bytes_buffered <= total_bytes - 16;
            n_bits_buffered <= total_bits - 128;
            send_frame_ff.enq(req);
         end
         else begin
            $display("(%0d) buff_frame %d ", $time, total_bytes);
            let req = ReqT {byte_shift: n_bytes_buffered, bit_shift: n_bits_buffered, flit: v};
            n_bytes_buffered <= total_bytes;
            n_bits_buffered <= total_bits;
            buff_frame_ff.enq(req);
         end
      end
      else begin
         if (total_bytes >= fromInteger(valueOf(MaskWidth))) begin
            $display("(%0d) send_last2 %d ", $time, total_bytes);
            let req = ReqT {byte_shift: n_bytes_buffered, bit_shift: n_bits_buffered, flit: v};
            n_bytes_buffered <= total_bytes - 16;
            n_bits_buffered <= total_bits - 128;
            send_last2_ff.enq(req);
         end
         else begin
            $display("(%0d) send_last1 %d ", $time, total_bytes);
            let req = ReqT {byte_shift: n_bytes_buffered, bit_shift: n_bits_buffered, flit: v};
            n_bytes_buffered <= 0;
            n_bits_buffered <= 0;
            send_last1_ff.enq(req);
         end
      end

      dbprint(3, $format("HeaderSerializer:rl_serialize_stage1 maskwidth=%d buffered %d", fromInteger(valueOf(MaskWidth)), total_bytes));
      dbprint(3, $format("HeaderSerializer:rl_serialize_stage1 ", fshow(data_in_ff.first)));
   endrule

   (* mutually_exclusive = "rl_send_full_frame, rl_buffer_partial_frame, rl_eop_full_frame, rl_eop_partial_frame" *)
   rule rl_send_full_frame;
      let v = send_frame_ff.first;
      send_frame_ff.deq;
      let egress_port = meta_in_ff.first;
      // shift data by n_bits_buffered and concat;
      let data = v.flit.data << v.bit_shift | data_buffered;
      // update total byte buffered, 16 - xxx
      let n_bytes_used = fromInteger(valueOf(MaskWidth)) - v.byte_shift;
      UInt#(NumBits) n_bits_used = cExtend(n_bytes_used) << 3;
      data_buffered <= v.flit.data >> n_bits_used;
      mask_buffered <= v.flit.mask >> n_bytes_used;
      // send flit
      ByteStream#(16) eth = defaultValue;
      eth.sop = sop_buff[1];
      eth.eop = False;
      eth.mask = 'hffff;
      eth.data = data;
      sop_buff[1] <= False;
      // set egress_port to stream
      eth.user = zeroExtend(egress_port);
      data_out_ff.enq(eth);
      dbprint(3, $format("HeaderSerializer:rl_send_full_frame ", fshow(eth)));
   endrule

   rule rl_buffer_partial_frame;
      let v = buff_frame_ff.first;
      buff_frame_ff.deq;
      // shift and append
      let data = (v.flit.data << v.bit_shift) | data_buffered;
      // shift and append
      let mask = (v.flit.mask << v.byte_shift) | mask_buffered;
      // update buffered data
      data_buffered <= data;
      // update buffered mask
      mask_buffered <= mask;
      dbprint(3, $format("HeaderSerializer:rl_buffer_partial_frame "));
   endrule

   // FIXME: there may be a bug here, when last beat has eop enabled and more than 16 bytes left to send.
   rule rl_eop_full_frame;
      let v = send_last2_ff.first;
      send_last2_ff.deq;
      let egress_port = meta_in_ff.first;
      let data = v.flit.data << v.bit_shift | data_buffered;
      ByteStream#(16) eth = defaultValue;
      eth.sop = False;
      eth.eop = True;
      eth.mask = 'hffff;
      eth.data = data;
      eth.user = zeroExtend(egress_port);
      data_out_ff.enq(eth);
      dbprint(3, $format("HeaderSerializer:rl_eop_full_frame ", fshow(eth)));
      // eop, dequeue metadata
      meta_in_ff.deq;
   endrule

   rule rl_eop_partial_frame;
      let v = send_last1_ff.first;
      send_last1_ff.deq;
      let egress_port = meta_in_ff.first;
      let data = (v.flit.data << v.bit_shift) | data_buffered;
      let mask = (v.flit.mask << v.byte_shift) | mask_buffered;
      // send flit
      ByteStream#(16) eth = defaultValue;
      eth.sop = False;
      eth.eop = True;
      eth.mask = mask;
      eth.data = data;
      eth.user = zeroExtend(egress_port);
      data_out_ff.enq(eth);
      dbprint(3, $format("HeaderSerializer:rl_eop_partial_frame ", fshow(eth)));
      // eop, dequeue metadata
      meta_in_ff.deq;
   endrule

   interface metadata = toPipeIn(meta_in_ff);
   interface writeServer = toPipeIn(data_in_ff);
   interface writeClient = toPipeOut(data_out_ff);
   method Action set_verbosity(int verbosity);
      cf_verbosity <= verbosity;
   endmethod
endmodule

// Copyright (c) 2016 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.

import BUtils::*;
import ClientServer::*;
import Connectable::*;
import CBus::*;
import ConfigReg::*;
import DbgDefs::*;
import DefaultValue::*;
import Ethernet::*;
import EthMac::*;
import GetPut::*;
import FIFOF::*;
import MemMgmt::*;
import MemTypes::*;
import MIMO::*;
import Pipe::*;
import PacketBuffer::*;
import PrintTrace::*;
import StoreAndForward::*;
import Stream::*;
import SpecialFIFOs::*;
import SharedBuff::*;
`include "ConnectalProjectConfig.bsv"
`include "Debug.defines"

typedef Bit#(9) EgressPort;

interface HeaderSerializer;
   interface PipeIn#(EgressPort) metadata;
   interface PipeIn#(ByteStream#(16)) writeServer;
   interface PipeOut#(ByteStream#(16)) writeClient;
   method Action set_verbosity(int verbosity);
endinterface

typedef TDiv#(PktDataWidth, 8) MaskWidth;
typedef TLog#(PktDataWidth) DataSize;
typedef TLog#(TDiv#(PktDataWidth, 8)) MaskSize;
typedef TAdd#(DataSize, 1) NumBits;
typedef TAdd#(MaskSize, 1) NumBytes;

(* synthesize *)
module mkHeaderSerializer(HeaderSerializer);
   `PRINT_DEBUG_MSG

   FIFOF#(ByteStream#(16)) data_in_ff <- mkSizedFIFOF(4);
   FIFOF#(ByteStream#(16)) data_out_ff <- mkSizedFIFOF(4);
   FIFOF#(EgressPort) meta_in_ff <- mkSizedFIFOF(16);

   Array#(Reg#(Bool)) sop_buff <- mkCReg(3, False);
   Array#(Reg#(Bool)) eop_buff <- mkCReg(3, False);
   Array#(Reg#(Bit#(PktDataWidth))) data_buff <- mkCReg(3, 0);
   Array#(Reg#(Bit#(MaskWidth))) mask_buff <- mkCReg(3, 0);

   Reg#(Bool) sop_buffered <- mkReg(False);
   Reg#(Bool) eop_buffered <- mkReg(False);
   Reg#(Bit#(PktDataWidth)) data_buffered <- mkReg(0);
   Reg#(Bit#(MaskWidth)) mask_buffered <- mkReg(0);
   Reg#(UInt#(TAdd#(MaskSize, 1))) n_bytes_buffered <- mkReg(0);
   Reg#(UInt#(TAdd#(DataSize, 1))) n_bits_buffered <- mkReg(0);

   PulseWire w_send_frame <- mkPulseWire();
   PulseWire w_buff_frame <- mkPulseWire();
   PulseWire w_send_last2 <- mkPulseWire();
   PulseWire w_send_last1 <- mkPulseWire();

   Array#(Reg#(UInt#(NumBytes))) n_bytes <- mkCReg(2, 0);
   Array#(Reg#(UInt#(NumBits))) n_bits <- mkCReg(2, 0);

   // deq fifo
   // shift and append
   rule rl_serialize_stage1;
      data_in_ff.deq;
      let data_in_buff = data_in_ff.first.data;
      let eop = data_in_ff.first.eop;
      UInt#(NumBytes) n_bytes_used = countOnes(data_in_ff.first.mask);
      UInt#(NumBits) n_bits_used = cExtend(n_bytes_used) << 3;

      n_bytes[0] <= n_bytes_used;
      n_bits[0] <= n_bits_used;
      data_buff[0] <= data_in_ff.first.data;
      mask_buff[0] <= data_in_ff.first.mask;
      eop_buff[0] <= data_in_ff.first.eop;

      if (data_in_ff.first.sop) begin
         sop_buff[0] <= True;
      end

      if (!eop) begin
         if (n_bytes_used + n_bytes_buffered >= fromInteger(valueOf(MaskWidth))) begin
            w_send_frame.send();
         end
         else begin
            w_buff_frame.send();
         end
      end
      else begin
         if (n_bytes_used + n_bytes_buffered >= fromInteger(valueOf(MaskWidth))) begin
            w_send_last2.send();
         end
         else begin
            w_send_last1.send();
         end
      end

      dbprint(3, $format("HeaderSerializer:rl_serialize_stage1 maskwidth=%d buffered %d nbytes %d nbits %d", fromInteger(valueOf(MaskWidth)), n_bytes_buffered, n_bytes_used, n_bits_used));
      dbprint(3, $format("HeaderSerializer:rl_serialize_stage1 ", fshow(data_in_ff.first)));
   endrule

   (* mutually_exclusive = "rl_send_full_frame, rl_buffer_partial_frame, rl_eop_full_frame, rl_eop_partial_frame" *)
   rule rl_send_full_frame if (w_send_frame);
      let egress_port = meta_in_ff.first;
      let data = data_buff[1] << n_bits_buffered | data_buffered;
      let n_bytes_used = fromInteger(valueOf(MaskWidth)) - n_bytes_buffered;
      UInt#(NumBits) n_bits_used = cExtend(n_bytes_used) << 3;
      n_bytes_buffered <= n_bytes[1] - n_bytes_used;
      n_bits_buffered <= n_bits[1] - n_bits_used;
      data_buffered <= data_buff[1] >> n_bits_used;
      mask_buffered <= mask_buff[1] >> n_bytes_used;
      ByteStream#(16) eth = defaultValue;
      eth.sop = sop_buff[1];
      eth.eop = False;
      eth.mask = 'hffff;
      eth.data = data;
      // set egress_port to stream
      eth.user = zeroExtend(egress_port);
      sop_buff[1] <= False;
      data_out_ff.enq(eth);
      dbprint(3, $format("HeaderSerializer:rl_send_full_frame n_bytes_buffered=%d", n_bytes[1] - n_bytes_used, fshow(eth)));
   endrule

   rule rl_buffer_partial_frame if (w_buff_frame);
      let n_bytes_used = n_bytes[1] + n_bytes_buffered;
      UInt#(NumBits) n_bits_used = cExtend(n_bytes_used) << 3;
      let data = (data_buff[1] << n_bits_buffered) | data_buffered;
      let mask = (mask_buff[1] << n_bytes_buffered) | mask_buffered;
      n_bytes_buffered <= n_bytes_used;
      n_bits_buffered <= n_bits_used;
      data_buffered <= data;
      mask_buffered <= mask;
      dbprint(3, $format("HeaderSerializer:rl_buffer_partial_frame n_bytes_buffered=%d", n_bytes_used));
   endrule

   rule rl_eop_full_frame if (w_send_last2);
      let egress_port = meta_in_ff.first;
      let data = data_buff[1] << n_bits_buffered | data_buffered;
      let n_bytes_used = fromInteger(valueOf(MaskWidth)) - n_bytes_buffered;
      UInt#(NumBits) n_bits_used = cExtend(n_bytes_used) << 3;
      n_bytes_buffered <= n_bytes[1] - n_bytes_used;
      n_bits_buffered <= n_bits[1] - n_bits_used;
      ByteStream#(16) eth = defaultValue;
      eth.sop = False;
      eth.eop = True;
      eth.mask = 'hffff;
      eth.data = data;
      eth.user = zeroExtend(egress_port);
      data_out_ff.enq(eth);
      dbprint(3, $format("HeaderSerializer:rl_eop_full_frame n_bytes_buffered=%d", n_bytes[1] - n_bytes_used));
      // eop, dequeue metadata
      meta_in_ff.deq;
   endrule

   rule rl_eop_partial_frame if (w_send_last1);
      let egress_port = meta_in_ff.first;
      let data = (data_buff[1] << n_bits_buffered) | data_buffered;
      let mask = (mask_buff[1] << n_bytes_buffered) | mask_buffered;
      n_bytes_buffered <= 0;
      n_bits_buffered <= 0;
      ByteStream#(16) eth = defaultValue;
      eth.sop = False;
      eth.eop = True;
      eth.mask = mask;
      eth.data = data;
      eth.user = zeroExtend(egress_port);
      data_out_ff.enq(eth);
      dbprint(3, $format("HeaderSerializer:rl_eop_partial_frame ", fshow(eth)));
      // eop, dequeue metadata
      meta_in_ff.deq;
   endrule

   interface metadata = toPipeIn(meta_in_ff);
   interface writeServer = toPipeIn(data_in_ff);
   interface writeClient = toPipeOut(data_out_ff);
   method Action set_verbosity(int verbosity);
      cf_verbosity <= verbosity;
   endmethod
endmodule


conditionalize bluescope in HdmiDisplay

conditionalize bluescope in HdmiDisplay

Change-Id: I3143b44788f0d085c9723367b40e67e7a6f7e523

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

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

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

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

import FIFO::*;
import FIFOF::*;
import BRAMFIFO::*;
import Vector::*;
import Clocks::*;
import GetPut::*;
import ClientServer::*;
import PCIE::*;
import GetPutWithClocks::*;
import Connectable::*;
import PortalMemory::*;
import MemTypes::*;
import DmaUtils::*;
import ClientServer::*;
import AxiMasterSlave::*;
import MemreadEngine::*;
import HDMI::*;
import XADC::*;
import YUV::*;
import Gearbox::*;
import MIMO::*;
import BlueScope::*;

interface HdmiDisplayRequest;
   method Action startFrameBuffer(Int#(32) base, UInt#(32) rows, UInt#(32) cols, UInt#(32) pixels);
   method Action stopFrameBuffer();
   method Action getTransferStats();
   method Action setTraceTransfers(Bit#(1) trace);
endinterface
interface HdmiDisplayIndication;
   method Action transferStarted(Bit#(32) count);
   method Action transferFinished(Bit#(32) count);
   method Action transferStats(Bit#(32) count, Bit#(32) transferCycles, Bit#(64) sumOfCycles);
endinterface

interface HdmiDisplay;
`ifdef HDMI_BLUESCOPE
   interface BlueScopeRequest  bluescopeRequest;
   interface ObjectWriteClient#(64) bluescopeWriteClient;
`endif
    interface HdmiDisplayRequest displayRequest;
    interface HdmiInternalRequest internalRequest;
    interface ObjectReadClient#(64) dmaClient;
    interface HDMI#(Bit#(HdmiBits)) hdmi;
    interface XADC xadc;
endinterface

module mkHdmiDisplay#(Clock hdmi_clock,
		      HdmiDisplayIndication hdmiDisplayIndication,
		      HdmiInternalIndication hdmiInternalIndication
`ifdef HDMI_BLUESCOPE
		      , BlueScopeIndication bluescopeIndication
`endif
)(HdmiDisplay);
    Clock defaultClock <- exposeCurrentClock;
    Reset defaultReset <- exposeCurrentReset;
    Reset hdmi_reset <- mkAsyncReset(2, defaultReset, hdmi_clock);

   Reg#(UInt#(16)) rowsReg <- mkReg(1080);
   Reg#(UInt#(16)) colsReg <- mkReg(1920);
   Reg#(UInt#(24)) pixelCountReg <- mkReg(1080*1920);

    Reg#(Bool) sendVsyncIndication <- mkReg(False);
    SyncPulseIfc vsyncPulse <- mkSyncHandshake(hdmi_clock, hdmi_reset, defaultClock);
    Reg#(Bit#(1)) bozobit <- mkReg(0, clocked_by hdmi_clock, reset_by hdmi_reset);

    Reg#(Maybe#(Bit#(32))) referenceReg <- mkReg(tagged Invalid);
    FIFO#(Bit#(64)) mrFifo <- mkSizedBRAMFIFO(1024);
    MemreadEngine#(64,16) memreadEngine <- mkMemreadEngine;

    HdmiGenerator#(Rgb888) hdmiGen <- mkHdmiGenerator(defaultClock, defaultReset,
							vsyncPulse, hdmiInternalIndication, clocked_by hdmi_clock, reset_by hdmi_reset);
`ifndef ZC706
   Rgb888ToYyuv converter <- mkRgb888ToYyuv(clocked_by hdmi_clock, reset_by hdmi_reset);
   mkConnection(hdmiGen.rgb888, converter.rgb888);
   HDMI#(Bit#(HdmiBits)) hdmisignals <- mkHDMI(converter.yyuv, clocked_by hdmi_clock, reset_by hdmi_reset);
`else
   HDMI#(Bit#(HdmiBits)) hdmisignals <- mkHDMI(hdmiGen.rgb888, clocked_by hdmi_clock, reset_by hdmi_reset);
`endif
`ifdef HDMI_BLUESCOPE
   let bluescope <- mkSyncBlueScope(65536, bluescopeIndication, hdmi_clock, hdmi_reset, defaultClock, defaultReset);
   MIMO#(1, 16, 64, Bit#(4)) mimo <- mkMIMO(MIMOConfiguration { unguarded: False, bram_based: False }, clocked_by hdmi_clock, reset_by hdmi_reset);
   Reg#(Bool) triggered <- mkReg(False, clocked_by hdmi_clock, reset_by hdmi_reset);
   rule toGearbox if ((hdmisignals.hdmi_vsync == 1) || triggered);
      Bit#(4) v = 0;
      v[0] = hdmisignals.hdmi_vsync;
      v[1] = hdmisignals.hdmi_de;
      v[2] = hdmisignals.hdmi_hsync;
      v[3] = hdmisignals.hdmi_vsync;
      triggered <= True;
      if (mimo.enqReadyN(1))
	 mimo.enq(1, cons(v,nil));
      else
	 $display("mimo.stalled mimo.count=%d", mimo.count);
   endrule
   rule gearboxToBlueScope if (mimo.deqReadyN(16));
      Bit#(64) v = pack(mimo.first());
      mimo.deq(16);
      bluescope.dataIn(v, v);
   endrule
`endif

   SyncFIFOIfc#(Bit#(64)) synchronizer <- mkSyncFIFO(32, defaultClock, defaultReset, hdmi_clock);
   rule fromMemread;
      let v <- toGet(memreadEngine.dataPipes[0]).get;
      mrFifo.enq(v);
   endrule
   rule toSynch;
      let v <- toGet(mrFifo).get();
      synchronizer.enq(v);
   endrule
   Reg#(Bit#(1)) evenOdd <- mkReg(0, clocked_by hdmi_clock, reset_by hdmi_reset);
   Reg#(Vector#(2,Bit#(32))) doublePixelReg <- mkReg(unpack(0), clocked_by hdmi_clock, reset_by hdmi_reset);
   rule doPut;
      Vector#(2,Bit#(32)) doublePixel = doublePixelReg;
      let pixel = doublePixel[evenOdd];
      if (evenOdd == 0) begin
	 doublePixel = unpack(synchronizer.first);
	 synchronizer.deq;
	 pixel = doublePixel[0];
      end
      doublePixelReg <= doublePixel;
      evenOdd <= evenOdd + 1;
      hdmiGen.request.put(pixel);
   endrule

   Reg#(Bit#(32)) transferCount <- mkReg(0);
   Reg#(Bit#(32)) transferCyclesSnapshot <- mkReg(0);
   Reg#(Bit#(32)) transferCycles <- mkReg(0);
   Reg#(Bit#(48)) transferSumOfCycles<- mkReg(0);
   Reg#(Bit#(32)) vsyncCount <- mkReg(0);

   FIFOF#(Bool) vsyncFifo <- mkFIFOF();
   rule vsyncrule if (vsyncPulse.pulse());
      vsyncCount <= vsyncCount + 1;
      if (vsyncFifo.notFull())
	 vsyncFifo.enq(True);
   endrule

   Reg#(Bool) traceTransfers <- mkReg(False);
   rule notransfer if (referenceReg matches tagged Invalid);
      vsyncFifo.deq();
   endrule
   rule startTransfer if (referenceReg matches tagged Valid .reference);
      memreadEngine.readServers[0].request.put(MemengineCmd{pointer:reference, base:0, len:pack(extend(pixelCountReg))*4, burstLen:64});
      if (traceTransfers)
	 hdmiDisplayIndication.transferStarted(transferCount);
      transferCyclesSnapshot <= transferCycles;
      vsyncFifo.deq();
   endrule
   rule countCycles;
      transferCycles <= transferCycles + 1;
   endrule
   rule finishTransferRule;
      let b <- memreadEngine.readServers[0].response.get;
      transferCount <= transferCount + 1;
      let tc = transferCycles - transferCyclesSnapshot;
      transferSumOfCycles <= transferSumOfCycles + extend(tc);
      if (traceTransfers)
	 hdmiDisplayIndication.transferFinished(transferCount);
   endrule

    rule bozobit_rule;
        bozobit <= ~bozobit;
    endrule

    interface HdmiDisplayRequest displayRequest;
	method Action startFrameBuffer(Int#(32) base, UInt#(32) rows, UInt#(32) cols, UInt#(32) pixels);
	   rowsReg <= truncate(rows);
	   colsReg <= truncate(cols);
	   pixelCountReg <= truncate(pixels);
	   $display("startFrameBuffer %h", base);
           referenceReg <= tagged Valid truncate(pack(base));
	   hdmiGen.control.setTestPattern(0);
	endmethod
       method Action stopFrameBuffer();
	  referenceReg <= tagged Invalid;
	  hdmiGen.control.setTestPattern(1);
       endmethod
       method Action getTransferStats();
          hdmiDisplayIndication.transferStats(transferCount, transferCycles-transferCyclesSnapshot, extend(transferSumOfCycles));
       endmethod
       method Action setTraceTransfers(Bit#(1) trace);
	  traceTransfers <= unpack(trace);
       endmethod
    endinterface: displayRequest

    interface ObjectReadClient dmaClient = memreadEngine.dmaClient;
    interface HDMI hdmi = hdmisignals;
    interface HdmiInternalRequest internalRequest = hdmiGen.control;
`ifdef HDMI_BLUESCOPE
    interface BlueScopeRequest bluescopeRequest = bluescope.requestIfc;
    interface ObjectWriteClient bluescopeWriteClient = bluescope.writeClient;
`endif
    interface XADC xadc;
        method Bit#(4) gpio;
            return { bozobit, hdmisignals.hdmi_vsync,
                hdmisignals.hdmi_data[8], hdmisignals.hdmi_data[0]};
                //hdmiGen.hdmi.hsync, hdmi_de};
        endmethod
    endinterface: xadc
endmodule

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

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

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

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

import FIFO::*;
import FIFOF::*;
import BRAMFIFO::*;
import Vector::*;
import Clocks::*;
import GetPut::*;
import ClientServer::*;
import PCIE::*;
import GetPutWithClocks::*;
import Connectable::*;
import PortalMemory::*;
import MemTypes::*;
import DmaUtils::*;
import ClientServer::*;
import AxiMasterSlave::*;
import MemreadEngine::*;
import HDMI::*;
import XADC::*;
import YUV::*;
import Gearbox::*;
import MIMO::*;
import BlueScope::*;

interface HdmiDisplayRequest;
   method Action startFrameBuffer(Int#(32) base, UInt#(32) rows, UInt#(32) cols, UInt#(32) pixels);
   method Action stopFrameBuffer();
   method Action getTransferStats();
   method Action setTraceTransfers(Bit#(1) trace);
endinterface
interface HdmiDisplayIndication;
   method Action transferStarted(Bit#(32) count);
   method Action transferFinished(Bit#(32) count);
   method Action transferStats(Bit#(32) count, Bit#(32) transferCycles, Bit#(64) sumOfCycles);
endinterface

interface HdmiDisplay;
   interface BlueScopeRequest  bluescopeRequest;
    interface HdmiDisplayRequest displayRequest;
    interface HdmiInternalRequest internalRequest;
    interface ObjectReadClient#(64) dmaClient;
   interface ObjectWriteClient#(64) bluescopeWriteClient;
    interface HDMI#(Bit#(HdmiBits)) hdmi;
    interface XADC xadc;
endinterface

module mkHdmiDisplay#(Clock hdmi_clock,
		      HdmiDisplayIndication hdmiDisplayIndication,
		      HdmiInternalIndication hdmiInternalIndication,
		      BlueScopeIndication bluescopeIndication)(HdmiDisplay);
    Clock defaultClock <- exposeCurrentClock;
    Reset defaultReset <- exposeCurrentReset;
    Reset hdmi_reset <- mkAsyncReset(2, defaultReset, hdmi_clock);

   Reg#(UInt#(16)) rowsReg <- mkReg(1080);
   Reg#(UInt#(16)) colsReg <- mkReg(1920);
   Reg#(UInt#(24)) pixelCountReg <- mkReg(1080*1920);

    Reg#(Bool) sendVsyncIndication <- mkReg(False);
    SyncPulseIfc vsyncPulse <- mkSyncHandshake(hdmi_clock, hdmi_reset, defaultClock);
    Reg#(Bit#(1)) bozobit <- mkReg(0, clocked_by hdmi_clock, reset_by hdmi_reset);

    Reg#(Maybe#(Bit#(32))) referenceReg <- mkReg(tagged Invalid);
    FIFO#(Bit#(64)) mrFifo <- mkSizedBRAMFIFO(1024);
    MemreadEngine#(64,16) memreadEngine <- mkMemreadEngine;

    HdmiGenerator#(Rgb888) hdmiGen <- mkHdmiGenerator(defaultClock, defaultReset,
							vsyncPulse, hdmiInternalIndication, clocked_by hdmi_clock, reset_by hdmi_reset);
`ifndef ZC706
   Rgb888ToYyuv converter <- mkRgb888ToYyuv(clocked_by hdmi_clock, reset_by hdmi_reset);
   mkConnection(hdmiGen.rgb888, converter.rgb888);
   HDMI#(Bit#(HdmiBits)) hdmisignals <- mkHDMI(converter.yyuv, clocked_by hdmi_clock, reset_by hdmi_reset);
`else
   HDMI#(Bit#(HdmiBits)) hdmisignals <- mkHDMI(hdmiGen.rgb888, clocked_by hdmi_clock, reset_by hdmi_reset);
`endif
   let bluescope <- mkSyncBlueScope(65536, bluescopeIndication, hdmi_clock, hdmi_reset, defaultClock, defaultReset);
   //Gearbox#(1, 16, Bit#(4)) gearbox <- mk1toNGearbox(hdmi_clock, hdmi_reset, hdmi_clock, hdmi_reset);
   MIMO#(1, 16, 64, Bit#(4)) mimo <- mkMIMO(MIMOConfiguration { unguarded: False, bram_based: False }, clocked_by hdmi_clock, reset_by hdmi_reset);
   Reg#(Bool) triggered <- mkReg(False, clocked_by hdmi_clock, reset_by hdmi_reset);
   rule toGearbox if ((hdmisignals.hdmi_vsync == 1) || triggered);
      Bit#(4) v = 0;
      v[0] = hdmisignals.hdmi_vsync;
      v[1] = hdmisignals.hdmi_de;
      v[2] = hdmisignals.hdmi_hsync;
      v[3] = hdmisignals.hdmi_vsync;
      triggered <= True;
      if (mimo.enqReadyN(1))
	 mimo.enq(1, cons(v,nil));
      else
	 $display("mimo.stalled mimo.count=%d", mimo.count);
   endrule
   rule gearboxToBlueScope if (mimo.deqReadyN(16));
      Bit#(64) v = pack(mimo.first());
      mimo.deq(16);
      bluescope.dataIn(v, v);
   endrule

   SyncFIFOIfc#(Bit#(64)) synchronizer <- mkSyncFIFO(32, defaultClock, defaultReset, hdmi_clock);
   rule fromMemread;
      let v <- toGet(memreadEngine.dataPipes[0]).get;
      mrFifo.enq(v);
   endrule
   rule toSynch;
      let v <- toGet(mrFifo).get();
      synchronizer.enq(v);
   endrule
   Reg#(Bit#(1)) evenOdd <- mkReg(0, clocked_by hdmi_clock, reset_by hdmi_reset);
   Reg#(Vector#(2,Bit#(32))) doublePixelReg <- mkReg(unpack(0), clocked_by hdmi_clock, reset_by hdmi_reset);
   rule doPut;
      Vector#(2,Bit#(32)) doublePixel = doublePixelReg;
      let pixel = doublePixel[evenOdd];
      if (evenOdd == 0) begin
	 doublePixel = unpack(synchronizer.first);
	 synchronizer.deq;
	 pixel = doublePixel[0];
      end
      doublePixelReg <= doublePixel;
      evenOdd <= evenOdd + 1;
      hdmiGen.request.put(pixel);
   endrule

   Reg#(Bit#(32)) transferCount <- mkReg(0);
   Reg#(Bit#(32)) transferCyclesSnapshot <- mkReg(0);
   Reg#(Bit#(32)) transferCycles <- mkReg(0);
   Reg#(Bit#(48)) transferSumOfCycles<- mkReg(0);
   Reg#(Bit#(32)) vsyncCount <- mkReg(0);

   FIFOF#(Bool) vsyncFifo <- mkFIFOF();
   rule vsyncrule if (vsyncPulse.pulse());
      vsyncCount <= vsyncCount + 1;
      if (vsyncFifo.notFull())
	 vsyncFifo.enq(True);
   endrule

   Reg#(Bool) traceTransfers <- mkReg(False);
   rule notransfer if (referenceReg matches tagged Invalid);
      vsyncFifo.deq();
   endrule
   rule startTransfer if (referenceReg matches tagged Valid .reference);
      memreadEngine.readServers[0].request.put(MemengineCmd{pointer:reference, base:0, len:pack(extend(pixelCountReg))*4, burstLen:64});
      if (traceTransfers)
	 hdmiDisplayIndication.transferStarted(transferCount);
      transferCyclesSnapshot <= transferCycles;
      vsyncFifo.deq();
   endrule
   rule countCycles;
      transferCycles <= transferCycles + 1;
   endrule
   rule finishTransferRule;
      let b <- memreadEngine.readServers[0].response.get;
      transferCount <= transferCount + 1;
      let tc = transferCycles - transferCyclesSnapshot;
      transferSumOfCycles <= transferSumOfCycles + extend(tc);
      if (traceTransfers)
	 hdmiDisplayIndication.transferFinished(transferCount);
   endrule

    rule bozobit_rule;
        bozobit <= ~bozobit;
    endrule

    interface HdmiDisplayRequest displayRequest;
	method Action startFrameBuffer(Int#(32) base, UInt#(32) rows, UInt#(32) cols, UInt#(32) pixels);
	   rowsReg <= truncate(rows);
	   colsReg <= truncate(cols);
	   pixelCountReg <= truncate(pixels);
	   $display("startFrameBuffer %h", base);
           referenceReg <= tagged Valid truncate(pack(base));
	   hdmiGen.control.setTestPattern(0);
	endmethod
       method Action stopFrameBuffer();
	  referenceReg <= tagged Invalid;
	  hdmiGen.control.setTestPattern(1);
       endmethod
       method Action getTransferStats();
          hdmiDisplayIndication.transferStats(transferCount, transferCycles-transferCyclesSnapshot, extend(transferSumOfCycles));
       endmethod
       method Action setTraceTransfers(Bit#(1) trace);
	  traceTransfers <= unpack(trace);
       endmethod
    endinterface: displayRequest

    interface ObjectReadClient dmaClient = memreadEngine.dmaClient;
    interface HDMI hdmi = hdmisignals;
    interface HdmiInternalRequest internalRequest = hdmiGen.control;
    interface BlueScopeRequest bluescopeRequest = bluescope.requestIfc;
    interface ObjectWriteClient bluescopeWriteClient = bluescope.writeClient;
    interface XADC xadc;
        method Bit#(4) gpio;
            return { bozobit, hdmisignals.hdmi_vsync,
                hdmisignals.hdmi_data[8], hdmisignals.hdmi_data[0]};
                //hdmiGen.hdmi.hsync, hdmi_de};
        endmethod
    endinterface: xadc
endmodule


update doublePixelReg

update doublePixelReg

Change-Id: I39ff50616d88d1a203fd1230c7622e8bea38c829

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

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

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

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

import FIFO::*;
import FIFOF::*;
import Vector::*;
import Clocks::*;
import GetPut::*;
import PCIE::*;
import GetPutWithClocks::*;
import Connectable::*;
import PortalMemory::*;
import Dma::*;
import DmaUtils::*;
import AxiMasterSlave::*;
import MemreadEngine::*;
import HDMI::*;
import XADC::*;
import YUV::*;

interface HdmiDisplayRequest;
   method Action startFrameBuffer0(Int#(32) base);
   method Action getTransferStats();
   method Action setTraceTransfers(Bool trace);
endinterface
interface HdmiDisplayIndication;
   method Action transferStarted(Bit#(32) count);
   method Action transferFinished(Bit#(32) count);
   method Action transferStats(Bit#(32) count, Bit#(32) transferCycles, Bit#(64) sumOfCycles);
endinterface

interface HdmiDisplay;
    interface HdmiDisplayRequest displayRequest;
    interface HdmiInternalRequest internalRequest;
    interface ObjectReadClient#(64) dmaClient;
    interface HDMI hdmi;
    interface XADC xadc;
endinterface

module mkHdmiDisplay#(Clock hdmi_clock,
		      HdmiDisplayIndication hdmiDisplayIndication,
		      HdmiInternalIndication hdmiInternalIndication)(HdmiDisplay);
    Clock defaultClock <- exposeCurrentClock;
    Reset defaultReset <- exposeCurrentReset;
    Reset hdmi_reset <- mkAsyncReset(2, defaultReset, hdmi_clock);
    Reg#(Bool) sendVsyncIndication <- mkReg(False);
    SyncPulseIfc vsyncPulse <- mkSyncHandshake(hdmi_clock, hdmi_reset, defaultClock);
    Reg#(Bit#(1)) bozobit <- mkReg(0, clocked_by hdmi_clock, reset_by hdmi_reset);

    Reg#(Maybe#(Bit#(32))) referenceReg <- mkReg(tagged Invalid);
    FIFOF#(Bit#(64))   mrFifo  <- mkSizedFIFOF(32);
    MemreadEngine#(64) memreadEngine <- mkMemreadEngine(8, mrFifo);

    HdmiGenerator hdmiGen <- mkHdmiGenerator(defaultClock, defaultReset,
					     vsyncPulse, hdmiInternalIndication, clocked_by hdmi_clock, reset_by hdmi_reset);

   SyncFIFOIfc#(Bit#(64)) synchronizer <- mkSyncFIFO(32, defaultClock, defaultReset, hdmi_clock);
   rule doGet;
      let v = mrFifo.first();
      mrFifo.deq();
      synchronizer.enq(v);
   endrule
   Reg#(Bit#(1)) evenOdd <- mkReg(0, clocked_by hdmi_clock, reset_by hdmi_reset);
   Reg#(Vector#(2,Bit#(32))) doublePixelReg <- mkReg(unpack(0), clocked_by hdmi_clock, reset_by hdmi_reset);
   rule doPut;
      Vector#(2,Bit#(32)) doublePixel = doublePixelReg;
      let pixel = doublePixel[evenOdd];
      if (evenOdd == 0) begin
	 doublePixel = unpack(synchronizer.first);
	 synchronizer.deq;
	 pixel = doublePixel[0];
      end
      doublePixelReg <= doublePixel;
      evenOdd <= evenOdd + 1;
      hdmiGen.request.put(pixel);
   endrule

   FIFOF#(Bool) vsyncFifo <- mkFIFOF();
   rule vsyncrule if (vsyncPulse.pulse());
      if (vsyncFifo.notFull())
	 vsyncFifo.enq(True);
   endrule
   Reg#(Bit#(32)) transferCount <- mkReg(0);
   Reg#(Bit#(32)) transferCycles <- mkReg(0);
   Reg#(Bit#(48)) transferSumOfCycles<- mkReg(0);

   Reg#(Bool) traceTransfers <- mkReg(False);
   rule notransfer if (referenceReg matches tagged Invalid);
      vsyncFifo.deq();
   endrule
   rule startTransfer if (referenceReg matches tagged Valid .reference);
      memreadEngine.start(reference, 0, (1080*1920)*4, 64);
      if (traceTransfers)
	 hdmiDisplayIndication.transferStarted(transferCount);
      transferCycles <= 0;
      vsyncFifo.deq();
   endrule
   rule countCycles;
      transferCycles <= transferCycles + 1;
   endrule
   rule finishTransferRule;
      let b <- memreadEngine.finish();
      transferCount <= transferCount + 1;
      transferSumOfCycles <= transferSumOfCycles + extend(transferCycles);
      if (traceTransfers)
	 hdmiDisplayIndication.transferFinished(transferCount);
   endrule

    rule bozobit_rule;
        bozobit <= ~bozobit;
    endrule

    interface HdmiDisplayRequest displayRequest;
	method Action startFrameBuffer0(Int#(32) base);
	    $display("startFrameBuffer %h", base);
            referenceReg <= tagged Valid truncate(pack(base));
	    hdmiGen.control.setTestPattern(0);
	endmethod
       method Action getTransferStats();
          hdmiDisplayIndication.transferStats(transferCount, transferCycles, extend(transferSumOfCycles));
       endmethod
       method Action setTraceTransfers(Bool trace);
	  traceTransfers <= trace;
       endmethod
    endinterface: displayRequest

    interface ObjectReadClient dmaClient = memreadEngine.dmaClient;
    interface HDMI hdmi = hdmiGen.hdmi;
    interface HdmiInternalRequest internalRequest = hdmiGen.control;
    interface XADC xadc;
        method Bit#(4) gpio;
            return { bozobit, hdmiGen.hdmi.vsync,
                hdmiGen.hdmi.data[8], hdmiGen.hdmi.data[0]};
                //hdmiGen.hdmi.hsync, hdmi_de};
        endmethod
    endinterface: xadc
endmodule

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

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

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

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

import FIFO::*;
import FIFOF::*;
import Vector::*;
import Clocks::*;
import GetPut::*;
import PCIE::*;
import GetPutWithClocks::*;
import Connectable::*;
import PortalMemory::*;
import Dma::*;
import DmaUtils::*;
import AxiMasterSlave::*;
import MemreadEngine::*;
import HDMI::*;
import XADC::*;
import YUV::*;

interface HdmiDisplayRequest;
   method Action startFrameBuffer0(Int#(32) base);
   method Action getTransferStats();
   method Action setTraceTransfers(Bool trace);
endinterface
interface HdmiDisplayIndication;
   method Action transferStarted(Bit#(32) count);
   method Action transferFinished(Bit#(32) count);
   method Action transferStats(Bit#(32) count, Bit#(32) transferCycles, Bit#(64) sumOfCycles);
endinterface

interface HdmiDisplay;
    interface HdmiDisplayRequest displayRequest;
    interface HdmiInternalRequest internalRequest;
    interface ObjectReadClient#(64) dmaClient;
    interface HDMI hdmi;
    interface XADC xadc;
endinterface

module mkHdmiDisplay#(Clock hdmi_clock,
		      HdmiDisplayIndication hdmiDisplayIndication,
		      HdmiInternalIndication hdmiInternalIndication)(HdmiDisplay);
    Clock defaultClock <- exposeCurrentClock;
    Reset defaultReset <- exposeCurrentReset;
    Reset hdmi_reset <- mkAsyncReset(2, defaultReset, hdmi_clock);
    Reg#(Bool) sendVsyncIndication <- mkReg(False);
    SyncPulseIfc vsyncPulse <- mkSyncHandshake(hdmi_clock, hdmi_reset, defaultClock);
    Reg#(Bit#(1)) bozobit <- mkReg(0, clocked_by hdmi_clock, reset_by hdmi_reset);

    Reg#(Maybe#(Bit#(32))) referenceReg <- mkReg(tagged Invalid);
    FIFOF#(Bit#(64))   mrFifo  <- mkSizedFIFOF(32);
    MemreadEngine#(64) memreadEngine <- mkMemreadEngine(8, mrFifo);

    HdmiGenerator hdmiGen <- mkHdmiGenerator(defaultClock, defaultReset,
					     vsyncPulse, hdmiInternalIndication, clocked_by hdmi_clock, reset_by hdmi_reset);

   SyncFIFOIfc#(Bit#(64)) synchronizer <- mkSyncFIFO(32, defaultClock, defaultReset, hdmi_clock);
   rule doGet;
      let v = mrFifo.first();
      mrFifo.deq();
      synchronizer.enq(v);
   endrule
   Reg#(Bit#(1)) evenOdd <- mkReg(0, clocked_by hdmi_clock, reset_by hdmi_reset);
   Reg#(Vector#(2,Bit#(32))) doublePixelReg <- mkReg(unpack(0), clocked_by hdmi_clock, reset_by hdmi_reset);
   rule doPut; // if (mimo.enqReadyN(2));
      Vector#(2,Bit#(32)) doublePixel = doublePixelReg;
      let pixel = doublePixel[evenOdd];
      if (evenOdd == 0) begin
	 doublePixel = unpack(synchronizer.first);
	 synchronizer.deq;
	 pixel = doublePixel[0];
      end
      evenOdd <= evenOdd + 1;
      hdmiGen.request.put(pixel);
   endrule

   FIFOF#(Bool) vsyncFifo <- mkFIFOF();
   rule vsyncrule if (vsyncPulse.pulse());
      if (vsyncFifo.notFull())
	 vsyncFifo.enq(True);
   endrule
   Reg#(Bit#(32)) transferCount <- mkReg(0);
   Reg#(Bit#(32)) transferCycles <- mkReg(0);
   Reg#(Bit#(48)) transferSumOfCycles<- mkReg(0);

   Reg#(Bool) traceTransfers <- mkReg(False);
   rule notransfer if (referenceReg matches tagged Invalid);
      vsyncFifo.deq();
   endrule
   rule startTransfer if (referenceReg matches tagged Valid .reference);
      memreadEngine.start(reference, 0, (1080*1920)*4, 64);
      if (traceTransfers)
	 hdmiDisplayIndication.transferStarted(transferCount);
      transferCycles <= 0;
      vsyncFifo.deq();
   endrule
   rule countCycles;
      transferCycles <= transferCycles + 1;
   endrule
   rule finishTransferRule;
      let b <- memreadEngine.finish();
      transferCount <= transferCount + 1;
      transferSumOfCycles <= transferSumOfCycles + extend(transferCycles);
      if (traceTransfers)
	 hdmiDisplayIndication.transferFinished(transferCount);
   endrule

    rule bozobit_rule;
        bozobit <= ~bozobit;
    endrule

    interface HdmiDisplayRequest displayRequest;
	method Action startFrameBuffer0(Int#(32) base);
	    $display("startFrameBuffer %h", base);
            referenceReg <= tagged Valid truncate(pack(base));
	    hdmiGen.control.setTestPattern(0);
	endmethod
       method Action getTransferStats();
          hdmiDisplayIndication.transferStats(transferCount, transferCycles, extend(transferSumOfCycles));
       endmethod
       method Action setTraceTransfers(Bool trace);
	  traceTransfers <= trace;
       endmethod
    endinterface: displayRequest

    interface ObjectReadClient dmaClient = memreadEngine.dmaClient;
    interface HDMI hdmi = hdmiGen.hdmi;
    interface HdmiInternalRequest internalRequest = hdmiGen.control;
    interface XADC xadc;
        method Bit#(4) gpio;
            return { bozobit, hdmiGen.hdmi.vsync,
                hdmiGen.hdmi.data[8], hdmiGen.hdmi.data[0]};
                //hdmiGen.hdmi.hsync, hdmi_de};
        endmethod
    endinterface: xadc
endmodule