clean up

clean up

// 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 FIFO::*;
import FIFOF::*;
import DefaultValue::*;
import Vector::*;
import BuildVector::*;
import GetPut::*;
import ClientServer::*;
import Connectable::*;
import Clocks::*;
import Gearbox::*;
import Pipe::*;
import RegFile::*;
import MemTypes::*;

import DbgTypes::*;
import Ethernet::*;
import EthMac::*;
//import GenericMatchTable::*;
import HostChannel::*;
import TxChannel::*;
//import RxChannel::*;
import ModifyMac::*;
import IPv4Parser::*;
import IPv4Route::*;
import MMU::*;
import MemMgmt::*;
import PacketBuffer::*;
import SharedBuff::*;
import StoreAndForward::*;
import Tap::*;
import TDM::*;
import TdmTypes::*;

interface TdmPipeline;
   interface Put#(PacketDataT#(64)) macRx;
   interface Get#(PacketDataT#(64)) macTx;
   interface PktWriteServer writeServer;
   interface Put#(TableEntry) add_entry;
   interface Put#(FlowId) delete_entry;
   interface Put#(Tuple2#(FlowId, ActionArg)) modify_entry;
   method MemMgmtDbgRec memMgmtDbg;
   method TDMDbgRec tdmDbg;
   method ActionValue#(PktBuffDbgRec) pktBuffDbg(Bit#(8) id);
   method MatchTableDbgRec matchTableDbg;
   method TxThruDbgRec ringToMacDbg;
endinterface

module mkTdmPipeline#(Clock txClock, Reset txReset
                     ,Clock rxClock, Reset rxReset
                     ,MemoryTestIndication indication
                     ,ConnectalMemory::MemServerIndication memServerInd
`ifdef DEBUG
                     ,MemMgmtIndication memTestInd
                     ,ConnectalMemory::MMUIndication mmuInd
`endif
   )(TdmPipeline);

   //RxChannel rxchan <- mkRxChannel(rxClock, rxReset);
   HostChannel hostchan <- mkHostChannel();
   TxChannel txchan <- mkTxChannel(txClock, txReset);

   IPv4Route ipv4Route <- mkIPv4Route(hostchan.next);
   ModifyMac modMac <- mkModifyMac(ipv4Route.next);
   TDM sched <- mkTDM(modMac.next, txchan);

   SharedBuffer#(12, 128, 1) mem <- mkSharedBuffer(vec(txchan.readClient)
                                                  ,vec(txchan.freeClient)
                                                  ,vec(hostchan.writeClient, modMac.writeClient)
                                                  ,vec(hostchan.mallocClient)
                                                  ,memServerInd
`ifdef DEBUG
                                                  ,memTestInd
                                                  ,mmuInd
`endif
                                                  );

   rule read_flow_id;
      let v <- toGet(ipv4Route.entry_added).get;
      indication.addEntryResp(v);
   endrule

   //interface macRx = rxchan.macRx;
   interface macTx = txchan.macTx;
   interface writeServer = hostchan.writeServer;
   interface add_entry = ipv4Route.add_entry;
   interface delete_entry = ipv4Route.delete_entry;
   interface modify_entry = ipv4Route.modify_entry;
   method matchTableDbg = ipv4Route.mdbg;
   method memMgmtDbg = mem.dbg;
   method tdmDbg = sched.dbg;
   //method ringToMacDbg = txchan.dbg;
   method ActionValue#(PktBuffDbgRec) pktBuffDbg(Bit#(8) id);
      PktBuffDbgRec v = defaultValue;
      case (id) matches
         0: v = hostchan.dbg;
         1: v = txchan.dbg;
         //2: v = rxchan.dbg;
      endcase
      return v;
   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 FIFO::*;
import FIFOF::*;
import DefaultValue::*;
import Vector::*;
import BuildVector::*;
import GetPut::*;
import ClientServer::*;
import Connectable::*;
import Clocks::*;
import Gearbox::*;
import Pipe::*;
import RegFile::*;
import MemTypes::*;

import DbgTypes::*;
import Ethernet::*;
import EthMac::*;
//import GenericMatchTable::*;
import HostChannel::*;
import TxChannel::*;
//import RxChannel::*;
import ModifyMac::*;
import IPv4Parser::*;
import IPv4Route::*;
import MMU::*;
import MemMgmt::*;
import PacketBuffer::*;
import SharedBuff::*;
import StoreAndForward::*;
import Tap::*;
import TDM::*;
import TdmTypes::*;

interface TdmPipeline;
   interface Put#(PacketDataT#(64)) macRx;
   interface Get#(PacketDataT#(64)) macTx;
   interface PktWriteServer writeServer;
   interface Put#(TableEntry) add_entry;
   interface Put#(FlowId) delete_entry;
   interface Put#(Tuple2#(FlowId, ActionArg)) modify_entry;
   method MemMgmtDbgRec memMgmtDbg;
   method TDMDbgRec tdmDbg;
   method ActionValue#(PktBuffDbgRec) pktBuffDbg(Bit#(8) id);
   method MatchTableDbgRec matchTableDbg;
   method TxThruDbgRec ringToMacDbg;
endinterface

module mkTdmPipeline#(Clock txClock, Reset txReset
                     ,Clock rxClock, Reset rxReset
                     ,MemoryTestIndication indication
                     ,ConnectalMemory::MemServerIndication memServerInd
`ifdef DEBUG
                     ,MemMgmtIndication memTestInd
                     ,ConnectalMemory::MMUIndication mmuInd
`endif
   )(TdmPipeline);

   //RxChannel rxchan <- mkRxChannel(rxClock, rxReset);
   HostChannel hostchan <- mkHostChannel();
   TxChannel txchan <- mkTxChannel(txClock, txReset);

   IPv4Route ipv4Route <- mkIPv4Route(hostchan.next);
   ModifyMac modMac <- mkModifyMac(ipv4Route.next);
   TDM sched <- mkTDM(modMac.next, txchan);

   SharedBuffer#(12, 128, 1) mem <- mkSharedBuffer(vec(txchan.readClient)
                                                  ,vec(txchan.freeClient)
                                                  ,vec(hostchan.writeClient, modMac.writeClient)
                                                  ,vec(hostchan.mallocClient)
                                                  ,memServerInd
`ifdef DEBUG
                                                  ,memTestInd
                                                  ,mmuInd
`endif
                                                  );

   rule read_flow_id;
      let v <- toGet(ipv4Route.entry_added).get;
      indication.addEntryResp(v);
   endrule

   //interface macRx = rxchan.macRx;
   interface macTx = txchan.macTx;
   interface writeServer = hostchan.writeServer;
   interface add_entry = ipv4Route.add_entry;
   interface delete_entry = ipv4Route.delete_entry;
   interface modify_entry = ipv4Route.modify_entry;
   method matchTableDbg = ipv4Route.mdbg;
   method memMgmtDbg = mem.dbg;
   method tdmDbg = sched.dbg;
   //method ringToMacDbg = txchan.dbg;
   method ActionValue#(PktBuffDbgRec) pktBuffDbg(Bit#(8) id);
      PktBuffDbgRec v = defaultValue;
      case (id) matches
         0: v = hostchan.dbg;
         1: v = txchan.dbg;
         2: v = rxchan.dbg;
      endcase
      return v;
   endmethod
endmodule


fix commenting

fix commenting

// 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 StmtFSM::*;
import BRAM::*;
import MCSAlgorithm::*;
import StackReg::*;

/* frame arguments */
typedef struct {
   Bit#(7) aStart;
   Bit#(7) bStart;
   Bit#(7) aLen;
   Bit#(7) bLen;
   } CArgs deriving(Bits);

typedef struct {
   Bit#(7) midi;
   Bit#(7) maxj;
   } CVars deriving(Bits);

typedef enum {HCSIdle, HCS1, HCS2, HCS3, HCS4, HCS5, HCS6,
   HCSComplete} HCState deriving (Bits, Eq);

module mkHirschC#(BRAMServer#(Bit#(strIndexWidth), Bit#(8)) strA, BRAMServer#(Bit#(strIndexWidth), Bit#(8)) strB, BRAMServer#(Bit#(lIndexWidth), Bit#(16)) matL, MCSAlgorithm chirschB0,  MCSAlgorithm chirschB1, BRAMServer#(Bit#(lIndexWidth), Bit#(16)) l0, BRAMServer#(Bit#(lIndexWidth), Bit#(16)) l1)(MCSAlgorithm)
         provisos(Add#(0, 7, strIndexWidth),
	       Add#(0, 14, lIndexWidth));

      /* pc, args, vars */
   StackReg#(128, HCState, CArgs, CVars) fr <- mkStackReg(128, HCSIdle);

   Reg#(Bit#(7)) aStartReg <- mkReg(0);
   Reg#(Bit#(7)) bStartReg <- mkReg(0);
   Reg#(Bit#(14)) rStartReg <- mkReg(0);
   Reg#(Bit#(7)) aLenReg <- mkReg(0);
   Reg#(Bit#(7)) bLenReg <- 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#(14)) outcounter <- mkReg(0);
   Reg#(Bit#(16)) maxjvalue <- mkReg(0);

/*
 * HirschC(Astart, Alen, Bstart, Blen, output fifo)
 * implicit A storage, B storage
 *
 */

  // This FSM searches string B looking for the first char of string A
   Stmt hirschC2Stmt =
   seq
      //$display("hirschC2Stmt running ");
      // read A[0]
      strA.request.put(BRAMRequest{write: False, responseOnWrite: False, address: fr.args.aStart, datain: ?});
      action
	 let tmp <- strA.response.get();
	 aData <= tmp;
      endaction
      // scan for it in B
      for (jj <= 0; jj < fr.args.bLen; jj <= jj + 1)
	 seq
	    strB.request.put(BRAMRequest{write: False, responseOnWrite: False, address: fr.args.bStart + jj, datain: ?});
	    action
	       let tmp <- strB.response.get();
	       bData <= tmp;
	    endaction
	    if (aData == bData)
	       seq
		  //$display("output %d", aData);
		  matL.request.put(BRAMRequest{write: True, responseOnWrite: False, address: outcounter, datain: zeroExtend(aData)});
		  outcounter <= outcounter + 1;
		  break;
	       endseq
	 endseq
      fr.doreturn();
   endseq;

   FSM hC2fsm <- mkFSM(hirschC2Stmt);

   // AlgC step 1, 2, and 3
   rule hc1 (fr.pc == HCS1);
      //$display("HCS1 aStart %d aLen %d bStart %d bLen %d", fr.args.aStart, fr.args.aLen, fr.args.bStart, fr.args.bLen);
      if (fr.args.bLen == 0)
	fr.doreturn();
     else if (fr.args.aLen == 1)
	begin
	   hC2fsm.start();
	   fr.nextpc(HCS2);
	end
     else
	action
	   let midi = fr.args.aLen >> 1;
	   fr.vars.midi <= midi;
	   chirschB1.setupA(fr.args.aStart, midi);
	   chirschB1.setupB(fr.args.bStart, fr.args.bLen);
	   chirschB0.setupA(fr.args.aStart+midi, fr.args.aLen - midi);
	   chirschB0.setupB(fr.args.bStart, fr.args.bLen);
	   chirschB0.fsm.start();
	   chirschB1.fsm.start();
	   fr.nextpc(HCS3);
	endaction
   endrule

   // This FSM searches the results of the two calls to HirschB
   Stmt hirschC4Stmt =
   seq
      //$display ("hirschC4A stmt running");
      maxjvalue <= 0;
      fr.vars.maxj <= 0;
      for (jj <= 0; jj <= fr.args.bLen; jj <= jj + 1)
	 seq
	    l0.request.put(BRAMRequest{write: False, responseOnWrite: False, address: zeroExtend(jj), datain: ?});
	    l1.request.put(BRAMRequest{write: False, responseOnWrite: False, address: zeroExtend(fr.args.bLen - jj), datain: ?});
	    action
	       let t1 <- l0.response.get();
	       let t2 <- l1.response.get();
	       //$display(" j %d l0 %d l1 %d, sum %d oldmax %d",
		 // jj, t1, t2, t1 + t2, maxjvalue);
	       if ((t1 + t2) > maxjvalue)
		  action
		     maxjvalue <= t1 + t2;
		     fr.vars.maxj <= jj;
		  endaction
	    endaction
	 endseq
      //$display ("midi %d maxj %d", fr.vars.midi, fr.vars.maxj);
      fr.docall(HCS1, HCS5, CArgs {aStart: fr.args.aStart, aLen: fr.vars.midi, bStart: fr.args.bStart, bLen: fr.vars.maxj}, fr.vars);
   endseq;

   FSM hc4fsm <- mkFSM(hirschC4Stmt);

   rule hc3 (fr.pc == HCS3 && chirschB0.fsm.done() && chirschB1.fsm.done());
      //$display("HSC3");
      hc4fsm.start();
      fr.nextpc(HCS4);
   endrule

   rule hc5 (fr.pc == HCS5);
      //$display("HSC5 aStart %d aLen %d bStart %d bLen %d midi %d maxj %d",
	 fr.args.aStart, fr.args.aLen, fr.args.bStart, fr.args.bLen,
	 fr.vars.midi, fr.vars.maxj);
      fr.docall(HCS1, HCS6, CArgs{aStart: fr.args.aStart + fr.vars.midi, aLen: fr.args.aLen - fr.vars.midi, bStart: fr.args.bStart + fr.vars.maxj, bLen: fr.args.bLen - fr.vars.maxj}, fr.vars);
   endrule

   rule hc6 (fr.pc == HCS6);
      //$display("HSC6");
      fr.doreturn();
   endrule

   rule hccomplete (fr.pc == HCSComplete);
      $display("HSCComplete, result size %d", outcounter);
      fr.nextpc(HCSIdle);
   endrule

   method Action setupA(Bit#(7) start, Bit#(7) length);
      $display("HirschC setupA %d %d", start, length);
      aStartReg <= start;
      aLenReg <= length;
   endmethod

   method Action setupB(Bit#(7) start, Bit#(7) length);
      $display("HirschC setupB %d %d", start, length);
      bStartReg <= start;
      bLenReg <= length;
   endmethod

   method Action setupL(Bit#(14) start);
      rStartReg <= start;
   endmethod

   method Bit#(14) result();
      return(outcounter);
   endmethod

   interface FSM fsm;
      method Action start();
         $display("HirschC running aLen %d bLen %d", aLenReg, bLenReg);
	 fr.docall(HCS1, HCSComplete, CArgs{aStart: 0, aLen: aLenReg,
	    bStart: 0, bLen: bLenReg}, CVars {midi: 0, maxj: 0});
      endmethod
      method Bool done();
	 return(fr.pc == HCSIdle);
      endmethod
      method Action waitTillDone();
      endmethod
      method Action abort();
      endmethod
   endinterface: fsm

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 StmtFSM::*;
import BRAM::*;
import MCSAlgorithm::*;
import StackReg::*;

/* frame arguments */
typedef struct {
   Bit#(7) aStart;
   Bit#(7) bStart;
   Bit#(7) aLen;
   Bit#(7) bLen;
   } CArgs deriving(Bits);

typedef struct {
   Bit#(7) midi;
   Bit#(7) maxj;
   } CVars deriving(Bits);

typedef enum {HCSIdle, HCS1, HCS2, HCS3, HCS4, HCS5, HCS6,
   HCSComplete} HCState deriving (Bits, Eq);

module mkHirschC#(BRAMServer#(Bit#(strIndexWidth), Bit#(8)) strA, BRAMServer#(Bit#(strIndexWidth), Bit#(8)) strB, BRAMServer#(Bit#(lIndexWidth), Bit#(16)) matL, MCSAlgorithm chirschB0,  MCSAlgorithm chirschB1, BRAMServer#(Bit#(lIndexWidth), Bit#(16)) l0, BRAMServer#(Bit#(lIndexWidth), Bit#(16)) l1)(MCSAlgorithm)
         provisos(Add#(0, 7, strIndexWidth),
	       Add#(0, 14, lIndexWidth));

      /* pc, args, vars */
   StackReg#(128, HCState, CArgs, CVars) fr <- mkStackReg(128, HCSIdle);

   Reg#(Bit#(7)) aStartReg <- mkReg(0);
   Reg#(Bit#(7)) bStartReg <- mkReg(0);
   Reg#(Bit#(14)) rStartReg <- mkReg(0);
   Reg#(Bit#(7)) aLenReg <- mkReg(0);
   Reg#(Bit#(7)) bLenReg <- 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#(14)) outcounter <- mkReg(0);
   Reg#(Bit#(16)) maxjvalue <- mkReg(0);

/*
 * HirschC(Astart, Alen, Bstart, Blen, output fifo)
 * implicit A storage, B storage
 *
 */

  // This FSM searches string B looking for the first char of string A
   Stmt hirschC2Stmt =
   seq
      //$display("hirschC2Stmt running ");
      // read A[0]
      strA.request.put(BRAMRequest{write: False, responseOnWrite: False, address: fr.args.aStart, datain: ?});
      action
	 let tmp <- strA.response.get();
	 aData <= tmp;
      endaction
      // scan for it in B
      for (jj <= 0; jj < fr.args.bLen; jj <= jj + 1)
	 seq
	    strB.request.put(BRAMRequest{write: False, responseOnWrite: False, address: fr.args.bStart + jj, datain: ?});
	    action
	       let tmp <- strB.response.get();
	       bData <= tmp;
	    endaction
	    if (aData == bData)
	       seq
		  //$display("output %d", aData);
		  matL.request.put(BRAMRequest{write: True, responseOnWrite: False, address: outcounter, datain: zeroExtend(aData)});
		  outcounter <= outcounter + 1;
		  break;
	       endseq
	 endseq
      fr.doreturn();
   endseq;

   FSM hC2fsm <- mkFSM(hirschC2Stmt);

   // AlgC step 1, 2, and 3
   rule hc1 (fr.pc == HCS1);
      //$display("HCS1 aStart %d aLen %d bStart %d bLen %d", fr.args.aStart, fr.args.aLen, fr.args.bStart, fr.args.bLen);
      if (fr.args.bLen == 0)
	fr.doreturn();
     else if (fr.args.aLen == 1)
	begin
	   hC2fsm.start();
	   fr.nextpc(HCS2);
	end
     else
	action
	   let midi = fr.args.aLen >> 1;
	   fr.vars.midi <= midi;
	   chirschB1.setupA(fr.args.aStart, midi);
	   chirschB1.setupB(fr.args.bStart, fr.args.bLen);
	   chirschB0.setupA(fr.args.aStart+midi, fr.args.aLen - midi);
	   chirschB0.setupB(fr.args.bStart, fr.args.bLen);
	   chirschB0.fsm.start();
	   chirschB1.fsm.start();
	   fr.nextpc(HCS3);
	endaction
   endrule

   // This FSM searches the results of the two calls to HirschB
   Stmt hirschC4Stmt =
   seq
      //$display ("hirschC4A stmt running");
      maxjvalue <= 0;
      fr.vars.maxj <= 0;
      for (jj <= 0; jj <= fr.args.bLen; jj <= jj + 1)
	 seq
	    l0.request.put(BRAMRequest{write: False, responseOnWrite: False, address: zeroExtend(jj), datain: ?});
	    l1.request.put(BRAMRequest{write: False, responseOnWrite: False, address: zeroExtend(fr.args.bLen - jj), datain: ?});
	    action
	       let t1 <- l0.response.get();
	       let t2 <- l1.response.get();
	       //$display(" j %d l0 %d l1 %d, sum %d oldmax %d",
		  jj, t1, t2, t1 + t2, maxjvalue);
	       if ((t1 + t2) > maxjvalue)
		  action
		     maxjvalue <= t1 + t2;
		     fr.vars.maxj <= jj;
		  endaction
	    endaction
	 endseq
      //$display ("midi %d maxj %d", fr.vars.midi, fr.vars.maxj);
      fr.docall(HCS1, HCS5, CArgs {aStart: fr.args.aStart, aLen: fr.vars.midi, bStart: fr.args.bStart, bLen: fr.vars.maxj}, fr.vars);
   endseq;

   FSM hc4fsm <- mkFSM(hirschC4Stmt);

   rule hc3 (fr.pc == HCS3 && chirschB0.fsm.done() && chirschB1.fsm.done());
      //$display("HSC3");
      hc4fsm.start();
      fr.nextpc(HCS4);
   endrule

   rule hc5 (fr.pc == HCS5);
      //$display("HSC5 aStart %d aLen %d bStart %d bLen %d midi %d maxj %d",
	 fr.args.aStart, fr.args.aLen, fr.args.bStart, fr.args.bLen,
	 fr.vars.midi, fr.vars.maxj);
      fr.docall(HCS1, HCS6, CArgs{aStart: fr.args.aStart + fr.vars.midi, aLen: fr.args.aLen - fr.vars.midi, bStart: fr.args.bStart + fr.vars.maxj, bLen: fr.args.bLen - fr.vars.maxj}, fr.vars);
   endrule

   rule hc6 (fr.pc == HCS6);
      //$display("HSC6");
      fr.doreturn();
   endrule

   rule hccomplete (fr.pc == HCSComplete);
      $display("HSCComplete, result size %d", outcounter);
      fr.nextpc(HCSIdle);
   endrule

   method Action setupA(Bit#(7) start, Bit#(7) length);
      $display("HirschC setupA %d %d", start, length);
      aStartReg <= start;
      aLenReg <= length;
   endmethod

   method Action setupB(Bit#(7) start, Bit#(7) length);
      $display("HirschC setupB %d %d", start, length);
      bStartReg <= start;
      bLenReg <= length;
   endmethod

   method Action setupL(Bit#(14) start);
      rStartReg <= start;
   endmethod

   method Bit#(14) result();
      return(outcounter);
   endmethod

   interface FSM fsm;
      method Action start();
         $display("HirschC running aLen %d bLen %d", aLenReg, bLenReg);
	 fr.docall(HCS1, HCSComplete, CArgs{aStart: 0, aLen: aLenReg,
	    bStart: 0, bLen: bLenReg}, CVars {midi: 0, maxj: 0});
      endmethod
      method Bool done();
	 return(fr.pc == HCSIdle);
      endmethod
      method Action waitTillDone();
      endmethod
      method Action abort();
      endmethod
   endinterface: fsm

endmodule


finish commenting

finish commenting

// 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 FIFOF::*;
import GetPutF::*;
import Dma::*;
import RingTypes::*;
import StmtFSM::*;

// The interface to the copyengine is a pair of fifos which supply and accept
// blocks of 8 64 bit words
// A Command:
//  word 0: COPY[63:56] TAG[31:0]
//  word 1: readMemHandle[63:32]
//  word 1: readAddress[23:0]
//  word 2  writeMemHandle[63:32]
//  word 2: writeAddress[23:0]
//  word 3: bytecount[15:0]
//  word 4-7 unused
// Status
//  word0-6 all 0
//  word7  TAG[31:0]

module mkCopyEngine#(DmaReadServer#(64) copy_read_chan, DmaWriteServer#(64) copy_write_chan) ( ServerF#(Bit#(64), Bit#(64)));
   FIFOF#(Bit#(64)) f_in  <- mkSizedFIFOF(16);    // to buffer incoming requests
   FIFOF#(Bit#(64)) f_out <- mkSizedFIFOF(16);    // to buffer outgoing responses
   Reg#(Bit#(16)) copyReadCount <- mkReg(0);
   Reg#(Bit#(16)) copyWriteCount <- mkReg(0);
   Reg#(Bit#(DmaAddrSize)) copyReadAddr <- mkReg(0);
   Reg#(Bit#(DmaAddrSize)) copyWriteAddr <- mkReg(0);
   Reg#(DmaPointer) copyReadHandle <- mkReg(0);
   Reg#(DmaPointer) copyWriteHandle <- mkReg(0);
   Reg#(Bit#(32)) copyTag <- mkReg(0);
   Reg#(Bool) copyBusy <- mkReg(False);
   Reg#(Bit#(4)) cmdCtr <- mkReg(0);
   Stmt copyStart =
   seq
      while(True)
	 seq
	    while (copyBusy) noAction;
	    /*
	    for (cmdCtr <= 0; cmdCtr < 8; cmdCtr <= cmdCtr + 1)
	       action
		  $display("COPY %h %h", cmdCtr, f_in.first());
		  f_in.deq();
	       endaction

	    */
	    action
	       copyTag <= f_in.first()[31:0];
	       f_in.deq();  // word 0
	    endaction
	    action
	       copyReadHandle <= f_in.first()[63:32];
	       copyReadAddr <= f_in.first()[23:0];
	       f_in.deq();  // word 1
	    endaction
	    action
	       copyWriteHandle <= f_in.first()[63:32];
	       copyWriteAddr <= f_in.first()[23:0];
	       f_in.deq();  // word 2
	    endaction
	    action
	       copyReadCount <= f_in.first()[15:0];
	       copyWriteCount <= f_in.first()[15:0];
	       f_in.deq();  // word 3
	    endaction
	       f_in.deq;  // discard words 4-7
	       f_in.deq;  // discard words 4-7
	       f_in.deq;  // discard words 4-7
	       f_in.deq;  // discard words 4-7
	    //$display("copyStart from %h to %h count %h",
	    //   copyReadAddr, copyWriteAddr, copyReadCount);
	    copyBusy <= True;
	 endseq
   endseq;

    rule copyReadRule (copyBusy && (copyReadCount != 0));
       //$display("copyRead %h, count %h", copyReadAddr, copyReadCount);
       copy_read_chan.readReq.put(DmaRequest{handle: copyReadHandle, address: copyReadAddr, burstLen: 1, tag: copyReadAddr[8:3]});
       copyReadAddr <= copyReadAddr + 8;
       copyReadCount <= copyReadCount - 8;
    endrule

    rule copyReadWriteRule (copyBusy);
       let data <- copy_read_chan.readData.get;
       //$display("copyReadWrite addr %h", copyWriteAddr);
       copy_write_chan.writeReq.put(DmaRequest{handle: copyWriteHandle, address: copyWriteAddr, burstLen: 1, tag: copyWriteAddr[8:3]});
       copy_write_chan.writeData.put(DmaData{data: data.data, tag: copyWriteAddr[8:3]});
       copyWriteAddr <= copyWriteAddr + 8;
    endrule

   Stmt copyFinish =
   seq
      while(True)
	 seq
	    while (!copyBusy) noAction;
	    while (copyWriteCount > 0)
	       action
		  let v <- copy_write_chan.writeDone.get;
		  //$display("copyWriteAck");
		  copyWriteCount <= copyWriteCount - 8;
	       endaction
	    f_out.enq(0);
	    f_out.enq(0);
	    f_out.enq(0);
	    f_out.enq(0);
	    f_out.enq(0);
	    f_out.enq(0);
	    f_out.enq(0);
	    f_out.enq(extend(copyTag));
	    copyBusy <= False;
	 endseq
   endseq;

   mkAutoFSM(copyStart);
   mkAutoFSM(copyFinish);

   interface PutF request = toPutF(f_in);
   interface GetF response = toGetF (f_out);

endmodule: mkCopyEngine

// 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 FIFOF::*;
import GetPutF::*;
import Dma::*;
import RingTypes::*;
import StmtFSM::*;

// The interface to the copyengine is a pair of fifos which supply and accept
// blocks of 8 64 bit words
// A Command:
//  word 0: COPY[63:56] TAG[31:0]
//  word 1: readMemHandle[63:32]
//  word 1: readAddress[23:0]
//  word 2  writeMemHandle[63:32]
//  word 2: writeAddress[23:0]
//  word 3: bytecount[15:0]
//  word 4-7 unused
// Status
//  word0-6 all 0
//  word7  TAG[31:0]

module mkCopyEngine#(DmaReadServer#(64) copy_read_chan, DmaWriteServer#(64) copy_write_chan) ( ServerF#(Bit#(64), Bit#(64)));
   FIFOF#(Bit#(64)) f_in  <- mkSizedFIFOF(16);    // to buffer incoming requests
   FIFOF#(Bit#(64)) f_out <- mkSizedFIFOF(16);    // to buffer outgoing responses
   Reg#(Bit#(16)) copyReadCount <- mkReg(0);
   Reg#(Bit#(16)) copyWriteCount <- mkReg(0);
   Reg#(Bit#(DmaAddrSize)) copyReadAddr <- mkReg(0);
   Reg#(Bit#(DmaAddrSize)) copyWriteAddr <- mkReg(0);
   Reg#(DmaPointer) copyReadHandle <- mkReg(0);
   Reg#(DmaPointer) copyWriteHandle <- mkReg(0);
   Reg#(Bit#(32)) copyTag <- mkReg(0);
   Reg#(Bool) copyBusy <- mkReg(False);
   Reg#(Bit#(4)) cmdCtr <- mkReg(0);
   Stmt copyStart =
   seq
      while(True)
	 seq
	    while (copyBusy) noAction;
	    /*
	    for (cmdCtr <= 0; cmdCtr < 8; cmdCtr <= cmdCtr + 1)
	       action
		  $display("COPY %h %h", cmdCtr, f_in.first());
		  f_in.deq();
	       endaction

	    */
	    action
	       copyTag <= f_in.first()[31:0];
	       f_in.deq();  // word 0
	    endaction
	    action
	       copyReadHandle <= f_in.first()[63:32];
	       copyReadAddr <= f_in.first()[23:0];
	       f_in.deq();  // word 1
	    endaction
	    action
	       copyWriteHandle <= f_in.first()[63:32];
	       copyWriteAddr <= f_in.first()[23:0];
	       f_in.deq();  // word 2
	    endaction
	    action
	       copyReadCount <= f_in.first()[15:0];
	       copyWriteCount <= f_in.first()[15:0];
	       f_in.deq();  // word 3
	    endaction
	       f_in.deq;  // discard words 4-7
	       f_in.deq;  // discard words 4-7
	       f_in.deq;  // discard words 4-7
	       f_in.deq;  // discard words 4-7
	    //$display("copyStart from %h to %h count %h",
	       copyReadAddr, copyWriteAddr, copyReadCount);
	    copyBusy <= True;
	 endseq
   endseq;

    rule copyReadRule (copyBusy && (copyReadCount != 0));
       //$display("copyRead %h, count %h", copyReadAddr, copyReadCount);
       copy_read_chan.readReq.put(DmaRequest{handle: copyReadHandle, address: copyReadAddr, burstLen: 1, tag: copyReadAddr[8:3]});
       copyReadAddr <= copyReadAddr + 8;
       copyReadCount <= copyReadCount - 8;
    endrule

    rule copyReadWriteRule (copyBusy);
       let data <- copy_read_chan.readData.get;
       //$display("copyReadWrite addr %h", copyWriteAddr);
       copy_write_chan.writeReq.put(DmaRequest{handle: copyWriteHandle, address: copyWriteAddr, burstLen: 1, tag: copyWriteAddr[8:3]});
       copy_write_chan.writeData.put(DmaData{data: data.data, tag: copyWriteAddr[8:3]});
       copyWriteAddr <= copyWriteAddr + 8;
    endrule

   Stmt copyFinish =
   seq
      while(True)
	 seq
	    while (!copyBusy) noAction;
	    while (copyWriteCount > 0)
	       action
		  let v <- copy_write_chan.writeDone.get;
		  //$display("copyWriteAck");
		  copyWriteCount <= copyWriteCount - 8;
	       endaction
	    f_out.enq(0);
	    f_out.enq(0);
	    f_out.enq(0);
	    f_out.enq(0);
	    f_out.enq(0);
	    f_out.enq(0);
	    f_out.enq(0);
	    f_out.enq(extend(copyTag));
	    copyBusy <= False;
	 endseq
   endseq;

   mkAutoFSM(copyStart);
   mkAutoFSM(copyFinish);

   interface PutF request = toPutF(f_in);
   interface GetF response = toGetF (f_out);

endmodule: mkCopyEngine


compilation fixes

compilation fixes

// 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 RingTypes::*;

module mkEchoServer ( ServerF#(Bit#(64), Bit#(64)));
   FIFO#(Bit#(64)) f_echo  <- mkSizedFIFOF(16);    // to buffer incoming requests

   interface PutF request = toPutF(f_echo);
   interface GetF response = toGetF(f_echo);

endmodule: mkEchoServer

// 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 GetPutF::*;
import RingTypes::*;

module mkEchoServer#() ( ServerF#(Bit#(64), Bit#(64)));
   FIFO#(Bit#(64)) f_echo  <- mkSizedFIFOF(16);    // to buffer incoming requests

   interface PutF request = toPutF(f_echo);
   interface GetF response = toGetF(f_echo);

endmodule: mkEchoServer


simplify deparser

simplify deparser

// 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 Assert::*;
import CBus::*;
import BUtils::*;
import DbgDefs::*;
import DefaultValue::*;
import Ethernet::*;
import FIFO::*;
import FIFOF::*;
import GetPut::*;
import StmtFSM::*;
import Vector::*;
import List::*;
import MIMO::*;
import Simple::*;
import Utils::*;
import Pipe::*;
import PacketBuffer::*;

interface Deparser;
   interface PipeIn#(MetadataT) metadata;
   interface PktWriteServer writeServer;
   interface PktWriteClient writeClient;
   interface Put#(int) verbosity;
   method DeparserPerfRec read_perf_info;
endinterface

typedef enum {
  StateDeparseStart,
  StateDeparseEthernet,
  StateDeparseIpv4
} DeparserState deriving (Bits, Eq, FShow);

typedef union tagged {
   Tuple2#(Bit#(112), Bit#(112)) UEthernetT;
   Tuple2#(Bit#(160), Bit#(160)) UIpv4T;
} MetaT;

typeclass ToTuple#(type t, type d);
   function Tuple2#(t, t) toTuple(d arg);
endtypeclass

instance ToTuple#(EthernetT, MetadataT);
   function Tuple2#(EthernetT, EthernetT) toTuple (MetadataT t);
      EthernetT data = defaultValue;
      EthernetT mask = defaultMask;
      let ethernet = fromMaybe(?, t.ethernet);
      data.etherType = ethernet.etherType;
      mask.etherType = 0;
      return tuple2(data, mask);
   endfunction
endinstance

instance ToTuple#(Ipv4T, MetadataT);
   function Tuple2#(Ipv4T, Ipv4T) toTuple (MetadataT t);
      Ipv4T data = defaultValue;
      Ipv4T mask = defaultMask;
      let ipv4 = fromMaybe(?, t.ipv4);
      data.dstAddr = ipv4.dstAddr;
      mask.dstAddr = 0;
      return tuple2(data, mask);
   endfunction
endinstance

(* synthesize *)
module mkDeparser(Deparser);
   Reg#(int) cr_verbosity[2] <- mkCRegU(2);
   FIFOF#(int) cr_verbosity_ff <- mkFIFOF;

   Reg#(DeparserState) rg_deparse_state <- mkReg(StateDeparseStart);
   FIFOF#(EtherData) data_in_ff <- mkFIFOF;
   FIFOF#(EtherData) data_out_ff <- mkFIFOF;
   FIFOF#(MetadataT) meta_in_ff <- mkFIFOF;

   Reg#(Bit#(32)) rg_offset <- mkReg(0);
   Reg#(Bit#(32)) rg_edit_offset <- mkReg(0);

   Reg#(Bit#(128)) rg_buff <- mkReg(0);
   Reg#(Bit#(32)) rg_shamt <- mkReg(0);

   rule set_verbosity;
      let x = cr_verbosity_ff.first;
      cr_verbosity_ff.deq;
      cr_verbosity[1] <= x;
   endrule

   function Action report_deparse_action (DeparserState state, Bit#(32) offset);
      action
         if (cr_verbosity[0] > 0)
            $display ("(%d) Deparser State %h offset 0x%h", $time, state, offset);
      endaction
   endfunction

   function Action succeed_and_next (Bit#(32) next_offset);
      action
         data_in_ff.deq;
         rg_offset <= next_offset;
      endaction
   endfunction

   function Action fail_and_trap (Bit#(32) next_offset);
      action
         data_in_ff.deq;
         rg_offset <= 0;
      endaction
   endfunction

   //function Bool matchesOffset ();

   let din = data_in_ff.first;
   let meta = meta_in_ff.first;

   rule rl_start_state if (rg_deparse_state == StateDeparseStart);
      let v = data_in_ff.first;
      if (v.sop) begin
         rg_deparse_state <= StateDeparseEthernet;
         $display("(%0d) Deparse Ethernet Start ", $time, fshow(v));
      end
      else begin
         data_in_ff.deq;
         data_out_ff.enq(v);
      end
   endrule

   function DeparserState compute_next_state_ethernet(Bit#(16) v);
      DeparserState nextState = StateDeparseStart;
      case (byteSwap(v)) matches
         'h800: begin
            nextState = StateDeparseIpv4;
         end
         default: begin
            nextState = StateDeparseStart;
         end
      endcase
      return nextState;
   endfunction

   function DeparserState compute_next_state (DeparserState state);
      DeparserState nextState = StateDeparseStart;
      case (state) matches
         StateDeparseEthernet: begin
            M_EthernetT ethernet = fromMaybe(?, meta.ethernet);
            nextState = compute_next_state_ethernet (ethernet.etherType);
         end
         default: begin
            nextState = StateDeparseStart;
         end
      endcase
      return nextState;
   endfunction

   function Bit#(l) read_data (UInt#(8) lhs, UInt#(8) rhs)
      provisos (Add#(a__, l, 128));
      Bit#(l) ldata = truncate(din.data) << (fromInteger(valueOf(l))-lhs);
      Bit#(l) rdata =truncate(rg_buff >> (fromInteger(valueOf(l))-rhs));
      Bit#(l) cdata = ldata | rdata;
      return cdata;
   endfunction

   function Bit#(max) create_mask (LUInt#(max) count);
      Bit#(max) v = 1 << count - 1;
      return v;
   endfunction

   // build_deparse_rule_no_opt
   function Rules build_deparse_rule_no_opt (DeparserState state,
                                             int offset,
                                             Tuple2#(Bit#(n), Bit#(n)) m,
                                             UInt#(8) clen,
                                             UInt#(8) plen)
      provisos (Mul#(TDiv#(n, 8), 8, n),
                Add#(a__, n, 128));
      Rules d =
      rules
         rule rl_deparse if ((rg_deparse_state == state) && (rg_offset == unpack(pack(offset))));
            report_deparse_action(rg_deparse_state, rg_offset);
            match {.meta, .mask} = m;
            Vector#(n, Bit#(1)) curr_meta = takeAt(0, unpack(byteSwap(meta)));
            Vector#(n, Bit#(1)) curr_mask = takeAt(0, unpack(byteSwap(mask)));
            Bit#(n) curr_data = read_data (clen, plen);
            let data = apply_changes (curr_data, pack(curr_meta), pack(curr_mask));
            let data_this_cycle = EtherData { sop: din.sop,
                                              eop: din.eop,
                                              data: zeroExtend(data),
                                              mask: create_mask(cExtend(fromInteger(valueOf(n)))) };
            data_out_ff.enq (data_this_cycle);
            rg_deparse_state <= compute_next_state(state);
            rg_buff <= din.data;
            // apply header removal by marking mask zero
            // apply added header by setting field at offset.
            succeed_and_next (rg_offset + cExtend(clen) + cExtend(plen));
         endrule
      endrules;
      return d;
   endfunction

   Tuple2#(EthernetT, EthernetT) ethernet = toTuple(meta);
   Bit#(112) ethernet_meta = pack(tpl_1(ethernet));
   Bit#(112) ethernet_mask = pack(tpl_2(ethernet));
   addRules(build_deparse_rule_no_opt(StateDeparseEthernet,
                                      0,
                                      tuple2(ethernet_meta, ethernet_mask),
                                      112,
                                      0));

   Tuple2#(Ipv4T, Ipv4T) ipv4 = toTuple(meta);
   Vector#(128, Bit#(1)) ipv4_meta_vec_0 = takeAt(0, unpack(pack(tpl_1(ipv4))));
   Vector#(128, Bit#(1)) ipv4_mask_vec_0 = takeAt(0, unpack(pack(tpl_2(ipv4))));
   Bit#(128) ipv4_meta_0 = pack(ipv4_meta_vec_0);
   Bit#(128) ipv4_mask_0 = pack(ipv4_mask_vec_0);
   addRules(build_deparse_rule_no_opt(StateDeparseIpv4,
                                      112,
                                      tuple2(ipv4_meta_0, ipv4_mask_0),
                                      112,
                                      16));

   Vector#(32, Bit#(1)) ipv4_meta_vec_1 = takeAt(128, unpack(pack(tpl_1(ipv4))));
   Vector#(32, Bit#(1)) ipv4_mask_vec_1 = takeAt(128, unpack(pack(tpl_2(ipv4))));
   Bit#(32) ipv4_meta_1 = pack(ipv4_meta_vec_1);
   Bit#(32) ipv4_mask_1 = pack(ipv4_mask_vec_1);
   addRules(build_deparse_rule_no_opt(StateDeparseIpv4,
                                      240,
                                      tuple2(ipv4_meta_1, ipv4_mask_1),
                                      16,
                                      16));

   rule rl_deparse_done;

   endrule

   interface metadata = toPipeIn(meta_in_ff);
   interface PktWriteServer writeServer;
      interface writeData = toPut(data_in_ff);
   endinterface
   interface PktWriteClient writeClient;
      interface writeData = toGet(data_out_ff);
   endinterface
   interface verbosity = toPut(cr_verbosity_ff);
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 Assert::*;
import CBus::*;
import BUtils::*;
import DbgDefs::*;
import DefaultValue::*;
import Ethernet::*;
import FIFO::*;
import FIFOF::*;
import GetPut::*;
import StmtFSM::*;
import Vector::*;
import List::*;
import MIMO::*;
import Simple::*;
import Utils::*;
import Pipe::*;
import PacketBuffer::*;

interface Deparser;
   interface PipeIn#(MetadataT) metadata;
   interface PktWriteServer writeServer;
   interface PktWriteClient writeClient;
   interface Put#(int) verbosity;
   method DeparserPerfRec read_perf_info;
endinterface

typedef enum {
  StateDeparseStart,
  StateDeparseEthernet,
  StateDeparseIpv4
} DeparserState deriving (Bits, Eq, FShow);

typedef union tagged {
   Tuple2#(Bit#(112), Bit#(112)) UEthernetT;
   Tuple2#(Bit#(160), Bit#(160)) UIpv4T;
} MetaT;

typeclass ToTuple#(type t, type d);
   function Tuple2#(t, t) toTuple(d arg);
endtypeclass

instance ToTuple#(EthernetT, MetadataT);
   function Tuple2#(EthernetT, EthernetT) toTuple (MetadataT t);
      EthernetT data = defaultValue;
      EthernetT mask = defaultMask;
      let ethernet = fromMaybe(?, t.ethernet);
      data.etherType = ethernet.etherType;
      mask.etherType = 0;
      return tuple2(data, mask);
   endfunction
endinstance

instance ToTuple#(Ipv4T, MetadataT);
   function Tuple2#(Ipv4T, Ipv4T) toTuple (MetadataT t);
      Ipv4T data = defaultValue;
      Ipv4T mask = defaultMask;
      let ipv4 = fromMaybe(?, t.ipv4);
      data.dstAddr = ipv4.dstAddr;
      mask.dstAddr = 0;
      return tuple2(data, mask);
   endfunction
endinstance

(* synthesize *)
module mkDeparser(Deparser);
   Reg#(int) cr_verbosity[2] <- mkCRegU(2);
   FIFOF#(int) cr_verbosity_ff <- mkFIFOF;

   Reg#(DeparserState) rg_deparse_state <- mkReg(StateDeparseStart);
   FIFOF#(EtherData) data_in_ff <- mkFIFOF;
   FIFOF#(EtherData) data_out_ff <- mkFIFOF;
   FIFOF#(MetadataT) meta_in_ff <- mkFIFOF;

   Reg#(Bit#(32)) rg_offset <- mkReg(0);
   Reg#(Bit#(32)) rg_edit_offset <- mkReg(0);

   Reg#(Bit#(128)) rg_buff <- mkReg(0);
   Reg#(Bit#(32)) rg_shamt <- mkReg(0);

   rule set_verbosity;
      let x = cr_verbosity_ff.first;
      cr_verbosity_ff.deq;
      cr_verbosity[1] <= x;
   endrule

   function Action report_deparse_action (DeparserState state, Bit#(32) offset);
      action
         if (cr_verbosity[0] > 0)
            $display ("(%d) Deparser State %h offset 0x%h", $time, state, offset);
      endaction
   endfunction

   function Action succeed_and_next (Bit#(32) next_offset);
      action
         data_in_ff.deq;
         rg_offset <= next_offset;
      endaction
   endfunction

   function Action fail_and_trap (Bit#(32) next_offset);
      action
         data_in_ff.deq;
         rg_offset <= 0;
      endaction
   endfunction

   //function Bool matchesOffset ();

   let din = data_in_ff.first;
   let meta = meta_in_ff.first;

   rule rl_start_state if (rg_deparse_state == StateDeparseStart);
      let v = data_in_ff.first;
      if (v.sop) begin
         rg_deparse_state <= StateDeparseEthernet;
         $display("(%0d) Deparse Ethernet Start ", $time, fshow(v));
      end
      else begin
         data_in_ff.deq;
         data_out_ff.enq(v);
      end
   endrule

   function DeparserState compute_next_state_ethernet(Bit#(16) v);
      DeparserState nextState = StateDeparseStart;
      case (byteSwap(v)) matches
         'h800: begin
            nextState = StateDeparseIpv4;
         end
         default: begin
            nextState = StateDeparseStart;
         end
      endcase
      return nextState;
   endfunction

   function DeparserState compute_next_state (DeparserState state);
      DeparserState nextState = StateDeparseStart;
      case (state) matches
         StateDeparseEthernet: begin
            M_EthernetT ethernet = fromMaybe(?, meta.ethernet);
            nextState = compute_next_state_ethernet (ethernet.etherType);
         end
         default: begin
            nextState = StateDeparseStart;
         end
      endcase
      return nextState;
   endfunction

   function Bit#(l) read_data (UInt#(8) lhs, UInt#(8) rhs)
      provisos (Add#(a__, l, 128));
      Bit#(l) ldata = truncate(din.data) << (fromInteger(valueOf(l))-lhs);
      Bit#(l) rdata =truncate(rg_buff >> (fromInteger(valueOf(l))-rhs));
      Bit#(l) cdata = ldata | rdata;
      return cdata;
   endfunction

   function Bit#(max) create_mask (LUInt#(max) count);
      Bit#(max) v = 1 << count - 1;
      return v;
   endfunction

   // build_deparse_rule_no_opt
   function Rules build_deparse_rule_no_opt (DeparserState state,
                                             int offset,
                                             Tuple2#(Bit#(n), Bit#(n)) m,
                                             UInt#(8) clen,
                                             UInt#(8) plen)
      provisos (Mul#(TDiv#(n, 8), 8, n),
                Add#(a__, n, 128));
      Rules d =
      rules
         rule rl_deparse if ((rg_deparse_state == state) && (rg_offset == unpack(pack(offset))));
            report_deparse_action(rg_deparse_state, rg_offset);
            match {.meta, .mask} = m;
            Vector#(n, Bit#(1)) curr_meta = takeAt(0, unpack(byteSwap(meta)));
            Vector#(n, Bit#(1)) curr_mask = takeAt(0, unpack(byteSwap(mask)));
            Bit#(n) curr_data = read_data (clen, plen);
            let data = apply_changes (curr_data, pack(curr_meta), pack(curr_mask));
            let data_this_cycle = EtherData { sop: din.sop,
                                              eop: din.eop,
                                              data: zeroExtend(data),
                                              mask: create_mask(cExtend(fromInteger(valueOf(n)))) };
            data_out_ff.enq (data_this_cycle);
            rg_deparse_state <= compute_next_state(state);
            rg_buff <= din.data;
            // apply header removal by marking mask zero
            // apply added header by setting field at offset.
            succeed_and_next (rg_offset + cExtend(clen) + cExtend(plen));
         endrule
      endrules;
      return d;
   endfunction

   rule rl_deparse_ipv4_1 if ((rg_deparse_state == StateDeparseIpv4) && (rg_offset == 112));
      report_deparse_action(rg_deparse_state, rg_offset);
      Tuple2#(Ipv4T, Ipv4T) tp = toTuple(meta);
      match {.mta, .msk} = tp;
      Vector#(128, Bit#(1)) curr_meta = takeAt(0, unpack(byteSwap(pack(mta))));
      Vector#(128, Bit#(1)) curr_mask = takeAt(0, unpack(byteSwap(pack(msk))));
      Bit#(112) d = truncate (din.data);
      Bit#(16) e = grab_left (rg_buff);
      let curr_data = {d, e};
      let data = apply_changes(curr_data, pack(curr_meta), pack(curr_mask));
      let data_this_cycle = EtherData { sop: din.sop, eop: din.eop, data: zeroExtend(data), mask: din.mask };
      data_out_ff.enq(data_this_cycle);
      // if eoh:
      //   state <= next_state
      rg_buff <= din.data;
      succeed_and_next(rg_offset + 128);
   endrule

   rule rl_deparse_ipv4_2 if ((rg_deparse_state == StateDeparseIpv4) && (rg_offset == 240));
      report_deparse_action(rg_deparse_state, rg_offset);
      Tuple2#(Ipv4T, Ipv4T) tp = toTuple(meta);
      match {.mta, .msk} = tp;
      // let data_in = read_data (16);
      Vector#(32, Bit#(1)) curr_meta = takeAt(128, unpack(byteSwap(pack(mta))));
      Vector#(32, Bit#(1)) curr_mask = takeAt(128, unpack(byteSwap(pack(msk))));
      //Bit#(32) curr_data = read_data (16, 16);
      Bit#(16) d = truncate (din.data);
      Bit#(16) e = grab_left (rg_buff);
      let curr_data = {d, e};
      let data = apply_changes(curr_data, pack(curr_meta), pack(curr_mask));
      let data_this_cycle = EtherData { sop: din.sop, eop: din.eop, data: zeroExtend(data), mask: din.mask };
      data_out_ff.enq(data_this_cycle);
      // if eoh:
      //    state <= next_state;
      rg_buff <= din.data;
      succeed_and_next(rg_offset + 32);
   endrule

   Tuple2#(EthernetT, EthernetT) ethernet = toTuple(meta);
   Bit#(112) ethernet_meta = pack(tpl_1(ethernet));
   Bit#(112) ethernet_mask = pack(tpl_2(ethernet));
   addRules(build_deparse_rule_no_opt(StateDeparseEthernet,
                                      0,
                                      tuple2(ethernet_meta, ethernet_mask),
                                      112,
                                      0));

//   Tuple2#(Ipv4T, Ipv4T) ipv4 = toTuple(meta);
//   let ipv4_meta = pack(tpl_1(ipv4));
//   let ipv4_mask = pack(tpl_2(ipv4));
//   addRules(build_deparse_rule_no_opt(StateDeparseIpv4, 112,
//      tuple2(ipv4_meta, ipv4_mask), 160, 112, 16));
//   addRules(build_deparse_rule_no_opt(StateDeparseIpv4, 240,
//      tuple2(ipv4_meta, ipv4_mask), 160, 16, 16));

   rule rl_deparse_done;

   endrule

   interface metadata = toPipeIn(meta_in_ff);
   interface PktWriteServer writeServer;
      interface writeData = toPut(data_in_ff);
   endinterface
   interface PktWriteClient writeClient;
      interface writeData = toGet(data_out_ff);
   endinterface
   interface verbosity = toPut(cr_verbosity_ff);
endmodule


updated bsv/ZynqTop.bsv now that mkPS7 converts the bits to clocks and resets

Change-Id: Idc62fc60ca5a87a6d3118a1efdd82d730591b921

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

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

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

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

import Clocks :: *;
import Vector            :: *;
import Connectable       :: *;
import Portal            :: *;
import Leds              :: *;
import Top               :: *;
import AxiMasterSlave    :: *;
import XbsvXilinxCells   :: *;
import PS7LIB::*;
import PPS7LIB::*;
import XADC::*;
import BRAM::*;
import Bscan::*;
import FIFOF::*;

//`define TRACE_AXI
//`define AXI_READ_TIMING

(* always_ready, always_enabled *)
interface ZynqTop#(type pins);
   (* prefix="" *)
   interface ZynqPins zynq;
   (* prefix="GPIO" *)
   interface LEDS             leds;
   (* prefix="XADC" *)
   interface XADC             xadc;
   interface pins             pins;
   interface Clock unused_clock;
   interface Reset unused_reset;
endinterface

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

module [Module] mkZynqTopFromPortal#(MkPortalTop#(ipins) constructor)(ZynqTop#(ipins));
   PS7 ps7 <- mkPS7();
   Clock mainclock = ps7.fclkclk[0];
   Reset mainreset = ps7.fclkreset[0];

   let top <- constructor(clocked_by mainclock, reset_by mainreset);
   Reg#(Bit#(8)) addrReg <- mkReg(9, clocked_by mainclock, reset_by mainreset);
   BscanBram#(Bit#(8), Bit#(64)) bscanBram <- mkBscanBram(1, addrReg, clocked_by mainclock, reset_by mainreset);
   BRAM_Configure bramCfg = defaultValue;
   bramCfg.memorySize = 256;
   bramCfg.latency = 1;
   BRAM2Port#(Bit#(8), Bit#(64)) traceBram <- mkSyncBRAM2Server(bramCfg, mainclock, mainreset,
								bscanBram.jtagClock, bscanBram.jtagReset);
   mkConnection(bscanBram.bramClient, traceBram.portB);

   ReadOnly#(Bit#(4)) debugReg <- mkNullCrossingWire(mainclock, bscanBram.debug());

   let interrupt_bit = top.interrupt ? 1'b1 : 1'b0;

`ifndef TRACE_AXI
   mkConnection(ps7.m_axi_gp[0].client, top.ctrl);
`else

   Vector#(5, FIFOF#(Bit#(64))) bscan_fifos <- replicateM(mkFIFOF(clocked_by mainclock, reset_by mainreset));

   rule write_bscanBram;
      Bit#(64) data = ?;
      if (bscan_fifos[0].notEmpty) begin
	 data = bscan_fifos[0].first;
	 bscan_fifos[0].deq;
      end
      else if (bscan_fifos[1].notEmpty) begin
	 data = bscan_fifos[1].first;
	 bscan_fifos[1].deq;
      end
      else if (bscan_fifos[2].notEmpty) begin
	 data = bscan_fifos[2].first;
	 bscan_fifos[2].deq;
      end
      else if (bscan_fifos[3].notEmpty) begin
	 data = bscan_fifos[3].first;
	 bscan_fifos[3].deq;
      end
      else begin
	 data = bscan_fifos[4].first;
	 bscan_fifos[4].deq;
      end
      traceBram.portA.request.put(BRAMRequest {write:True, responseOnWrite:False, address:addrReg, datain:data});
      addrReg <= addrReg + 1;
   endrule
   Reg#(Bit#(16)) seqCounter <- mkReg(0, clocked_by mainclock, reset_by mainreset);
   rule seqinc;
       seqCounter <= seqCounter + 1;
   endrule

   // AXI trace for JTAG
   let m = ps7.m_axi_gp[0].client;
   let s = top.ctrl;
   //mkConnection(m.req_ar, s.req_ar);
   rule connect_req_ar;
       let req <- m.req_ar.get();
       s.req_ar.put(req);
       bscan_fifos[0].enq(
	   {3'h1, interrupt_bit, req.id,
`ifdef AXI_READ_TIMING
                    seqCounter,
`else
                    req.len, req.cache, req.prot, req.size,
                    pack(req.burst == 2'b01), pack(req.lock == 0 && req.qos == 0),
`endif
                    req.address});
   endrule
   //mkConnection(s.resp_read, m.resp_read);
   rule connect_resp_read;
       let resp <- s.resp_read.get();
       m.resp_read.put(resp);
       bscan_fifos[1].enq(
           {3'h2, interrupt_bit, resp.id, resp.resp, resp.last, 13'b0, resp.data});
   endrule
   //mkConnection(m.req_aw, s.req_aw);
   rule connect_req_aw;
       let req <- m.req_aw.get();
       s.req_aw.put(req);
       bscan_fifos[2].enq(
           {3'h3, interrupt_bit, req.id, req.len, req.cache, req.prot, req.size,
                    pack(req.burst == 2'b01), pack(req.lock == 0 && req.qos == 0), req.address});
   endrule
   //mkConnection(m.resp_write, s.resp_write);
   rule connect_resp_write;
       let resp <- m.resp_write.get();
       s.resp_write.put(resp);
       bscan_fifos[3].enq(
           {3'h4, interrupt_bit, resp.id, resp.last, resp.byteEnable, 11'b0, resp.data});
   endrule
   //mkConnection(s.resp_b, m.resp_b);
   rule connect_resp_b;
       let resp <- s.resp_b.get();
       m.resp_b.put(resp);
       bscan_fifos[4].enq(
           {3'h5, interrupt_bit, resp.id, resp.resp, 46'b0});
   endrule
`endif

   mkConnection(top.m_axi, ps7.s_axi_hp[0].axi.server);
   rule send_int_rule;
       ps7.interrupt(interrupt_bit);
   endrule

   interface zynq = ps7.pins;
   interface leds = top.leds;
   interface XADC xadc;
       method Bit#(4) gpio;
           return debugReg;
`ifdef BOZOIFDEF
           return {interrupt_bit,
                 pack((ps7.debug.arvalid == 1)
                   && (ps7.debug.araddr[18:16] == 3'd1)   // /dev/fpga1
                   && (ps7.debug.araddr[15:14] == 2'd2)   // indication
                   && (ps7.debug.araddr[13:8] == 6'd1)),  //     #1
                 ps7.debug.rvalid,
                 pack((ps7.debug.awvalid == 1)
                   && (ps7.debug.awaddr[18:16] == 3'd2)   // /dev/fpga2
                   && (ps7.debug.awaddr[15:14] == 2'd0)   // request
                   && (ps7.debug.awaddr[13:8] == 6'd1))}; //     #1
`endif
       endmethod
   endinterface
   interface pins = top.pins;
   interface unused_clock = mainclock;
   interface unused_reset = mainreset;
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 Clocks :: *;
import Vector            :: *;
import Connectable       :: *;
import Portal            :: *;
import Leds              :: *;
import Top               :: *;
import AxiMasterSlave    :: *;
import XbsvXilinxCells   :: *;
import PS7LIB::*;
import PPS7LIB::*;
import XADC::*;
import BRAM::*;
import Bscan::*;
import FIFOF::*;

//`define TRACE_AXI
//`define AXI_READ_TIMING

(* always_ready, always_enabled *)
interface ZynqTop#(type pins);
   (* prefix="" *)
   interface ZynqPins zynq;
   (* prefix="GPIO" *)
   interface LEDS             leds;
   (* prefix="XADC" *)
   interface XADC             xadc;
   interface pins             pins;
   interface Clock unused_clock;
   interface Reset unused_reset;
endinterface

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

module [Module] mkZynqTopFromPortal#(MkPortalTop#(ipins) constructor)(ZynqTop#(ipins));
   B2C mainclock <- mkB2C();
   PS7 ps7 <- mkPS7(mainclock.c, mainclock.r, clocked_by mainclock.c, reset_by mainclock.r);
   let top <- constructor(clocked_by mainclock.c, reset_by mainclock.r);
   Reg#(Bit#(8)) addrReg <- mkReg(9, clocked_by mainclock.c, reset_by mainclock.r);
   BscanBram#(Bit#(8), Bit#(64)) bscanBram <- mkBscanBram(1, addrReg, clocked_by mainclock.c, reset_by mainclock.r);
   BRAM_Configure bramCfg = defaultValue;
   bramCfg.memorySize = 256;
   bramCfg.latency = 1;
   BRAM2Port#(Bit#(8), Bit#(64)) traceBram <- mkSyncBRAM2Server(bramCfg, mainclock.c, mainclock.r,
								bscanBram.jtagClock, bscanBram.jtagReset);
   mkConnection(bscanBram.bramClient, traceBram.portB);

   ReadOnly#(Bit#(4)) debugReg <- mkNullCrossingWire(mainclock.c, bscanBram.debug());

   let interrupt_bit = top.interrupt ? 1'b1 : 1'b0;

`ifndef TRACE_AXI
   mkConnection(ps7.m_axi_gp[0].client, top.ctrl);
`else

   Vector#(5, FIFOF#(Bit#(64))) bscan_fifos <- replicateM(mkFIFOF(clocked_by mainclock.c, reset_by mainclock.r));

   rule write_bscanBram;
      Bit#(64) data = ?;
      if (bscan_fifos[0].notEmpty) begin
	 data = bscan_fifos[0].first;
	 bscan_fifos[0].deq;
      end
      else if (bscan_fifos[1].notEmpty) begin
	 data = bscan_fifos[1].first;
	 bscan_fifos[1].deq;
      end
      else if (bscan_fifos[2].notEmpty) begin
	 data = bscan_fifos[2].first;
	 bscan_fifos[2].deq;
      end
      else if (bscan_fifos[3].notEmpty) begin
	 data = bscan_fifos[3].first;
	 bscan_fifos[3].deq;
      end
      else begin
	 data = bscan_fifos[4].first;
	 bscan_fifos[4].deq;
      end
      traceBram.portA.request.put(BRAMRequest {write:True, responseOnWrite:False, address:addrReg, datain:data});
      addrReg <= addrReg + 1;
   endrule
   Reg#(Bit#(16)) seqCounter <- mkReg(0, clocked_by mainclock.c, reset_by mainclock.r);
   rule seqinc;
       seqCounter <= seqCounter + 1;
   endrule

   // AXI trace for JTAG
   let m = ps7.m_axi_gp[0].client;
   let s = top.ctrl;
   //mkConnection(m.req_ar, s.req_ar);
   rule connect_req_ar;
       let req <- m.req_ar.get();
       s.req_ar.put(req);
       bscan_fifos[0].enq(
	   {3'h1, interrupt_bit, req.id,
`ifdef AXI_READ_TIMING
                    seqCounter,
`else
                    req.len, req.cache, req.prot, req.size,
                    pack(req.burst == 2'b01), pack(req.lock == 0 && req.qos == 0),
`endif
                    req.address});
   endrule
   //mkConnection(s.resp_read, m.resp_read);
   rule connect_resp_read;
       let resp <- s.resp_read.get();
       m.resp_read.put(resp);
       bscan_fifos[1].enq(
           {3'h2, interrupt_bit, resp.id, resp.resp, resp.last, 13'b0, resp.data});
   endrule
   //mkConnection(m.req_aw, s.req_aw);
   rule connect_req_aw;
       let req <- m.req_aw.get();
       s.req_aw.put(req);
       bscan_fifos[2].enq(
           {3'h3, interrupt_bit, req.id, req.len, req.cache, req.prot, req.size,
                    pack(req.burst == 2'b01), pack(req.lock == 0 && req.qos == 0), req.address});
   endrule
   //mkConnection(m.resp_write, s.resp_write);
   rule connect_resp_write;
       let resp <- m.resp_write.get();
       s.resp_write.put(resp);
       bscan_fifos[3].enq(
           {3'h4, interrupt_bit, resp.id, resp.last, resp.byteEnable, 11'b0, resp.data});
   endrule
   //mkConnection(s.resp_b, m.resp_b);
   rule connect_resp_b;
       let resp <- s.resp_b.get();
       m.resp_b.put(resp);
       bscan_fifos[4].enq(
           {3'h5, interrupt_bit, resp.id, resp.resp, 46'b0});
   endrule
`endif

   mkConnection(top.m_axi, ps7.s_axi_hp[0].axi.server);
   rule send_int_rule;
       ps7.interrupt(interrupt_bit);
   endrule

   rule b2c_rule;
       mainclock.inputclock(ps7.fclkclk()[0]);
       mainclock.inputreset(ps7.fclkresetn()[0]);
   endrule

   interface zynq = ps7.pins;
   interface leds = top.leds;
   interface XADC xadc;
       method Bit#(4) gpio;
           return debugReg;
`ifdef BOZOIFDEF
           return {interrupt_bit,
                 pack((ps7.debug.arvalid == 1)
                   && (ps7.debug.araddr[18:16] == 3'd1)   // /dev/fpga1
                   && (ps7.debug.araddr[15:14] == 2'd2)   // indication
                   && (ps7.debug.araddr[13:8] == 6'd1)),  //     #1
                 ps7.debug.rvalid,
                 pack((ps7.debug.awvalid == 1)
                   && (ps7.debug.awaddr[18:16] == 3'd2)   // /dev/fpga2
                   && (ps7.debug.awaddr[15:14] == 2'd0)   // request
                   && (ps7.debug.awaddr[13:8] == 6'd1))}; //     #1
`endif
       endmethod
   endinterface
   interface pins = top.pins;
   interface unused_clock = mainclock.c;
   interface unused_reset = mainclock.r;
endmodule

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


Prepare for word matched flag. It should not trigger data acquisition to acqFifo.

import FIFOF::*;
import Connectable::*;
import SysConfig::*;
import AsyncPulseSync::*;
import StatusLED::*;
import CycleCounter::*;
import AvalonSlave::*;
import InterruptSender::*;

typedef 3  AvalonAddrSize;
typedef 32 AvalonDataSize;

typedef Bit#(AvalonDataSize) Word;
typedef Word TimeStamp;

typedef Tuple2#(Bit#(NumFlags), TimeStamp) AcqFifoContents;

interface AcqSys;
	(* prefix="" *)
	interface InterruptSenderWires irqWires;
	(* prefix="" *)
	interface AvalonSlaveWires#(AvalonAddrSize, AvalonDataSize) avalonWires;
	(* prefix="" *)
	interface StatusLEDWires ledWires;
	(* prefix="CH" *)
	interface Vector#(NumInputs, AcqIn) inputs;
	(* prefix="", result="STIM" *)
	method Bit#(StimSize) stimuli;
endinterface

(* synthesize, clock_prefix="clk", reset_prefix="reset_n" *)
module mkAcqSys(AcqSys);
	AvalonSlave#(AvalonAddrSize, AvalonDataSize) avalon <- mkAvalonSlave;

	Vector#(NumInputs, SyncPulseIfc) inSyncs <- replicateM(mkAsyncPulseSync);
	Bit#(NumInputs) syncedIn = fromPulseVector(inSyncs);

	CycleCounter#(CyclesStimRate) stimRate <- mkCycleCounter;
	Bit#(NumFlags) flagIn = {1'b0, stimRate.ticked?1'b1:1'b0, syncedIn};

	CycleCounter#(CyclesResolution) cycleCounter <- mkCycleCounter;
	StatusLED#(2) led <- mkStatusLED(flagIn, cycleCounter.ticked);
	Reg#(Bool) acqStarted <- mkReg(False);
	Reg#(TimeStamp) timestamp <- mkReg(0);
	Array#(Reg#(Bit#(NumFlags))) channelFlags <- mkCReg(2, 0);

	FIFOF#(AcqFifoContents) acqFifo <- mkSizedFIFOF(2*valueOf(NumFlags));
	RWire#(AcqFifoContents) acqFifoFirst <- mkRWire;
	FIFOF#(Bit#(StimSize)) stimFifo <- mkFIFOF;

	rule peekAcqFifo;
		acqFifoFirst.wset(acqFifo.first);
	endrule

	rule handleCmd;
		let cmd <- avalon.busClient.request.get;
		(*split*)
		case (cmd) matches
			// Register @0x00: Enable/disable acquisition.
			tagged AvalonRequest{addr: 0, data: .x, command: Write}:
				action
					acqStarted <= x != 0;
					(*split*)
					if(x == 0) begin
						led.errorClear;
						acqFifo.clear;
						stimFifo.clear;
					end
				endaction
			tagged AvalonRequest{addr: 0, data: .*, command: Read}:
				avalon.busClient.response.put(acqStarted ? 1 : 0);
			// Register @0x04: Read flags from the FIFO. MSB is zero if data is valid.
			tagged AvalonRequest{addr: 1, data: .*, command: Read}:
				action
					Bit#(NumFlags) flags = tpl_1(fromMaybe(tuple2(0,0), acqFifoFirst.wget));
					Bit#(TSub#(AvalonDataSize, 1)) extFlags = extend(flags);
					Bit#(1) invalidFlag = isValid(acqFifoFirst.wget) ? 0 : 1;
					avalon.busClient.response.put({invalidFlag, extFlags});
				endaction
			// Register @0x08: Read timestamp from the FIFO. WARNING: may block.
			tagged AvalonRequest{addr: 2, data: .*, command: Read}:
				action
					TimeStamp tstamp = tpl_2(acqFifo.first);
					avalon.busClient.response.put(tstamp);
					acqFifo.deq;
				endaction
			// Register @0x0c: Write sample to stimuli FIFO. WARNING: may block.
			tagged AvalonRequest{addr: 3, data: .x, command: Write}:
				stimFifo.enq(truncate(x));
			// Deal with reads to addresses not listed above
			tagged AvalonRequest{addr: .*, data: .*, command: Read}:
				avalon.busClient.response.put(32'hBADC0FFE);
		endcase
	endrule

	(* fire_when_enabled *)
	rule stimLoad(acqStarted && stimRate.ticked);
		(*split*)
		if(stimFifo.notEmpty) begin
			stimFifo.deq;
		end else begin
			led.errorCondition[1].set;
		end
	endrule

	(* fire_when_enabled *)
	rule timestampUpdate(acqStarted && cycleCounter.ticked);
		let flags = asReg(channelFlags[0]);
		Bit#(TSub#(NumFlags,1)) truncatedFlags = truncate(flags);
		(*split*)
		if(truncatedFlags != 0) begin
			(*split*)
			if(acqFifo.notFull) begin
				acqFifo.enq(tuple2(flags, timestamp));
			end else begin
				led.errorCondition[0].set;  // TX FIFO overflow
			end
		end
		flags <= 0;
		timestamp <= timestamp + 1;
	endrule

	(* fire_when_enabled, no_implicit_conditions *)
	rule blendChannelFlags(acqStarted);
		channelFlags[1] <= channelFlags[1] | flagIn;
	endrule

	method Bit#(StimSize) stimuli =
		acqStarted ? stimFifo.first : 0;

	interface irqWires = irqSender(acqFifo.notEmpty);
	interface avalonWires = avalon.slaveWires;
	interface ledWires = led.wires;
	interface inputs = Vector::map(toAcqIn, inSyncs);
endmodule

import FIFOF::*;
import Connectable::*;
import SysConfig::*;
import AsyncPulseSync::*;
import StatusLED::*;
import CycleCounter::*;
import AvalonSlave::*;
import InterruptSender::*;

typedef 3  AvalonAddrSize;
typedef 32 AvalonDataSize;

typedef Bit#(AvalonDataSize) Word;
typedef Word TimeStamp;

typedef Tuple2#(Bit#(NumFlags), TimeStamp) AcqFifoContents;

interface AcqSys;
	(* prefix="" *)
	interface InterruptSenderWires irqWires;
	(* prefix="" *)
	interface AvalonSlaveWires#(AvalonAddrSize, AvalonDataSize) avalonWires;
	(* prefix="" *)
	interface StatusLEDWires ledWires;
	(* prefix="CH" *)
	interface Vector#(NumInputs, AcqIn) inputs;
	(* prefix="", result="STIM" *)
	method Bit#(StimSize) stimuli;
endinterface

(* synthesize, clock_prefix="clk", reset_prefix="reset_n" *)
module mkAcqSys(AcqSys);
	AvalonSlave#(AvalonAddrSize, AvalonDataSize) avalon <- mkAvalonSlave;

	Vector#(NumInputs, SyncPulseIfc) inSyncs <- replicateM(mkAsyncPulseSync);
	Bit#(NumInputs) syncedIn = fromPulseVector(inSyncs);

	CycleCounter#(CyclesStimRate) stimRate <- mkCycleCounter;
	Bit#(NumFlags) flagIn = {1'b0, stimRate.ticked?1'b1:1'b0, syncedIn};

	CycleCounter#(CyclesResolution) cycleCounter <- mkCycleCounter;
	StatusLED#(2) led <- mkStatusLED(flagIn, cycleCounter.ticked);
	Reg#(Bool) acqStarted <- mkReg(False);
	Reg#(TimeStamp) timestamp <- mkReg(0);
	Array#(Reg#(Bit#(NumFlags))) channelFlags <- mkCReg(2, 0);

	FIFOF#(AcqFifoContents) acqFifo <- mkSizedFIFOF(2*valueOf(NumFlags));
	RWire#(AcqFifoContents) acqFifoFirst <- mkRWire;
	FIFOF#(Bit#(StimSize)) stimFifo <- mkFIFOF;

	rule peekAcqFifo;
		acqFifoFirst.wset(acqFifo.first);
	endrule

	rule handleCmd;
		let cmd <- avalon.busClient.request.get;
		(*split*)
		case (cmd) matches
			// Register @0x00: Enable/disable acquisition.
			tagged AvalonRequest{addr: 0, data: .x, command: Write}:
				action
					acqStarted <= x != 0;
					(*split*)
					if(x == 0) begin
						led.errorClear;
						acqFifo.clear;
						stimFifo.clear;
					end
				endaction
			tagged AvalonRequest{addr: 0, data: .*, command: Read}:
				avalon.busClient.response.put(acqStarted ? 1 : 0);
			// Register @0x04: Read flags from the FIFO. MSB is zero if data is valid.
			tagged AvalonRequest{addr: 1, data: .*, command: Read}:
				action
					Bit#(NumFlags) flags = tpl_1(fromMaybe(tuple2(0,0), acqFifoFirst.wget));
					Bit#(TSub#(AvalonDataSize, 1)) extFlags = extend(flags);
					Bit#(1) invalidFlag = isValid(acqFifoFirst.wget) ? 0 : 1;
					avalon.busClient.response.put({invalidFlag, extFlags});
				endaction
			// Register @0x08: Read timestamp from the FIFO. WARNING: may block.
			tagged AvalonRequest{addr: 2, data: .*, command: Read}:
				action
					TimeStamp tstamp = tpl_2(acqFifo.first);
					avalon.busClient.response.put(tstamp);
					acqFifo.deq;
				endaction
			// Register @0x0c: Write sample to stimuli FIFO. WARNING: may block.
			tagged AvalonRequest{addr: 3, data: .x, command: Write}:
				stimFifo.enq(truncate(x));
			// Deal with reads to addresses not listed above
			tagged AvalonRequest{addr: .*, data: .*, command: Read}:
				avalon.busClient.response.put(32'hBADC0FFE);
		endcase
	endrule

	(* fire_when_enabled *)
	rule stimLoad(acqStarted && stimRate.ticked);
		(*split*)
		if(stimFifo.notEmpty) begin
			stimFifo.deq;
		end else begin
			led.errorCondition[1].set;
		end
	endrule

	(* fire_when_enabled *)
	rule timestampUpdate(acqStarted && cycleCounter.ticked);
		let flags = asReg(channelFlags[0]);
		(*split*)
		if(flags != 0) begin
			(*split*)
			if(acqFifo.notFull) begin
				acqFifo.enq(tuple2(flags, timestamp));
			end else begin
				led.errorCondition[0].set;  // TX FIFO overflow
			end
		end
		flags <= 0;
		timestamp <= timestamp + 1;
	endrule

	(* fire_when_enabled, no_implicit_conditions *)
	rule blendChannelFlags(acqStarted);
		channelFlags[1] <= channelFlags[1] | flagIn;
	endrule

	method Bit#(StimSize) stimuli =
		acqStarted ? stimFifo.first : 0;

	interface irqWires = irqSender(acqFifo.notEmpty);
	interface avalonWires = avalon.slaveWires;
	interface ledWires = led.wires;
	interface inputs = Vector::map(toAcqIn, inSyncs);
endmodule