adapted from Maxcommonsubseq

adapted from Maxcommonsubseq

// 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 FIFO::*;
import FIFOF::*;
import SpecialFIFOs::*;
import GetPut::*;
import StmtFSM::*;
//import Vector::*;
import BRAM::*;
//import Gearbox::*;
import Connectable::*;
import MCSAlgorithm::*;

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

// algorithm
import GotohB::*;
import GotohC::*;

interface SmithwatermanRequest;
   method Action setupA(Bit#(32) strPointer, Bit#(32) strOffset, Bit#(32) strLen);
   method Action setupB(Bit#(32) strPointer, Bit#(32) strOffset, Bit#(32) strLen);
   method Action start(Bit#(32) alg);
endinterface

interface SmithwatermanIndication;
   method Action searchResult(Bit#(32) v);
   method Action setupAComplete();
   method Action setupBComplete();
endinterface

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

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

module mkSmithwatermanRequest#(SmithwatermanIndication indication,
			ObjectReadServer#(busWidth)   setupA_read_server,
			ObjectReadServer#(busWidth)   setupB_read_server,
			ObjectWriteServer#(busWidth)   fetch_write_server )(SmithwatermanRequest)

   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#(14)) aLenReg <- mkReg(0);
  Reg#(Bit#(14)) bLenReg <- mkReg(0);
  Reg#(Bit#(14)) rLenReg <- mkReg(0);
   BRAM2Port#(StringIdx, Bit#(8)) strA  <- mkBRAM2Server(defaultValue);
   BRAM2Port#(StringIdx, Bit#(8)) strB <- mkBRAM2Server(defaultValue);
   BRAM2Port#(LIdx, Bit#(16)) cc <- mkBRAM2Server(defaultValue);
   BRAM2Port#(LIdx, Bit#(16)) dd <- mkBRAM2Server(defaultValue);
   BRAM2Port#(LIdx, Bit#(16)) rr <- mkBRAM2Server(defaultValue);
   BRAM2Port#(LIdx, Bit#(16)) ss <- 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);

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

   MCSAlgorithm cgotohB1 <- mkGotohB(strA.portA, strB.portA, matL0.portA, 1);
   MCSAlgorithm cgotohB0 <- mkGotohB(strA.portA, strB.portA, matL1.portA, 0);
   MCSAlgorithm gotohC <- mkGotohC(strA.portA, strB.portA, cgotohB0, cgotohB1, cc.portB, dd.portB, rr.portB, ss.portB);
   // create BRAM Write client for matL

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

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

   rule gotohC_completion (gotohCRunning && gotohC.fsm.done);
      gotohCRunning <= False;
      indication.searchResult(pack(zeroExtend(gotohC.result())));
      endrule

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

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

   method Action start(Bit#(32) alg);
      $display ("start %d", alg);
      case (alg)
	 3: begin
	       gotohC.fsm.start();
	       gotohCRunning <= True;
	    end
      endcase
   endmethod

endmodule

error: pathspec 'examples/smithwaterman/Smithwaterman.bsv' did not match any file(s) known to git


added StdPcieDma32Top.bsv

added StdPcieDma32Top.bsv

Change-Id: Ia82e34d042bce9b309a3951545aecf880adb8cfa

// 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 Xilinx            :: *;
import XilinxPCIE        :: *;
import Xilinx7PcieBridge :: *;
import PcieToAxiBridge   :: *;
import Portal            :: *;
import Leds              :: *;
import Top               :: *;
import PcieTop           :: *;

(* synthesize *)
module mkSynthesizeablePortalTop(PortalTop#(40, 1, 32, Empty));
   let top <- mkPortalTop();
   interface ctrl = top.ctrl;
   interface m_axi = top.m_axi;
   interface interrupt = top.interrupt;
   interface leds = top.leds;
   interface pins = top.pins;
endmodule

module mkPcieTop #(Clock pci_sys_clk_p, Clock pci_sys_clk_n,
   Clock sys_clk_p,     Clock sys_clk_n,
   Reset pci_sys_reset_n)
   (VC707_FPGA);

   let top <- mkPcieTopFromPortal(pci_sys_clk_p, pci_sys_clk_n, sys_clk_p, sys_clk_n, pci_sys_reset_n,
				  mkSynthesizeablePortalTop);
   return top.fpga;
endmodule: mkPcieTop

error: pathspec 'bsv/StdPcieDma32Top.bsv' did not match any file(s) known to git


LIFO implementation from bluespec forum

LIFO implementation from bluespec forum

/*-
 * Copyright (c) 2015 Jonathan Woodrulf
 * All rights reserved.
 *
 * This software was developed by SRI International and the University of
 * Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237
 * ("CTSRD"), as part of the DARPA CRASH research programme.
 *
 * @BERI_LICENSE_topER_START@
 *
 * Licensed to BERI Open Systems C.I.C. (BERI) under one or more contributor
 * license agreements.  See the NOTICE file distributed with this work for
 * additional information regarding copyright ownership.  BERI licenses this
 * file to you under the BERI Hardware-Software License, Version 1.0 (the
 * "License"); you may not use this file except in compliance with the
 * License.  You may obtain a copy of the License at:
 *
 *   http://www.beri-open-systems.org/legal/license-1-0.txt
 *
 * Unless required by applicable law or agreed to in writing, Work distributed
 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 * CONDITIONS OF ANY KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations under the License.
 *
 * @BERI_LICENSE_topER_END@
 *
 *****************************************************************************

 LF LIFO (Stack) library
 ===========

 This is a library of pure Bluespec LIFO components

 *****************************************************************************/

import ConfigReg::*;
import FIFO::*;
import FIFOF::*;
import RegFile::*;
import Vector::*;
import DReg    :: *;
import SpecialFIFOs :: *;

interface LF#(type data, numeric type depth);
  method Action push(data x);
  method ActionValue#(data) pop();
  method data peek();
  method Bool notFull();
  method Bool notEmpty();
  method Bit#(TLog#(depth)) remaining();
endinterface

// Equal to Bluespec equivelant
module mkUGLF(LF#(data, depth))
provisos(Log#(depth,logDepth),Bits#(data, data_width));
	RegFile#(Bit#(logDepth),data)    rf <- mkRegFileWCF(minBound, maxBound); // BRAM
  Reg#(Bit#(logDepth))         top[2] <- mkCReg(2,0);

  Bit#(logDepth) thisTop = top[0];
  Bit#(logDepth) nextTop = top[1] + 1;
  Bool empty = (top[0]==0);
  Bool full  = (top[1] == -1);

  method Action push(data in);
    rf.upd(nextTop,in);
    top[1] <= nextTop;
  endmethod
  method ActionValue#(data) pop();
    top[0] <= thisTop - 1;
    return rf.sub(thisTop);
  endmethod
  method data peek() = rf.sub(thisTop);
  method Bool notFull() = !full;
  method Bool notEmpty() = !empty;
  method Bit#(TLog#(depth)) remaining() = -1 - thisTop;
endmodule

module mkLF(LF#(data, depth))
provisos(Log#(depth,logDepth),Bits#(data, data_width));
  LF#(data, depth) lf <- mkUGLF();
  return guardLF(lf);
endmodule

function LF#(data, depth) guardLF (LF#(data, depth) lf) =
  interface LF#(data, depth);
    method Action push(data in) if (lf.notFull);
      lf.push(in);
    endmethod
    method ActionValue#(data) pop() if (lf.notEmpty) = lf.pop();
    method data peek() if (lf.notEmpty) = lf.peek;
    method Bool notFull() = lf.notFull;
    method Bool notEmpty() = lf.notEmpty;
    method Bit#(TLog#(depth)) remaining() = lf.remaining();
  endinterface;

error: pathspec 'hw/bsv/LF.bsv' did not match any file(s) known to git


quick version of MIMO using ConnectalBramFifo to help timing closure

error: pathspec 'bsv/ConnectalMimo.bsv' did not match any file(s) known to git


rename everything, changed tdo to ReadOnly

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

// The Jtag state machine is copied from the Bluespec Small Examples Tap.bsv

interface SerialReg#(type regtype);
   method Action update();
   method Action capture();
   method Action shift(bit d);
   interface Reg#(regtype) r;
   interface Readonly#(bit) tdo;
endinterface

// can I pass in an initial value for the register?

module mkSerialReg#(type regtype)(SerialReg);

   Reg#(regtype) dreg <- mkReg(?);
   Reg#(regtype) sreg <- mkReg(?);
   Reg#(bit) oreg <- mkReg(?);

   method Action update ();
      dreg <= sreg;
   endmethod

   method Action capture ();
      sreg <= dreg;
   endmethod

   method Action shift (bit d);
      sreg <= {d, (sreg >> 1)};
      oreg <= sreg[0];
   endmethod

   interface r = dreg;
   interface tdo = regToReadOnly(oreg);

endmodule

error: pathspec 'examples/serialconfig/JtagReg.bsv' did not match any file(s) known to git


multiprotocol sample output

multiprotocol sample output

import BUtils::*;
import BuildVector::*;
import CBus::*;
import ClientServer::*;
import Connectable::*;
import DbgDefs::*;
import DefaultValue::*;
import Ethernet::*;
import FIFO::*;
import FIFOF::*;
import FShow::*;
import GetPut::*;
import List::*;
import MIMO::*;
import MatchTable::*;
import PacketBuffer::*;
import PrintTrace::*;
import Pipe::*;
import Register::*;
import SpecialFIFOs::*;
import StmtFSM::*;
import TxRx::*;
import Utils::*;
import Vector::*;
typedef struct {
  Bit#(9) ingress_port;
  Bit#(32) packet_length;
  Bit#(9) egress_spec;
  Bit#(9) egress_port;
  Bit#(32) egress_instance;
  Bit#(32) instance_type;
  Bit#(32) clone_spec;
  Bit#(5) _padding;
} StandardMetadataT deriving (Bits, Eq);
instance DefaultValue#(StandardMetadataT);
  defaultValue = unpack(0);
endinstance
instance DefaultMask#(StandardMetadataT);
  defaultMask = unpack(maxBound);
endinstance
function StandardMetadataT extract_standard_metadata_t(Bit#(160) data);
  return unpack(byteSwap(data));
endfunction

typedef struct {
  Bit#(48) dstAddr;
  Bit#(48) srcAddr;
  Bit#(16) etherType;
} EthernetT deriving (Bits, Eq);
instance DefaultValue#(EthernetT);
  defaultValue = unpack(0);
endinstance
instance DefaultMask#(EthernetT);
  defaultMask = unpack(maxBound);
endinstance
function EthernetT extract_ethernet_t(Bit#(112) data);
  return unpack(byteSwap(data));
endfunction

typedef struct {
  Bit#(3) pcp;
  Bit#(1) cfi;
  Bit#(12) vid;
  Bit#(16) etherType;
} VlanTagT deriving (Bits, Eq);
instance DefaultValue#(VlanTagT);
  defaultValue = unpack(0);
endinstance
instance DefaultMask#(VlanTagT);
  defaultMask = unpack(maxBound);
endinstance
function VlanTagT extract_vlan_tag_t(Bit#(32) data);
  return unpack(byteSwap(data));
endfunction

typedef struct {
  Bit#(4) version;
  Bit#(4) ihl;
  Bit#(8) diffserv;
  Bit#(16) totalLen;
  Bit#(16) identification;
  Bit#(3) flags;
  Bit#(13) fragOffset;
  Bit#(8) ttl;
  Bit#(8) protocol;
  Bit#(16) hdrChecksum;
  Bit#(32) srcAddr;
  Bit#(32) dstAddr;
} Ipv4T deriving (Bits, Eq);
instance DefaultValue#(Ipv4T);
  defaultValue = unpack(0);
endinstance
instance DefaultMask#(Ipv4T);
  defaultMask = unpack(maxBound);
endinstance
function Ipv4T extract_ipv4_t(Bit#(160) data);
  return unpack(byteSwap(data));
endfunction

typedef struct {
  Bit#(4) version;
  Bit#(8) trafficClass;
  Bit#(20) flowLabel;
  Bit#(16) payloadLen;
  Bit#(8) nextHdr;
  Bit#(8) hopLimit;
  Bit#(128) srcAddr;
  Bit#(128) dstAddr;
} Ipv6T deriving (Bits, Eq);
instance DefaultValue#(Ipv6T);
  defaultValue = unpack(0);
endinstance
instance DefaultMask#(Ipv6T);
  defaultMask = unpack(maxBound);
endinstance
function Ipv6T extract_ipv6_t(Bit#(320) data);
  return unpack(byteSwap(data));
endfunction

typedef struct {
  Bit#(16) typeCode;
  Bit#(16) hdrChecksum;
} IcmpT deriving (Bits, Eq);
instance DefaultValue#(IcmpT);
  defaultValue = unpack(0);
endinstance
instance DefaultMask#(IcmpT);
  defaultMask = unpack(maxBound);
endinstance
function IcmpT extract_icmp_t(Bit#(32) data);
  return unpack(byteSwap(data));
endfunction

typedef struct {
  Bit#(16) srcPort;
  Bit#(16) dstPort;
  Bit#(32) seqNo;
  Bit#(32) ackNo;
  Bit#(4) dataOffset;
  Bit#(4) res;
  Bit#(8) flags;
  Bit#(16) window;
  Bit#(16) checksum;
  Bit#(16) urgentPtr;
} TcpT deriving (Bits, Eq);
instance DefaultValue#(TcpT);
  defaultValue = unpack(0);
endinstance
instance DefaultMask#(TcpT);
  defaultMask = unpack(maxBound);
endinstance
function TcpT extract_tcp_t(Bit#(160) data);
  return unpack(byteSwap(data));
endfunction

typedef struct {
  Bit#(16) srcPort;
  Bit#(16) dstPort;
  Bit#(16) length_;
  Bit#(16) checksum;
} UdpT deriving (Bits, Eq);
instance DefaultValue#(UdpT);
  defaultValue = unpack(0);
endinstance
instance DefaultMask#(UdpT);
  defaultMask = unpack(maxBound);
endinstance
function UdpT extract_udp_t(Bit#(64) data);
  return unpack(byteSwap(data));
endfunction

typedef struct {
  Bit#(1) drop;
  Bit#(8) egress_port;
  Bit#(4) packet_type;
  Bit#(3) _padding;
} IngressMetadataT deriving (Bits, Eq);
instance DefaultValue#(IngressMetadataT);
  defaultValue = unpack(0);
endinstance
instance DefaultMask#(IngressMetadataT);
  defaultMask = unpack(maxBound);
endinstance
function IngressMetadataT extract_ingress_metadata_t(Bit#(16) data);
  return unpack(byteSwap(data));
endfunction

typedef struct {
  PacketInstance pkt;
  MetadataT meta;
} MetadataRequest deriving (Bits, Eq, FShow);
typedef union tagged {
  struct {
    PacketInstance pkt;
    MetadataT meta;
  } EthertypeMatchL2PacketRspT;
  struct {
    PacketInstance pkt;
    MetadataT meta;
  } EthertypeMatchIpv4PacketRspT;
  struct {
    PacketInstance pkt;
    MetadataT meta;
  } EthertypeMatchIpv6PacketRspT;
  struct {
    PacketInstance pkt;
    MetadataT meta;
  } EthertypeMatchMplsPacketRspT;
  struct {
    PacketInstance pkt;
    MetadataT meta;
  } EthertypeMatchMimPacketRspT;
  struct {
    PacketInstance pkt;
    MetadataT meta;
  } Ipv4MatchNopRspT;
  struct {
    PacketInstance pkt;
    MetadataT meta;
  } Ipv4MatchSetEgressPortRspT;
  struct {
    PacketInstance pkt;
    MetadataT meta;
  } Ipv6MatchNopRspT;
  struct {
    PacketInstance pkt;
    MetadataT meta;
  } Ipv6MatchSetEgressPortRspT;
  struct {
    PacketInstance pkt;
    MetadataT meta;
  } L2MatchNopRspT;
  struct {
    PacketInstance pkt;
    MetadataT meta;
  } L2MatchSetEgressPortRspT;
} MetadataResponse deriving (Bits, Eq);
typedef struct {
  Maybe#(Bit#(4)) ing_metadata$packet_type;
  Maybe#(Bit#(8)) ing_metadata$egress_port;
  Maybe#(Bit#(8)) runtime_egress_port;
  Maybe#(Bit#(16)) ethernet$etherType;
  Maybe#(Bit#(32)) ipv4$srcAddr;
  Maybe#(Bit#(128)) ipv6$srcAddr;
  Maybe#(Bit#(48)) ethernet$srcAddr;
} MetadataT deriving (Bits, Eq, FShow);
instance DefaultValue#(MetadataT);
  defaultValue = unpack(0);
endinstance
// ====== PARSER ======

typedef enum {
  StateStart,
  StateParseEthernet,
  StateParseVlanTag,
  StateParseIpv4,
  StateParseIpv6,
  StateParseIcmp,
  StateParseTcp,
  StateParseUdp
} ParserState deriving (Bits, Eq);
interface Parser;
  interface Put#(EtherData) frameIn;
  interface Get#(MetadataT) meta;
  interface Put#(int) verbosity;
  method ParserPerfRec read_perf_info ();
endinterface
module mkParser  (Parser);
  PulseWire w_parse_ipv6_parse_tcp <- mkPulseWireOR();
  PulseWire w_parse_ipv4_parse_icmp <- mkPulseWireOR();
  PulseWire w_parse_ipv4_start <- mkPulseWireOR();
  PulseWire w_parse_ipv6_start <- mkPulseWireOR();
  PulseWire w_parse_ethernet_parse_ipv6 <- mkPulseWireOR();
  PulseWire w_parse_ipv4_parse_udp <- mkPulseWireOR();
  PulseWire w_parse_ethernet_parse_ipv4 <- mkPulseWireOR();
  PulseWire w_parse_tcp_start <- mkPulseWireOR();
  PulseWire w_parse_udp_start <- mkPulseWireOR();
  PulseWire w_parse_ethernet_parse_vlan_tag <- mkPulseWireOR();
  PulseWire w_parse_ethernet_start <- mkPulseWireOR();
  PulseWire w_parse_vlan_tag_start <- mkPulseWireOR();
  PulseWire w_start_parse_ethernet <- mkPulseWireOR();
  PulseWire w_parse_vlan_tag_parse_ipv6 <- mkPulseWireOR();
  PulseWire w_parse_vlan_tag_parse_ipv4 <- mkPulseWireOR();
  PulseWire w_parse_ipv6_parse_icmp <- mkPulseWireOR();
  PulseWire w_parse_ipv6_parse_udp <- mkPulseWireOR();
  PulseWire w_parse_icmp_start <- mkPulseWireOR();
  PulseWire w_parse_ipv4_parse_tcp <- mkPulseWireOR();
  PulseWire w_parse_done <- mkPulseWire();
  Reg#(Bool) parse_done[2] <- mkCReg(2, True);
  Reg#(int) cr_verbosity[2] <- mkCRegU(2);
  FIFOF#(int) cr_verbosity_ff <- mkFIFOF;
  rule set_verbosity;
    let x = cr_verbosity_ff.first;
    cr_verbosity_ff.deq;
    cr_verbosity[1] <= x;
  endrule

  FIFO#(ParserState) parse_state_ff <- mkPipelineFIFO();
  FIFOF#(Maybe#(Bit#(128))) data_ff <- mkDFIFOF(tagged Invalid);
  FIFOF#(Maybe#(EthernetT)) ethernet_out_ff <- mkDFIFOF(tagged Invalid);
  FIFOF#(Maybe#(IcmpT)) icmp_out_ff <- mkDFIFOF(tagged Invalid);
  FIFOF#(Maybe#(Ipv4T)) ipv4_out_ff <- mkDFIFOF(tagged Invalid);
  FIFOF#(Maybe#(Ipv6T)) ipv6_out_ff <- mkDFIFOF(tagged Invalid);
  FIFOF#(Maybe#(VlanTagT)) vlan_tag_out_ff <- mkDFIFOF(tagged Invalid);
  FIFOF#(Maybe#(TcpT)) tcp_out_ff <- mkDFIFOF(tagged Invalid);
  FIFOF#(Maybe#(UdpT)) udp_out_ff <- mkDFIFOF(tagged Invalid);

  FIFOF#(EtherData) data_in_ff <- mkFIFOF;
  FIFOF#(MetadataT) meta_in_ff <- printTraceT("metadata_ff", mkFIFOF);
  PulseWire w_parse_header_done <- mkPulseWireOR();
  PulseWire w_load_header <- mkPulseWireOR();
  Reg#(Bit#(32)) rg_next_header_len[3] <- mkCReg(3, 0);
  Reg#(Bit#(32)) rg_buffered[3] <- mkCReg(3, 0);
  Reg#(Bit#(32)) rg_shift_amt[3] <- mkCReg(3, 0);
  Reg#(Bit#(512)) rg_tmp[2] <- mkCReg(2, 0);
  function Action dbg3(Fmt msg);
    action
      if (cr_verbosity[0] > 3) begin
        $display("(%0d) ", $time, msg);
      end
    endaction
  endfunction
  function Action succeed_and_next(Bit#(32) offset);
    action
      rg_buffered[0] <= rg_buffered[0] - offset;
      rg_shift_amt[0] <= rg_buffered[0] - offset;
      dbg3($format("succeed_and_next subtract offset = %d shift_amt/buffered = %d", offset, rg_buffered[0] - offset));
    endaction
  endfunction
  function Action fetch_next_header0(Bit#(32) len);
    action
      rg_next_header_len[0] <= len;
      w_parse_header_done.send();
    endaction
  endfunction
  function Action fetch_next_header1(Bit#(32) len);
    action
      rg_next_header_len[1] <= len;
      w_parse_header_done.send();
    endaction
  endfunction
  function Action move_shift_amt(Bit#(32) len);
    action
      rg_shift_amt[0] <= rg_shift_amt[0] + len;
      w_load_header.send();
    endaction
  endfunction
  function Action failed_and_trap(Bit#(32) offset);
    action
      rg_buffered[0] <= 0;
    endaction
  endfunction
  function Action report_parse_action(ParserState state, Bit#(32) offset, Bit#(128) data, Bit#(512) buff);
    action
      if (cr_verbosity[0] > 3) begin
        $display("(%0d) Parser State %h buffered %d, %h, %h", $time, state, offset, data, buff);
      end
    endaction
  endfunction
  let sop_this_cycle = data_in_ff.first.sop;
  let eop_this_cycle = data_in_ff.first.eop;
  let data_this_cycle = data_in_ff.first.data;
  function Action compute_next_state_parse_ethernet(Bit#(16) etherType);
    action
      let v = {etherType};
      if (v == 'h8100) begin
        dbg3($format("transit to parse_vlan_tag"));
        w_parse_ethernet_parse_vlan_tag.send();
      end
      else if (v == 'h9100) begin
        dbg3($format("transit to parse_vlan_tag"));
        w_parse_ethernet_parse_vlan_tag.send();
      end
      else if (v == 'h0800) begin
        dbg3($format("transit to parse_ipv4"));
        w_parse_ethernet_parse_ipv4.send();
      end
      else if (v == 'h86dd) begin
        dbg3($format("transit to parse_ipv6"));
        w_parse_ethernet_parse_ipv6.send();
      end
      else begin
        dbg3($format("transit to start"));
        w_parse_ethernet_start.send();
      end
    endaction
  endfunction
  function Action compute_next_state_parse_vlan_tag(Bit#(16) etherType);
    action
      let v = {etherType};
      if (v == 'h0800) begin
        dbg3($format("transit to parse_ipv4"));
        w_parse_vlan_tag_parse_ipv4.send();
      end
      else if (v == 'h86dd) begin
        dbg3($format("transit to parse_ipv6"));
        w_parse_vlan_tag_parse_ipv6.send();
      end
      else begin
        dbg3($format("transit to start"));
        w_parse_vlan_tag_start.send();
      end
    endaction
  endfunction
  function Action compute_next_state_parse_ipv4(Bit#(13) fragOffset, Bit#(4) ihl, Bit#(8) protocol);
    action
      let v = {fragOffset, ihl, protocol};
      if ((v & 'h00000fff) == 'h00000501) begin
        dbg3($format("transit to parse_icmp"));
        w_parse_ipv4_parse_icmp.send();
      end
      else if ((v & 'h00000fff) == 'h00000506) begin
        dbg3($format("transit to parse_tcp"));
        w_parse_ipv4_parse_tcp.send();
      end
      else if ((v & 'h00000fff) == 'h00000511) begin
        dbg3($format("transit to parse_udp"));
        w_parse_ipv4_parse_udp.send();
      end
      else begin
        dbg3($format("transit to start"));
        w_parse_ipv4_start.send();
      end
    endaction
  endfunction
  function Action compute_next_state_parse_ipv6(Bit#(8) nextHdr);
    action
      let v = {nextHdr};
      if (v == 'h01) begin
        dbg3($format("transit to parse_icmp"));
        w_parse_ipv6_parse_icmp.send();
      end
      else if (v == 'h06) begin
        dbg3($format("transit to parse_tcp"));
        w_parse_ipv6_parse_tcp.send();
      end
      else if (v == 'h11) begin
        dbg3($format("transit to parse_udp"));
        w_parse_ipv6_parse_udp.send();
      end
      else begin
        dbg3($format("transit to start"));
        w_parse_ipv6_start.send();
      end
    endaction
  endfunction
  function Action compute_next_state_parse_icmp();
    action
      dbg3($format("transit to start"));
      w_parse_icmp_start.send();
    endaction
  endfunction
  function Action compute_next_state_parse_tcp();
    action
      dbg3($format("transit to start"));
      w_parse_tcp_start.send();
    endaction
  endfunction
  function Action compute_next_state_parse_udp();
    action
      dbg3($format("transit to start"));
      w_parse_udp_start.send();
    endaction
  endfunction
  rule rl_data_ff_load if ((!parse_done[1] && rg_buffered[2] < rg_next_header_len[2]) && (w_parse_header_done || w_load_header));
    let v = data_in_ff.first.data;
    data_in_ff.deq;
    rg_buffered[2] <= rg_buffered[2] + 128;
    data_ff.enq(tagged Valid v);
    dbg3($format("dequeue data %d %d", rg_buffered[2], rg_next_header_len[2]));
  endrule

  rule rl_start_state_deq if (parse_done[1] && sop_this_cycle && !w_parse_header_done);
    let v = data_in_ff.first.data;
    data_ff.enq(tagged Valid v);
    rg_buffered[2] <= 128;
    rg_shift_amt[2] <= 0;
    parse_done[1] <= False;
    parse_state_ff.enq(StateParseEthernet);
  endrule

  rule rl_start_state_idle if (parse_done[1] && (!sop_this_cycle || w_parse_header_done));
    data_in_ff.deq;
  endrule

  rule rl_parse_done if (w_parse_done);
    MetadataT meta = defaultValue;
    let ethernet <- toGet(ethernet_out_ff).get;
    let icmp <- toGet(icmp_out_ff).get;
    let ipv4 <- toGet(ipv4_out_ff).get;
    let ipv6 <- toGet(ipv6_out_ff).get;
    let vlan <- toGet(vlan_tag_out_ff).get;
    let tcp <- toGet(tcp_out_ff).get;
    let udp <- toGet(udp_out_ff).get;
    if (isValid(ethernet)) begin
      meta.ethernet$etherType = tagged Valid fromMaybe(?, ethernet).etherType;
      meta.ethernet$srcAddr = tagged Valid fromMaybe(?, ethernet).srcAddr;
    end
    if (isValid(ipv4)) begin
      meta.ipv4$srcAddr = tagged Valid fromMaybe(?, ipv4).srcAddr;
    end
    if (isValid(ipv6)) begin
      meta.ipv6$srcAddr = tagged Valid fromMaybe(?, ipv6).srcAddr;
    end
    meta_in_ff.enq(meta);
  endrule

  (* fire_when_enabled *)
  rule rl_parse_ethernet_load if ((parse_state_ff.first == StateParseEthernet) && (rg_buffered[0] < 112));
    report_parse_action(parse_state_ff.first, rg_buffered[0], data_this_cycle, rg_tmp[0]);
    if (isValid(data_ff.first)) begin
      data_ff.deq;
      let data = zeroExtend(data_this_cycle) << rg_shift_amt[0] | rg_tmp[0];
      rg_tmp[0] <= zeroExtend(data);
      move_shift_amt(128);
    end
  endrule

  (* fire_when_enabled *)
  rule rl_parse_ethernet_extract if ((parse_state_ff.first == StateParseEthernet) && (rg_buffered[0] >= 112));
    let data = rg_tmp[0];
    if (isValid(data_ff.first)) begin
      data_ff.deq;
      data = zeroExtend(data_this_cycle) << rg_shift_amt[0] | rg_tmp[0];
    end
    report_parse_action(parse_state_ff.first, rg_buffered[0], data_this_cycle, data);
    let ethernet_t = extract_ethernet_t(truncate(data));
    compute_next_state_parse_ethernet(ethernet_t.etherType);
    ethernet_out_ff.enq(tagged Valid ethernet_t);
    rg_tmp[0] <= zeroExtend(data >> 112);
    succeed_and_next(112);
    dbg3($format("extract %s", "parse_ethernet"));
    parse_state_ff.deq;
  endrule

  (* mutually_exclusive="rl_parse_ethernet_parse_vlan_tag, rl_parse_ethernet_parse_ipv4, rl_parse_ethernet_parse_ipv6, rl_parse_ethernet_start" *)
  rule rl_parse_ethernet_parse_vlan_tag if ((w_parse_ethernet_parse_vlan_tag));
    parse_state_ff.enq(StateParseVlanTag);
    dbg3($format("%s -> %s", "parse_ethernet", "parse_vlan_tag"));
    fetch_next_header0(32);
  endrule

  rule rl_parse_ethernet_parse_ipv4 if ((w_parse_ethernet_parse_ipv4));
    parse_state_ff.enq(StateParseIpv4);
    dbg3($format("%s -> %s", "parse_ethernet", "parse_ipv4"));
    fetch_next_header0(160);
  endrule

  rule rl_parse_ethernet_parse_ipv6 if ((w_parse_ethernet_parse_ipv6));
    parse_state_ff.enq(StateParseIpv6);
    dbg3($format("%s -> %s", "parse_ethernet", "parse_ipv6"));
    fetch_next_header0(320);
  endrule

  rule rl_parse_ethernet_start if ((w_parse_ethernet_start));
    parse_done[0] <= True;
    w_parse_done.send();
    dbg3($format("%s -> %s", "parse_ethernet", "start"));
    fetch_next_header0(0);
  endrule

  (* fire_when_enabled *)
  rule rl_parse_vlan_tag_load if ((parse_state_ff.first == StateParseVlanTag) && (rg_buffered[0] < 32));
    report_parse_action(parse_state_ff.first, rg_buffered[0], data_this_cycle, rg_tmp[0]);
    if (isValid(data_ff.first)) begin
      data_ff.deq;
      let data = zeroExtend(data_this_cycle) << rg_shift_amt[0] | rg_tmp[0];
      rg_tmp[0] <= zeroExtend(data);
      move_shift_amt(128);
    end
  endrule

  (* fire_when_enabled *)
  rule rl_parse_vlan_tag_extract if ((parse_state_ff.first == StateParseVlanTag) && (rg_buffered[0] >= 32));
    let data = rg_tmp[0];
    if (isValid(data_ff.first)) begin
      data_ff.deq;
      data = zeroExtend(data_this_cycle) << rg_shift_amt[0] | rg_tmp[0];
    end
    report_parse_action(parse_state_ff.first, rg_buffered[0], data_this_cycle, data);
    let vlan_tag_t = extract_vlan_tag_t(truncate(data));
    compute_next_state_parse_vlan_tag(vlan_tag_t.etherType);
    rg_tmp[0] <= zeroExtend(data >> 32);
    succeed_and_next(32);
    dbg3($format("extract %s", "parse_vlan_tag"));
    parse_state_ff.deq;
  endrule

  (* mutually_exclusive="rl_parse_vlan_tag_parse_ipv4, rl_parse_vlan_tag_parse_ipv6, rl_parse_vlan_tag_start" *)
  rule rl_parse_vlan_tag_parse_ipv4 if ((w_parse_vlan_tag_parse_ipv4));
    parse_state_ff.enq(StateParseIpv4);
    dbg3($format("%s -> %s", "parse_vlan_tag", "parse_ipv4"));
    fetch_next_header0(160);
  endrule

  rule rl_parse_vlan_tag_parse_ipv6 if ((w_parse_vlan_tag_parse_ipv6));
    parse_state_ff.enq(StateParseIpv6);
    dbg3($format("%s -> %s", "parse_vlan_tag", "parse_ipv6"));
    fetch_next_header0(320);
  endrule

  rule rl_parse_vlan_tag_start if ((w_parse_vlan_tag_start));
    parse_done[0] <= True;
    w_parse_done.send();
    dbg3($format("%s -> %s", "parse_vlan_tag", "start"));
    fetch_next_header0(0);
  endrule

  (* fire_when_enabled *)
  rule rl_parse_ipv4_load if ((parse_state_ff.first == StateParseIpv4) && (rg_buffered[0] < 160));
    report_parse_action(parse_state_ff.first, rg_buffered[0], data_this_cycle, rg_tmp[0]);
    if (isValid(data_ff.first)) begin
      data_ff.deq;
      let data = zeroExtend(data_this_cycle) << rg_shift_amt[0] | rg_tmp[0];
      rg_tmp[0] <= zeroExtend(data);
      move_shift_amt(128);
    end
  endrule

  (* fire_when_enabled *)
  rule rl_parse_ipv4_extract if ((parse_state_ff.first == StateParseIpv4) && (rg_buffered[0] >= 160));
    let data = rg_tmp[0];
    if (isValid(data_ff.first)) begin
      data_ff.deq;
      data = zeroExtend(data_this_cycle) << rg_shift_amt[0] | rg_tmp[0];
    end
    report_parse_action(parse_state_ff.first, rg_buffered[0], data_this_cycle, data);
    let ipv4_t = extract_ipv4_t(truncate(data));
    compute_next_state_parse_ipv4(ipv4_t.fragOffset,ipv4_t.ihl,ipv4_t.protocol);
    rg_tmp[0] <= zeroExtend(data >> 160);
    succeed_and_next(160);
    dbg3($format("extract %s", "parse_ipv4"));
    ipv4_out_ff.enq(tagged Valid ipv4_t);
    parse_state_ff.deq;
  endrule

  (* mutually_exclusive="rl_parse_ipv4_parse_icmp, rl_parse_ipv4_parse_tcp, rl_parse_ipv4_parse_udp, rl_parse_ipv4_start" *)
  rule rl_parse_ipv4_parse_icmp if ((w_parse_ipv4_parse_icmp));
    parse_state_ff.enq(StateParseIcmp);
    dbg3($format("%s -> %s", "parse_ipv4", "parse_icmp"));
    fetch_next_header0(32);
  endrule

  rule rl_parse_ipv4_parse_tcp if ((w_parse_ipv4_parse_tcp));
    parse_state_ff.enq(StateParseTcp);
    dbg3($format("%s -> %s", "parse_ipv4", "parse_tcp"));
    fetch_next_header0(160);
  endrule

  rule rl_parse_ipv4_parse_udp if ((w_parse_ipv4_parse_udp));
    parse_state_ff.enq(StateParseUdp);
    dbg3($format("%s -> %s", "parse_ipv4", "parse_udp"));
    fetch_next_header0(64);
  endrule

  rule rl_parse_ipv4_start if ((w_parse_ipv4_start));
    parse_done[0] <= True;
    w_parse_done.send();
    dbg3($format("%s -> %s", "parse_ipv4", "start"));
    fetch_next_header0(0);
  endrule

  (* fire_when_enabled *)
  rule rl_parse_ipv6_load if ((parse_state_ff.first == StateParseIpv6) && (rg_buffered[0] < 320));
    report_parse_action(parse_state_ff.first, rg_buffered[0], data_this_cycle, rg_tmp[0]);
    if (isValid(data_ff.first)) begin
      data_ff.deq;
      let data = zeroExtend(data_this_cycle) << rg_shift_amt[0] | rg_tmp[0];
      rg_tmp[0] <= zeroExtend(data);
      move_shift_amt(128);
    end
  endrule

  (* fire_when_enabled *)
  rule rl_parse_ipv6_extract if ((parse_state_ff.first == StateParseIpv6) && (rg_buffered[0] >= 320));
    let data = rg_tmp[0];
    if (isValid(data_ff.first)) begin
      data_ff.deq;
      data = zeroExtend(data_this_cycle) << rg_shift_amt[0] | rg_tmp[0];
    end
    report_parse_action(parse_state_ff.first, rg_buffered[0], data_this_cycle, data);
    let ipv6_t = extract_ipv6_t(truncate(data));
    compute_next_state_parse_ipv6(ipv6_t.nextHdr);
    rg_tmp[0] <= zeroExtend(data >> 320);
    succeed_and_next(320);
    dbg3($format("extract %s", "parse_ipv6"));
    parse_state_ff.deq;
  endrule

  (* mutually_exclusive="rl_parse_ipv6_parse_icmp, rl_parse_ipv6_parse_tcp, rl_parse_ipv6_parse_udp, rl_parse_ipv6_start" *)
  rule rl_parse_ipv6_parse_icmp if ((w_parse_ipv6_parse_icmp));
    parse_state_ff.enq(StateParseIcmp);
    dbg3($format("%s -> %s", "parse_ipv6", "parse_icmp"));
    fetch_next_header0(32);
  endrule

  rule rl_parse_ipv6_parse_tcp if ((w_parse_ipv6_parse_tcp));
    parse_state_ff.enq(StateParseTcp);
    dbg3($format("%s -> %s", "parse_ipv6", "parse_tcp"));
    fetch_next_header0(160);
  endrule

  rule rl_parse_ipv6_parse_udp if ((w_parse_ipv6_parse_udp));
    parse_state_ff.enq(StateParseUdp);
    dbg3($format("%s -> %s", "parse_ipv6", "parse_udp"));
    fetch_next_header0(64);
  endrule

  rule rl_parse_ipv6_start if ((w_parse_ipv6_start));
    parse_done[0] <= True;
    w_parse_done.send();
    dbg3($format("%s -> %s", "parse_ipv6", "start"));
    fetch_next_header0(0);
  endrule

  (* fire_when_enabled *)
  rule rl_parse_icmp_load if ((parse_state_ff.first == StateParseIcmp) && (rg_buffered[0] < 32));
    report_parse_action(parse_state_ff.first, rg_buffered[0], data_this_cycle, rg_tmp[0]);
    if (isValid(data_ff.first)) begin
      data_ff.deq;
      let data = zeroExtend(data_this_cycle) << rg_shift_amt[0] | rg_tmp[0];
      rg_tmp[0] <= zeroExtend(data);
      move_shift_amt(128);
    end
  endrule

  (* fire_when_enabled *)
  rule rl_parse_icmp_extract if ((parse_state_ff.first == StateParseIcmp) && (rg_buffered[0] >= 32));
    let data = rg_tmp[0];
    if (isValid(data_ff.first)) begin
      data_ff.deq;
      data = zeroExtend(data_this_cycle) << rg_shift_amt[0] | rg_tmp[0];
    end
    report_parse_action(parse_state_ff.first, rg_buffered[0], data_this_cycle, data);
    compute_next_state_parse_icmp();
    rg_tmp[0] <= zeroExtend(data >> 32);
    succeed_and_next(32);
    dbg3($format("extract %s", "parse_icmp"));
    parse_state_ff.deq;
  endrule

  (* mutually_exclusive="rl_parse_icmp_start" *)
  rule rl_parse_icmp_start if ((w_parse_icmp_start));
    parse_done[0] <= True;
    w_parse_done.send();
    dbg3($format("%s -> %s", "parse_icmp", "start"));
    fetch_next_header0(0);
  endrule

  (* fire_when_enabled *)
  rule rl_parse_tcp_load if ((parse_state_ff.first == StateParseTcp) && (rg_buffered[0] < 160));
    report_parse_action(parse_state_ff.first, rg_buffered[0], data_this_cycle, rg_tmp[0]);
    if (isValid(data_ff.first)) begin
      data_ff.deq;
      let data = zeroExtend(data_this_cycle) << rg_shift_amt[0] | rg_tmp[0];
      rg_tmp[0] <= zeroExtend(data);
      move_shift_amt(128);
    end
  endrule

  (* fire_when_enabled *)
  rule rl_parse_tcp_extract if ((parse_state_ff.first == StateParseTcp) && (rg_buffered[0] >= 160));
    let data = rg_tmp[0];
    if (isValid(data_ff.first)) begin
      data_ff.deq;
      data = zeroExtend(data_this_cycle) << rg_shift_amt[0] | rg_tmp[0];
    end
    report_parse_action(parse_state_ff.first, rg_buffered[0], data_this_cycle, data);
    compute_next_state_parse_tcp();
    rg_tmp[0] <= zeroExtend(data >> 160);
    succeed_and_next(160);
    dbg3($format("extract %s", "parse_tcp"));
    parse_state_ff.deq;
  endrule

  (* mutually_exclusive="rl_parse_tcp_start" *)
  rule rl_parse_tcp_start if ((w_parse_tcp_start));
    parse_done[0] <= True;
    w_parse_done.send();
    dbg3($format("%s -> %s", "parse_tcp", "start"));
    fetch_next_header0(0);
  endrule

  (* fire_when_enabled *)
  rule rl_parse_udp_load if ((parse_state_ff.first == StateParseUdp) && (rg_buffered[0] < 64));
    report_parse_action(parse_state_ff.first, rg_buffered[0], data_this_cycle, rg_tmp[0]);
    if (isValid(data_ff.first)) begin
      data_ff.deq;
      let data = zeroExtend(data_this_cycle) << rg_shift_amt[0] | rg_tmp[0];
      rg_tmp[0] <= zeroExtend(data);
      move_shift_amt(128);
    end
  endrule

  (* fire_when_enabled *)
  rule rl_parse_udp_extract if ((parse_state_ff.first == StateParseUdp) && (rg_buffered[0] >= 64));
    let data = rg_tmp[0];
    if (isValid(data_ff.first)) begin
      data_ff.deq;
      data = zeroExtend(data_this_cycle) << rg_shift_amt[0] | rg_tmp[0];
    end
    report_parse_action(parse_state_ff.first, rg_buffered[0], data_this_cycle, data);
    compute_next_state_parse_udp();
    rg_tmp[0] <= zeroExtend(data >> 64);
    succeed_and_next(64);
    dbg3($format("extract %s", "parse_udp"));
    parse_state_ff.deq;
  endrule

  (* mutually_exclusive="rl_parse_udp_start" *)
  rule rl_parse_udp_start if ((w_parse_udp_start));
    parse_done[0] <= True;
    w_parse_done.send();
    dbg3($format("%s -> %s", "parse_udp", "start"));
    fetch_next_header0(0);
  endrule

  interface frameIn = toPut(data_in_ff);
  interface meta = toGet(meta_in_ff);
  interface verbosity = toPut(cr_verbosity_ff);
endmodule

// ====== DEPARSER ======

typedef enum {
  StateDeparseStart,
  StateEthernet,
  StateVlanTag,
  StateIpv4,
  StateIpv6,
  StateTcp,
  StateUdp,
  StateIcmp
} DeparserState deriving (Bits, Eq);
interface Deparser;
  interface PipeIn#(MetadataT) metadata;
  interface PktWriteServer writeServer;
  interface PktWriteClient writeClient;
  interface Put#(int) verbosity;
  method DeparserPerfRec read_perf_info ();
endinterface
module mkDeparser  (Deparser);
  Reg#(int) cr_verbosity[2] <- mkCRegU(2);
  FIFOF#(int) cr_verbosity_ff <- mkFIFOF;
  rule set_verbosity;
    let x = cr_verbosity_ff.first;
    cr_verbosity_ff.deq;
    cr_verbosity[1] <= x;
  endrule

  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#(128)) rg_buff <- mkReg(0);
  Reg#(DeparserState) rg_deparse_state <- mkReg(StateDeparseStart);
  let din = data_in_ff.first;
  let meta = meta_in_ff.first;
  function Action report_deparse_action(DeparserState state, Bit#(32) offset);
    action
      if (cr_verbosity[0] > 0) begin
        $display("(%d) Deparse State %h offset %h", $time, state, offset);
      end
    endaction
  endfunction
  function Action succeed_and_next(Bit#(32) offset);
    action
      data_in_ff.deq;
      rg_offset <= offset;
    endaction
  endfunction
  function Action failed_and_trap(Bit#(32) offset);
    action
      data_in_ff.deq;
      rg_offset <= 0;
    endaction
  endfunction
  function DeparserState compute_next_state(DeparserState state);
    DeparserState nextState = StateDeparseStart;
    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(UInt#(max) count);
    Bit#(max) v = 1 << count - 1;
    return v;
  endfunction
  rule rl_start_state if (rg_deparse_state == StateDeparseStart);
    let v = data_in_ff.first;
    if (v.sop) begin
      rg_deparse_state <= StateEthernet;
    end
    else begin
      data_in_ff.deq;
      data_out_ff.enq(v);
    end
  endrule

  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);
        $display ("read_data %h", curr_data);
        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);
        DeparserState next_state = compute_next_state(state);
        $display ("next_state %h", next_state);
        rg_deparse_state <= next_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
  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
typedef union tagged {
  struct {
    PacketInstance pkt;
  } Ipv4PacketReqT;
  struct {
    PacketInstance pkt;
  } Ipv6PacketReqT;
  struct {
    PacketInstance pkt;
  } L2PacketReqT;
  struct {
    PacketInstance pkt;
  } MimPacketReqT;
  struct {
    PacketInstance pkt;
  } MplsPacketReqT;
  struct {
    PacketInstance pkt;
  } NopReqT;
  struct {
    PacketInstance pkt;
    Bit#(8) runtime_egress_port;
  } SetEgressPortReqT;
} BBRequest deriving (Bits, Eq, FShow);
typedef union tagged {
  struct {
    PacketInstance pkt;
    Bit#(4) ing_metadata$packet_type;
  } Ipv4PacketRspT;
  struct {
    PacketInstance pkt;
    Bit#(4) ing_metadata$packet_type;
  } Ipv6PacketRspT;
  struct {
    PacketInstance pkt;
    Bit#(4) ing_metadata$packet_type;
  } L2PacketRspT;
  struct {
    PacketInstance pkt;
    Bit#(4) ing_metadata$packet_type;
  } MimPacketRspT;
  struct {
    PacketInstance pkt;
    Bit#(4) ing_metadata$packet_type;
  } MplsPacketRspT;
  struct {
    PacketInstance pkt;
  } NopRspT;
  struct {
    PacketInstance pkt;
    Bit#(8) ing_metadata$egress_port;
  } SetEgressPortRspT;
} BBResponse deriving (Bits, Eq, FShow);

// ====== IPV4_PACKET ======

interface Ipv4Packet;
  interface Server#(BBRequest, BBResponse) prev_control_state;
endinterface
module mkIpv4Packet  (Ipv4Packet);
  RX #(BBRequest) rx_prev_control_state <- mkRX;
  TX #(BBResponse) tx_prev_control_state <- mkTX;
  let rx_info_prev_control_state = rx_prev_control_state.u;
  let tx_info_prev_control_state = tx_prev_control_state.u;
  FIFOF#(PacketInstance) curr_packet_ff <- mkFIFOF;
  Reg#(Bit#(4)) ing_metadata$packet_type <- mkReg(0);
  rule ipv4_packet_request;
    let v = rx_info_prev_control_state.first;
    rx_info_prev_control_state.deq;
    case (v) matches
      tagged Ipv4PacketReqT {pkt: .pkt}: begin
        ing_metadata$packet_type <= 'h1;
        curr_packet_ff.enq(pkt);
      end
    endcase
  endrule

  rule ipv4_packet_response;
    let pkt <- toGet(curr_packet_ff).get;
    BBResponse rsp = tagged Ipv4PacketRspT {pkt: pkt, ing_metadata$packet_type: ing_metadata$packet_type};
    tx_info_prev_control_state.enq(rsp);
  endrule

  interface prev_control_state = toServer(rx_prev_control_state.e, tx_prev_control_state.e);
endmodule

// ====== IPV6_PACKET ======

interface Ipv6Packet;
  interface Server#(BBRequest, BBResponse) prev_control_state;
endinterface
module mkIpv6Packet  (Ipv6Packet);
  RX #(BBRequest) rx_prev_control_state <- mkRX;
  TX #(BBResponse) tx_prev_control_state <- mkTX;
  let rx_info_prev_control_state = rx_prev_control_state.u;
  let tx_info_prev_control_state = tx_prev_control_state.u;
  FIFOF#(PacketInstance) curr_packet_ff <- mkFIFOF;
  Reg#(Bit#(4)) ing_metadata$packet_type <- mkReg(0);
  rule ipv6_packet_request;
    let v = rx_info_prev_control_state.first;
    rx_info_prev_control_state.deq;
    case (v) matches
      tagged Ipv6PacketReqT {pkt: .pkt}: begin
        ing_metadata$packet_type <= 'h2;
        curr_packet_ff.enq(pkt);
      end
    endcase
  endrule

  rule ipv6_packet_response;
    let pkt <- toGet(curr_packet_ff).get;
    BBResponse rsp = tagged Ipv6PacketRspT {pkt: pkt, ing_metadata$packet_type: ing_metadata$packet_type};
    tx_info_prev_control_state.enq(rsp);
  endrule

  interface prev_control_state = toServer(rx_prev_control_state.e, tx_prev_control_state.e);
endmodule

// ====== L2_PACKET ======

interface L2Packet;
  interface Server#(BBRequest, BBResponse) prev_control_state;
endinterface
module mkL2Packet  (L2Packet);
  RX #(BBRequest) rx_prev_control_state <- mkRX;
  TX #(BBResponse) tx_prev_control_state <- mkTX;
  let rx_info_prev_control_state = rx_prev_control_state.u;
  let tx_info_prev_control_state = tx_prev_control_state.u;
  FIFOF#(PacketInstance) curr_packet_ff <- mkFIFOF;
  Reg#(Bit#(4)) ing_metadata$packet_type <- mkReg(0);
  rule l2_packet_request;
    let v = rx_info_prev_control_state.first;
    rx_info_prev_control_state.deq;
    case (v) matches
      tagged L2PacketReqT {pkt: .pkt}: begin
        ing_metadata$packet_type <= 'h0;
        curr_packet_ff.enq(pkt);
      end
    endcase
  endrule

  rule l2_packet_response;
    let pkt <- toGet(curr_packet_ff).get;
    BBResponse rsp = tagged L2PacketRspT {pkt: pkt, ing_metadata$packet_type: ing_metadata$packet_type};
    tx_info_prev_control_state.enq(rsp);
  endrule

  interface prev_control_state = toServer(rx_prev_control_state.e, tx_prev_control_state.e);
endmodule

// ====== MIM_PACKET ======

interface MimPacket;
  interface Server#(BBRequest, BBResponse) prev_control_state;
endinterface
module mkMimPacket  (MimPacket);
  RX #(BBRequest) rx_prev_control_state <- mkRX;
  TX #(BBResponse) tx_prev_control_state <- mkTX;
  let rx_info_prev_control_state = rx_prev_control_state.u;
  let tx_info_prev_control_state = tx_prev_control_state.u;
  FIFOF#(PacketInstance) curr_packet_ff <- mkFIFOF;
  Reg#(Bit#(4)) ing_metadata$packet_type <- mkReg(0);
  rule mim_packet_request;
    let v = rx_info_prev_control_state.first;
    rx_info_prev_control_state.deq;
    case (v) matches
      tagged MimPacketReqT {pkt: .pkt}: begin
        ing_metadata$packet_type <= 'h4;
        curr_packet_ff.enq(pkt);
      end
    endcase
  endrule

  rule mim_packet_response;
    let pkt <- toGet(curr_packet_ff).get;
    BBResponse rsp = tagged MimPacketRspT {pkt: pkt, ing_metadata$packet_type: ing_metadata$packet_type};
    tx_info_prev_control_state.enq(rsp);
  endrule

  interface prev_control_state = toServer(rx_prev_control_state.e, tx_prev_control_state.e);
endmodule

// ====== MPLS_PACKET ======

interface MplsPacket;
  interface Server#(BBRequest, BBResponse) prev_control_state;
endinterface
module mkMplsPacket  (MplsPacket);
  RX #(BBRequest) rx_prev_control_state <- mkRX;
  TX #(BBResponse) tx_prev_control_state <- mkTX;
  let rx_info_prev_control_state = rx_prev_control_state.u;
  let tx_info_prev_control_state = tx_prev_control_state.u;
  FIFOF#(PacketInstance) curr_packet_ff <- mkFIFOF;
  Reg#(Bit#(4)) ing_metadata$packet_type <- mkReg(0);
  rule mpls_packet_request;
    let v = rx_info_prev_control_state.first;
    rx_info_prev_control_state.deq;
    case (v) matches
      tagged MplsPacketReqT {pkt: .pkt}: begin
        ing_metadata$packet_type <= 'h3;
        curr_packet_ff.enq(pkt);
      end
    endcase
  endrule

  rule mpls_packet_response;
    let pkt <- toGet(curr_packet_ff).get;
    BBResponse rsp = tagged MplsPacketRspT {pkt: pkt, ing_metadata$packet_type: ing_metadata$packet_type};
    tx_info_prev_control_state.enq(rsp);
  endrule

  interface prev_control_state = toServer(rx_prev_control_state.e, tx_prev_control_state.e);
endmodule

// ====== NOP ======

interface Nop;
  interface Server#(BBRequest, BBResponse) prev_control_state;
endinterface
module mkNop  (Nop);
  RX #(BBRequest) rx_prev_control_state <- mkRX;
  TX #(BBResponse) tx_prev_control_state <- mkTX;
  let rx_info_prev_control_state = rx_prev_control_state.u;
  let tx_info_prev_control_state = tx_prev_control_state.u;
  FIFOF#(PacketInstance) curr_packet_ff <- mkFIFOF;
  rule nop_request;
    let v = rx_info_prev_control_state.first;
    rx_info_prev_control_state.deq;
    case (v) matches
      tagged NopReqT {pkt: .pkt}: begin
        curr_packet_ff.enq(pkt);
      end
    endcase
  endrule

  rule nop_response;
    let pkt <- toGet(curr_packet_ff).get;
    BBResponse rsp = tagged NopRspT {pkt: pkt};
    tx_info_prev_control_state.enq(rsp);
  endrule

  interface prev_control_state = toServer(rx_prev_control_state.e, tx_prev_control_state.e);
endmodule

// ====== SET_EGRESS_PORT ======

interface SetEgressPort;
  interface Server#(BBRequest, BBResponse) prev_control_state;
endinterface
module mkSetEgressPort  (SetEgressPort);
  RX #(BBRequest) rx_prev_control_state <- mkRX;
  TX #(BBResponse) tx_prev_control_state <- mkTX;
  let rx_info_prev_control_state = rx_prev_control_state.u;
  let tx_info_prev_control_state = tx_prev_control_state.u;
  FIFOF#(PacketInstance) curr_packet_ff <- mkFIFOF;
  Reg#(Bit#(8)) ing_metadata$egress_port <- mkReg(0);
  rule set_egress_port_request;
    let v = rx_info_prev_control_state.first;
    rx_info_prev_control_state.deq;
    case (v) matches
      tagged SetEgressPortReqT {pkt: .pkt, runtime_egress_port: .runtime_egress_port}: begin
        ing_metadata$egress_port <= runtime_egress_port;
        curr_packet_ff.enq(pkt);
      end
    endcase
  endrule

  rule set_egress_port_response;
    let pkt <- toGet(curr_packet_ff).get;
    BBResponse rsp = tagged SetEgressPortRspT {pkt: pkt, ing_metadata$egress_port: ing_metadata$egress_port};
    tx_info_prev_control_state.enq(rsp);
  endrule

  interface prev_control_state = toServer(rx_prev_control_state.e, tx_prev_control_state.e);
endmodule

// ====== L2_MATCH ======

typedef struct {
  Bit#(6) padding;
  Bit#(48) ethernet$srcAddr;
} L2MatchReqT deriving (Bits, Eq, FShow);
typedef enum {
  DEFAULT_L2_MATCH,
  NOP,
  SET_EGRESS_PORT
} L2MatchActionT deriving (Bits, Eq, FShow);
typedef struct {
  L2MatchActionT _action;
  Bit#(8) runtime_egress_port;
} L2MatchRspT deriving (Bits, Eq, FShow);
import "BDPI" function ActionValue#(Bit#(10)) matchtable_read_l2_match(Bit#(54) msgtype);
import "BDPI" function Action matchtable_write_l2_match(Bit#(54) msgtype, Bit#(10) data);
instance MatchTableSim#(3, 54, 10);
  function ActionValue#(Bit#(10)) matchtable_read(Bit#(3) id, Bit#(54) key);
    actionvalue
      let v <- matchtable_read_l2_match(key);
      return v;
    endactionvalue
  endfunction
  function Action matchtable_write(Bit#(3) id, Bit#(54) key, Bit#(10) data);
    action
      matchtable_write_l2_match(key, data);
    endaction
  endfunction
endinstance
interface L2Match;
  interface Server #(MetadataRequest, MetadataResponse) prev_control_state_0;
  interface Client #(BBRequest, BBResponse) next_control_state_0;
  interface Client #(BBRequest, BBResponse) next_control_state_1;
endinterface
module mkL2Match  (L2Match);
  RX #(MetadataRequest) rx_metadata <- mkRX;
  let rx_info_metadata = rx_metadata.u;
  TX #(MetadataResponse) tx_metadata <- mkTX;
  let tx_info_metadata = tx_metadata.u;
  Vector#(2, FIFOF#(BBRequest)) bbReqFifo <- replicateM(printTraceM("bbreq", mkFIFOF));
  Vector#(2, FIFOF#(BBResponse)) bbRspFifo <- replicateM(printTraceM("bbrsp", mkFIFOF));
  FIFOF#(PacketInstance) packet_ff <- mkFIFOF;
  MatchTable#(3, 256, SizeOf#(L2MatchReqT), SizeOf#(L2MatchRspT)) matchTable <- mkMatchTable("l2match.dat");
  Vector#(2, Bool) readyBits = map(fifoNotEmpty, bbRspFifo);
  Bool interruptStatus = False;
  Bit#(2) readyChannel = -1;
  for (Integer i=1; i>=0; i=i-1) begin
      if (readyBits[i]) begin
          interruptStatus = True;
          readyChannel = fromInteger(i);
      end
  end

  Vector#(2, FIFOF#(MetadataT)) metadata_ff <- replicateM(mkFIFOF);
  rule rl_handle_request;
    let data = rx_info_metadata.first;
    rx_info_metadata.deq;
    let meta = data.meta;
    let pkt = data.pkt;
    let ethernet$srcAddr = fromMaybe(?, meta.ethernet$srcAddr);
    L2MatchReqT req = L2MatchReqT {padding: 0, ethernet$srcAddr: ethernet$srcAddr};
    matchTable.lookupPort.request.put(pack(req));
    packet_ff.enq(pkt);
    metadata_ff[0].enq(meta);
  endrule

  rule rl_handle_execute;
    let rsp <- matchTable.lookupPort.response.get;
    let pkt <- toGet(packet_ff).get;
    let meta <- toGet(metadata_ff[0]).get;
    if (rsp matches tagged Valid .data) begin
      L2MatchRspT resp = unpack(data);
      case (resp._action) matches
        NOP: begin
          BBRequest req = tagged NopReqT {pkt: pkt};
          bbReqFifo[0].enq(req); //FIXME: replace with RXTX.
        end
        SET_EGRESS_PORT: begin
          BBRequest req = tagged SetEgressPortReqT {pkt: pkt, runtime_egress_port: resp.runtime_egress_port};
          bbReqFifo[1].enq(req); //FIXME: replace with RXTX.
        end
      endcase
      // forward metadata to next stage.
      metadata_ff[1].enq(meta);
    end
  endrule

  rule rl_handle_response if (interruptStatus);
    let v <- toGet(bbRspFifo[readyChannel]).get;
    let meta <- toGet(metadata_ff[1]).get;
    case (v) matches
      tagged NopRspT {pkt: .pkt}: begin
        MetadataResponse rsp = tagged L2MatchNopRspT {pkt: pkt, meta: meta};
        tx_info_metadata.enq(rsp);
      end
      tagged SetEgressPortRspT {pkt: .pkt, ing_metadata$egress_port: .ing_metadata$egress_port}: begin
        meta.ing_metadata$egress_port = tagged Valid ing_metadata$egress_port;
        MetadataResponse rsp = tagged L2MatchSetEgressPortRspT {pkt: pkt, meta: meta};
        tx_info_metadata.enq(rsp);
      end
    endcase
  endrule

  interface prev_control_state_0 = toServer(rx_metadata.e, tx_metadata.e);
  interface next_control_state_0 = toClient(bbReqFifo[0], bbRspFifo[0]);
  interface next_control_state_1 = toClient(bbReqFifo[1], bbRspFifo[1]);
endmodule

// ====== IPV4_MATCH ======

typedef struct {
  Bit#(4) padding;
  Bit#(32) ipv4$srcAddr;
} Ipv4MatchReqT deriving (Bits, Eq);
typedef enum {
  DEFAULT_IPV4_MATCH,
  NOP,
  SET_EGRESS_PORT
} Ipv4MatchActionT deriving (Bits, Eq);
typedef struct {
  Ipv4MatchActionT _action;
  Bit#(8) runtime_egress_port;
} Ipv4MatchRspT deriving (Bits, Eq);
import "BDPI" function ActionValue#(Bit#(10)) matchtable_read_ipv4_match(Bit#(36) msgtype);
import "BDPI" function Action matchtable_write_ipv4_match(Bit#(36) msgtype, Bit#(10) data);
instance MatchTableSim#(1, 36, 10);
  function ActionValue#(Bit#(10)) matchtable_read(Bit#(1) id, Bit#(36) key);
    actionvalue
      let v <- matchtable_read_ipv4_match(key);
      return v;
    endactionvalue
  endfunction
  function Action matchtable_write(Bit#(1) id, Bit#(36) key, Bit#(10) data);
    action
      matchtable_write_ipv4_match(key, data);
    endaction
  endfunction
endinstance
interface Ipv4Match;
  interface Server #(MetadataRequest, MetadataResponse) prev_control_state_0;
  interface Client #(BBRequest, BBResponse) next_control_state_0;
  interface Client #(BBRequest, BBResponse) next_control_state_1;
endinterface
module mkIpv4Match  (Ipv4Match);
  RX #(MetadataRequest) rx_metadata <- mkRX;
  let rx_info_metadata = rx_metadata.u;
  TX #(MetadataResponse) tx_metadata <- mkTX;
  let tx_info_metadata = tx_metadata.u;
  Vector#(2, FIFOF#(BBRequest)) bbReqFifo <- replicateM(mkFIFOF);
  Vector#(2, FIFOF#(BBResponse)) bbRspFifo <- replicateM(mkFIFOF);
  FIFOF#(PacketInstance) packet_ff <- mkFIFOF;
  MatchTable#(1, 256, SizeOf#(Ipv4MatchReqT), SizeOf#(Ipv4MatchRspT)) matchTable <- mkMatchTable("ipv4match.dat");
  Vector#(2, Bool) readyBits = map(fifoNotEmpty, bbRspFifo);
  Bool interruptStatus = False;
  Bit#(2) readyChannel = -1;
  for (Integer i=1; i>=0; i=i-1) begin
      if (readyBits[i]) begin
          interruptStatus = True;
          readyChannel = fromInteger(i);
      end
  end

  Vector#(2, FIFOF#(MetadataT)) metadata_ff <- replicateM(mkFIFOF);
  rule rl_handle_request;
    let data = rx_info_metadata.first;
    rx_info_metadata.deq;
    let meta = data.meta;
    let pkt = data.pkt;
    let ipv4$srcAddr = fromMaybe(?, meta.ipv4$srcAddr);
    Ipv4MatchReqT req = Ipv4MatchReqT {padding: 0, ipv4$srcAddr: ipv4$srcAddr};
    matchTable.lookupPort.request.put(pack(req));
    packet_ff.enq(pkt);
    metadata_ff[0].enq(meta);
  endrule

  rule rl_handle_execute;
    let rsp <- matchTable.lookupPort.response.get;
    let pkt <- toGet(packet_ff).get;
    let meta <- toGet(metadata_ff[0]).get;
    if (rsp matches tagged Valid .data) begin
      Ipv4MatchRspT resp = unpack(data);
      case (resp._action) matches
        NOP: begin
          BBRequest req = tagged NopReqT {pkt: pkt};
          bbReqFifo[0].enq(req); //FIXME: replace with RXTX.
        end
        SET_EGRESS_PORT: begin
          BBRequest req = tagged SetEgressPortReqT {pkt: pkt, runtime_egress_port: resp.runtime_egress_port};
          bbReqFifo[1].enq(req); //FIXME: replace with RXTX.
        end
      endcase
      // forward metadata to next stage.
      metadata_ff[1].enq(meta);
    end
  endrule

  rule rl_handle_response if (interruptStatus);
    let v <- toGet(bbRspFifo[readyChannel]).get;
    let meta <- toGet(metadata_ff[1]).get;
    case (v) matches
      tagged NopRspT {pkt: .pkt}: begin
        MetadataResponse rsp = tagged Ipv4MatchNopRspT {pkt: pkt, meta: meta};
        tx_info_metadata.enq(rsp);
      end
      tagged SetEgressPortRspT {pkt: .pkt, ing_metadata$egress_port: .ing_metadata$egress_port}: begin
        meta.ing_metadata$egress_port = tagged Valid ing_metadata$egress_port;
        MetadataResponse rsp = tagged Ipv4MatchSetEgressPortRspT {pkt: pkt, meta: meta};
        tx_info_metadata.enq(rsp);
      end
    endcase
  endrule

  interface prev_control_state_0 = toServer(rx_metadata.e, tx_metadata.e);
  interface next_control_state_0 = toClient(bbReqFifo[0], bbRspFifo[0]);
  interface next_control_state_1 = toClient(bbReqFifo[1], bbRspFifo[1]);
endmodule

// ====== IPV6_MATCH ======

typedef struct {
  Bit#(7) padding;
  Bit#(128) ipv6$srcAddr;
} Ipv6MatchReqT deriving (Bits, Eq);
typedef enum {
  DEFAULT_IPV6_MATCH,
  NOP,
  SET_EGRESS_PORT
} Ipv6MatchActionT deriving (Bits, Eq);
typedef struct {
  Ipv6MatchActionT _action;
  Bit#(8) runtime_egress_port;
} Ipv6MatchRspT deriving (Bits, Eq);
import "BDPI" function ActionValue#(Bit#(10)) matchtable_read_ipv6_match(Bit#(135) msgtype);
import "BDPI" function Action matchtable_write_ipv6_match(Bit#(135) msgtype, Bit#(10) data);
instance MatchTableSim#(2, 135, 10);
  function ActionValue#(Bit#(10)) matchtable_read(Bit#(2) id, Bit#(135) key);
    actionvalue
      let v <- matchtable_read_ipv6_match(key);
      return v;
    endactionvalue
  endfunction
  function Action matchtable_write(Bit#(2) id, Bit#(135) key, Bit#(10) data);
    action
      matchtable_write_ipv6_match(key, data);
    endaction
  endfunction
endinstance
interface Ipv6Match;
  interface Server #(MetadataRequest, MetadataResponse) prev_control_state_0;
  interface Client #(BBRequest, BBResponse) next_control_state_0;
  interface Client #(BBRequest, BBResponse) next_control_state_1;
endinterface
module mkIpv6Match  (Ipv6Match);
  RX #(MetadataRequest) rx_metadata <- mkRX;
  let rx_info_metadata = rx_metadata.u;
  TX #(MetadataResponse) tx_metadata <- mkTX;
  let tx_info_metadata = tx_metadata.u;
  Vector#(2, FIFOF#(BBRequest)) bbReqFifo <- replicateM(mkFIFOF);
  Vector#(2, FIFOF#(BBResponse)) bbRspFifo <- replicateM(mkFIFOF);
  FIFOF#(PacketInstance) packet_ff <- mkFIFOF;
  MatchTable#(2, 256, SizeOf#(Ipv6MatchReqT), SizeOf#(Ipv6MatchRspT)) matchTable <- mkMatchTable("ipv6match.dat");
  Vector#(2, Bool) readyBits = map(fifoNotEmpty, bbRspFifo);
  Bool interruptStatus = False;
  Bit#(2) readyChannel = -1;
  for (Integer i=1; i>=0; i=i-1) begin
      if (readyBits[i]) begin
          interruptStatus = True;
          readyChannel = fromInteger(i);
      end
  end

  Vector#(2, FIFOF#(MetadataT)) metadata_ff <- replicateM(mkFIFOF);
  rule rl_handle_request;
    let data = rx_info_metadata.first;
    rx_info_metadata.deq;
    let meta = data.meta;
    let pkt = data.pkt;
    let ipv6$srcAddr = fromMaybe(?, meta.ipv6$srcAddr);
    Ipv6MatchReqT req = Ipv6MatchReqT {padding: 0, ipv6$srcAddr: ipv6$srcAddr};
    matchTable.lookupPort.request.put(pack(req));
    packet_ff.enq(pkt);
    metadata_ff[0].enq(meta);
  endrule

  rule rl_handle_execute;
    let rsp <- matchTable.lookupPort.response.get;
    let pkt <- toGet(packet_ff).get;
    let meta <- toGet(metadata_ff[0]).get;
    if (rsp matches tagged Valid .data) begin
      Ipv6MatchRspT resp = unpack(data);
      case (resp._action) matches
        NOP: begin
          BBRequest req = tagged NopReqT {pkt: pkt};
          bbReqFifo[0].enq(req); //FIXME: replace with RXTX.
        end
        SET_EGRESS_PORT: begin
          BBRequest req = tagged SetEgressPortReqT {pkt: pkt, runtime_egress_port: resp.runtime_egress_port};
          bbReqFifo[1].enq(req); //FIXME: replace with RXTX.
        end
      endcase
      // forward metadata to next stage.
      metadata_ff[1].enq(meta);
    end
  endrule

  rule rl_handle_response if (interruptStatus);
    let v <- toGet(bbRspFifo[readyChannel]).get;
    let meta <- toGet(metadata_ff[1]).get;
    case (v) matches
      tagged NopRspT {pkt: .pkt}: begin
        MetadataResponse rsp = tagged Ipv6MatchNopRspT {pkt: pkt, meta: meta};
        tx_info_metadata.enq(rsp);
      end
      tagged SetEgressPortRspT {pkt: .pkt, ing_metadata$egress_port: .ing_metadata$egress_port}: begin
        meta.ing_metadata$egress_port = tagged Valid ing_metadata$egress_port;
        MetadataResponse rsp = tagged Ipv6MatchSetEgressPortRspT {pkt: pkt, meta: meta};
        tx_info_metadata.enq(rsp);
      end
    endcase
  endrule

  interface prev_control_state_0 = toServer(rx_metadata.e, tx_metadata.e);
  interface next_control_state_0 = toClient(bbReqFifo[0], bbRspFifo[0]);
  interface next_control_state_1 = toClient(bbReqFifo[1], bbRspFifo[1]);
endmodule

// ====== ETHERTYPE_MATCH ======

typedef struct {
  Bit#(2) padding;
  Bit#(16) ethernet$etherType;
} EthertypeMatchReqT deriving (Bits, Eq);
typedef enum {
  DEFAULT_ETHERTYPE_MATCH,
  L2_PACKET,
  IPV4_PACKET,
  IPV6_PACKET,
  MPLS_PACKET,
  MIM_PACKET
} EthertypeMatchActionT deriving (Bits, Eq);
typedef struct {
  EthertypeMatchActionT _action;
} EthertypeMatchRspT deriving (Bits, Eq);
import "BDPI" function ActionValue#(Bit#(3)) matchtable_read_ethertype_match(Bit#(18) msgtype);
import "BDPI" function Action matchtable_write_ethertype_match(Bit#(18) msgtype, Bit#(3) data);
instance MatchTableSim#(0, 18, 3);
  function ActionValue#(Bit#(3)) matchtable_read(Bit#(0) id, Bit#(18) key);
    actionvalue
      let v <- matchtable_read_ethertype_match(key);
      return v;
    endactionvalue
  endfunction
  function Action matchtable_write(Bit#(0) id, Bit#(18) key, Bit#(3) data);
    action
      matchtable_write_ethertype_match(key, data);
    endaction
  endfunction
endinstance
interface EthertypeMatch;
  interface Server #(MetadataRequest, MetadataResponse) prev_control_state_0;
  interface Client #(BBRequest, BBResponse) next_control_state_0;
  interface Client #(BBRequest, BBResponse) next_control_state_1;
  interface Client #(BBRequest, BBResponse) next_control_state_2;
  interface Client #(BBRequest, BBResponse) next_control_state_3;
  interface Client #(BBRequest, BBResponse) next_control_state_4;
endinterface
module mkEthertypeMatch  (EthertypeMatch);
  RX #(MetadataRequest) rx_metadata <- mkRX;
  let rx_info_metadata = rx_metadata.u;
  TX #(MetadataResponse) tx_metadata <- mkTX;
  let tx_info_metadata = tx_metadata.u;
  Vector#(5, FIFOF#(BBRequest)) bbReqFifo <- replicateM(mkFIFOF);
  Vector#(5, FIFOF#(BBResponse)) bbRspFifo <- replicateM(mkFIFOF);
  FIFOF#(PacketInstance) packet_ff <- mkFIFOF;
  MatchTable#(0, 256, SizeOf#(EthertypeMatchReqT), SizeOf#(EthertypeMatchRspT)) matchTable <- mkMatchTable("ethermatch.dat");
  Vector#(5, Bool) readyBits = map(fifoNotEmpty, bbRspFifo);
  Bool interruptStatus = False;
  Bit#(5) readyChannel = -1;
  for (Integer i=4; i>=0; i=i-1) begin
      if (readyBits[i]) begin
          interruptStatus = True;
          readyChannel = fromInteger(i);
      end
  end

  Vector#(2, FIFOF#(MetadataT)) metadata_ff <- replicateM(mkFIFOF);
  rule rl_handle_request;
    let data = rx_info_metadata.first;
    rx_info_metadata.deq;
    let meta = data.meta;
    let pkt = data.pkt;
    let ethernet$etherType = fromMaybe(?, meta.ethernet$etherType);
    EthertypeMatchReqT req = EthertypeMatchReqT {padding: 0, ethernet$etherType: ethernet$etherType};
    matchTable.lookupPort.request.put(pack(req));
    packet_ff.enq(pkt);
    metadata_ff[0].enq(meta);
  endrule

  rule rl_handle_execute;
    let rsp <- matchTable.lookupPort.response.get;
    let pkt <- toGet(packet_ff).get;
    let meta <- toGet(metadata_ff[0]).get;
    if (rsp matches tagged Valid .data) begin
      EthertypeMatchRspT resp = unpack(data);
      case (resp._action) matches
        L2_PACKET: begin
          BBRequest req = tagged L2PacketReqT {pkt: pkt};
          bbReqFifo[0].enq(req); //FIXME: replace with RXTX.
        end
        IPV4_PACKET: begin
          BBRequest req = tagged Ipv4PacketReqT {pkt: pkt};
          bbReqFifo[1].enq(req); //FIXME: replace with RXTX.
        end
        IPV6_PACKET: begin
          BBRequest req = tagged Ipv6PacketReqT {pkt: pkt};
          bbReqFifo[2].enq(req); //FIXME: replace with RXTX.
        end
        MPLS_PACKET: begin
          BBRequest req = tagged MplsPacketReqT {pkt: pkt};
          bbReqFifo[3].enq(req); //FIXME: replace with RXTX.
        end
        MIM_PACKET: begin
          BBRequest req = tagged MimPacketReqT {pkt: pkt};
          bbReqFifo[4].enq(req); //FIXME: replace with RXTX.
        end
      endcase
      // forward metadata to next stage.
      metadata_ff[1].enq(meta);
    end
  endrule

  rule rl_handle_response if (interruptStatus);
    let v <- toGet(bbRspFifo[readyChannel]).get;
    let meta <- toGet(metadata_ff[1]).get;
    case (v) matches
      tagged L2PacketRspT {pkt: .pkt, ing_metadata$packet_type: .ing_metadata$packet_type}: begin
        meta.ing_metadata$packet_type = tagged Valid ing_metadata$packet_type;
        MetadataResponse rsp = tagged EthertypeMatchL2PacketRspT {pkt: pkt, meta: meta};
        tx_info_metadata.enq(rsp);
      end
      tagged Ipv4PacketRspT {pkt: .pkt, ing_metadata$packet_type: .ing_metadata$packet_type}: begin
        meta.ing_metadata$packet_type = tagged Valid ing_metadata$packet_type;
        MetadataResponse rsp = tagged EthertypeMatchIpv4PacketRspT {pkt: pkt, meta: meta};
        tx_info_metadata.enq(rsp);
      end
      tagged Ipv6PacketRspT {pkt: .pkt, ing_metadata$packet_type: .ing_metadata$packet_type}: begin
        meta.ing_metadata$packet_type = tagged Valid ing_metadata$packet_type;
        MetadataResponse rsp = tagged EthertypeMatchIpv6PacketRspT {pkt: pkt, meta: meta};
        tx_info_metadata.enq(rsp);
      end
      tagged MplsPacketRspT {pkt: .pkt, ing_metadata$packet_type: .ing_metadata$packet_type}: begin
        meta.ing_metadata$packet_type = tagged Valid ing_metadata$packet_type;
        MetadataResponse rsp = tagged EthertypeMatchMplsPacketRspT {pkt: pkt, meta: meta};
        tx_info_metadata.enq(rsp);
      end
      tagged MimPacketRspT {pkt: .pkt, ing_metadata$packet_type: .ing_metadata$packet_type}: begin
        meta.ing_metadata$packet_type = tagged Valid ing_metadata$packet_type;
        MetadataResponse rsp = tagged EthertypeMatchMimPacketRspT {pkt: pkt, meta: meta};
        tx_info_metadata.enq(rsp);
      end
    endcase
  endrule

  interface prev_control_state_0 = toServer(rx_metadata.e, tx_metadata.e);
  interface next_control_state_0 = toClient(bbReqFifo[0], bbRspFifo[0]);
  interface next_control_state_1 = toClient(bbReqFifo[1], bbRspFifo[1]);
  interface next_control_state_2 = toClient(bbReqFifo[2], bbRspFifo[2]);
  interface next_control_state_3 = toClient(bbReqFifo[3], bbRspFifo[3]);
  interface next_control_state_4 = toClient(bbReqFifo[4], bbRspFifo[4]);
endmodule

// ====== INGRESS ======

interface Ingress;
  interface Client#(MetadataRequest, MetadataResponse) next;
endinterface
module mkIngress #(Vector#(numClients, Client#(MetadataRequest, MetadataResponse)) mdc) (Ingress);
  FIFOF#(MetadataRequest) default_req_ff <- mkFIFOF;
  FIFOF#(MetadataResponse) default_rsp_ff <- mkFIFOF;
  FIFOF#(MetadataRequest) ethertype_match_req_ff <- mkFIFOF;
  FIFOF#(MetadataResponse) ethertype_match_rsp_ff <- mkFIFOF;
  FIFOF#(MetadataRequest) ipv4_match_req_ff <- mkFIFOF;
  FIFOF#(MetadataResponse) ipv4_match_rsp_ff <- mkFIFOF;
  FIFOF#(MetadataRequest) ipv6_match_req_ff <- mkFIFOF;
  FIFOF#(MetadataResponse) ipv6_match_rsp_ff <- mkFIFOF;
  FIFOF#(MetadataRequest) l2_match_req_ff <- mkFIFOF;
  FIFOF#(MetadataResponse) l2_match_rsp_ff <- mkFIFOF;
  FIFOF#(MetadataRequest) next_req_ff <- mkFIFOF;
  FIFOF#(MetadataResponse) next_rsp_ff <- mkFIFOF;
  Vector#(numClients, Server#(MetadataRequest, MetadataResponse)) mds = replicate(toServer(default_req_ff, default_rsp_ff));
  mkConnection(mds, mdc);
  EthertypeMatch ethertype_match <- mkEthertypeMatch();
  Ipv4Match ipv4_match <- mkIpv4Match();
  Ipv6Match ipv6_match <- mkIpv6Match();
  L2Match l2_match <- mkL2Match();
  mkConnection(toClient(ethertype_match_req_ff, ethertype_match_rsp_ff), ethertype_match.prev_control_state_0);
  mkConnection(toClient(ipv4_match_req_ff, ipv4_match_rsp_ff), ipv4_match.prev_control_state_0);
  mkConnection(toClient(ipv6_match_req_ff, ipv6_match_rsp_ff), ipv6_match.prev_control_state_0);
  mkConnection(toClient(l2_match_req_ff, l2_match_rsp_ff), l2_match.prev_control_state_0);
  // Basic Blocks
  L2Packet l2_packet_0 <- mkL2Packet();
  Ipv4Packet ipv4_packet_0 <- mkIpv4Packet();
  Ipv6Packet ipv6_packet_0 <- mkIpv6Packet();
  MplsPacket mpls_packet_0 <- mkMplsPacket();
  MimPacket mim_packet_0 <- mkMimPacket();
  Nop nop_0 <- mkNop();
  SetEgressPort set_egress_port_0 <- mkSetEgressPort();
  Nop nop_1 <- mkNop();
  SetEgressPort set_egress_port_1 <- mkSetEgressPort();
  Nop nop_2 <- mkNop();
  SetEgressPort set_egress_port_2 <- mkSetEgressPort();
  mkChan(mkFIFOF, mkFIFOF, ethertype_match.next_control_state_0, l2_packet_0.prev_control_state);
  mkChan(mkFIFOF, mkFIFOF, ethertype_match.next_control_state_1, ipv4_packet_0.prev_control_state);
  mkChan(mkFIFOF, mkFIFOF, ethertype_match.next_control_state_2, ipv6_packet_0.prev_control_state);
  mkChan(mkFIFOF, mkFIFOF, ethertype_match.next_control_state_3, mpls_packet_0.prev_control_state);
  mkChan(mkFIFOF, mkFIFOF, ethertype_match.next_control_state_4, mim_packet_0.prev_control_state);
  mkChan(mkFIFOF, mkFIFOF, ipv4_match.next_control_state_0, nop_0.prev_control_state);
  mkChan(mkFIFOF, mkFIFOF, ipv4_match.next_control_state_1, set_egress_port_0.prev_control_state);
  mkChan(mkFIFOF, mkFIFOF, ipv6_match.next_control_state_0, nop_1.prev_control_state);
  mkChan(mkFIFOF, mkFIFOF, ipv6_match.next_control_state_1, set_egress_port_1.prev_control_state);
  mkChan(mkFIFOF, mkFIFOF, l2_match.next_control_state_0, nop_2.prev_control_state);
  mkChan(mkFIFOF, mkFIFOF, l2_match.next_control_state_1, set_egress_port_2.prev_control_state);
  rule default_next_state if (default_req_ff.notEmpty);
    default_req_ff.deq;
    let _req = default_req_ff.first;
    let meta = _req.meta;
    let pkt = _req.pkt;
    MetadataRequest req = MetadataRequest {pkt: pkt, meta: meta};
    ethertype_match_req_ff.enq(req);
  endrule

  rule ethertype_match_next_state if (ethertype_match_rsp_ff.notEmpty);
    ethertype_match_rsp_ff.deq;
    let _rsp = ethertype_match_rsp_ff.first;
    case (_rsp) matches
      tagged EthertypeMatchL2PacketRspT {meta: .meta, pkt: .pkt}: begin
        MetadataRequest req = MetadataRequest {pkt: pkt, meta: meta};
        l2_match_req_ff.enq(req);
      end
      tagged EthertypeMatchIpv4PacketRspT {meta: .meta, pkt: .pkt}: begin
        MetadataRequest req = MetadataRequest {pkt: pkt, meta: meta};
        ipv4_match_req_ff.enq(req);
      end
      tagged EthertypeMatchIpv6PacketRspT {meta: .meta, pkt: .pkt}: begin
        MetadataRequest req = MetadataRequest {pkt: pkt, meta: meta};
        ipv6_match_req_ff.enq(req);
      end
      tagged EthertypeMatchMplsPacketRspT {meta: .meta, pkt: .pkt}: begin
        MetadataRequest req = MetadataRequest {pkt: pkt, meta: meta};
        ipv6_match_req_ff.enq(req);
      end
      tagged EthertypeMatchMimPacketRspT {meta: .meta, pkt: .pkt}: begin
        MetadataRequest req = MetadataRequest {pkt: pkt, meta: meta};
        l2_match_req_ff.enq(req);
      end
    endcase
  endrule

  rule ipv4_match_next_state if (ipv4_match_rsp_ff.notEmpty);
    ipv4_match_rsp_ff.deq;
    let _rsp = ipv4_match_rsp_ff.first;
    case (_rsp) matches
      tagged Ipv4MatchNopRspT {meta: .meta, pkt: .pkt}: begin
        MetadataRequest req = MetadataRequest {pkt: pkt, meta: meta};
        next_req_ff.enq(req);
      end
      tagged Ipv4MatchSetEgressPortRspT {meta: .meta, pkt: .pkt}: begin
        MetadataRequest req = MetadataRequest {pkt: pkt, meta: meta};
        next_req_ff.enq(req);
      end
    endcase
  endrule

  rule ipv6_match_next_state if (ipv6_match_rsp_ff.notEmpty);
    ipv6_match_rsp_ff.deq;
    let _rsp = ipv6_match_rsp_ff.first;
    case (_rsp) matches
      tagged Ipv6MatchNopRspT {meta: .meta, pkt: .pkt}: begin
        MetadataRequest req = MetadataRequest {pkt: pkt, meta: meta};
        next_req_ff.enq(req);
      end
      tagged Ipv6MatchSetEgressPortRspT {meta: .meta, pkt: .pkt}: begin
        MetadataRequest req = MetadataRequest {pkt: pkt, meta: meta};
        next_req_ff.enq(req);
      end
    endcase
  endrule

  rule l2_match_next_state if (l2_match_rsp_ff.notEmpty);
    l2_match_rsp_ff.deq;
    let _rsp = l2_match_rsp_ff.first;
    case (_rsp) matches
      tagged L2MatchNopRspT {meta: .meta, pkt: .pkt}: begin
        MetadataRequest req = MetadataRequest {pkt: pkt, meta: meta};
        next_req_ff.enq(req);
      end
      tagged L2MatchSetEgressPortRspT {meta: .meta, pkt: .pkt}: begin
        MetadataRequest req = MetadataRequest {pkt: pkt, meta: meta};
        next_req_ff.enq(req);
      end
    endcase
  endrule

  interface next = (interface Client#(MetadataRequest, MetadataResponse);
    interface request = toGet(next_req_ff);
    interface response = toPut(next_rsp_ff);
  endinterface);
endmodule

// ====== EGRESS ======

interface Egress;
  interface Client#(MetadataRequest, MetadataResponse) next;
endinterface
module mkEgress #(Vector#(numClients, Client#(MetadataRequest, MetadataResponse)) mdc) (Egress);
  FIFOF#(MetadataRequest) default_req_ff <- mkFIFOF;
  FIFOF#(MetadataResponse) default_rsp_ff <- mkFIFOF;
  FIFOF#(MetadataRequest) next_req_ff <- mkFIFOF;
  FIFOF#(MetadataResponse) next_rsp_ff <- mkFIFOF;
  Vector#(numClients, Server#(MetadataRequest, MetadataResponse)) mds = replicate(toServer(default_req_ff, default_rsp_ff));
  mkConnection(mds, mdc);
  // Basic Blocks
  rule default_next_state if (default_req_ff.notEmpty);
    default_req_ff.deq;
    let _req = default_req_ff.first;
    let meta = _req.meta;
    let pkt = _req.pkt;
    MetadataRequest req = MetadataRequest {pkt: pkt, meta: meta};
    next_req_ff.enq(req);
    $display("Egress out", fshow(req));
  endrule

  interface next = (interface Client#(MetadataRequest, MetadataResponse);
    interface request = toGet(next_req_ff);
    interface response = toPut(next_rsp_ff);
  endinterface);
endmodule
// Copyright (c) 2016 P4FPGA Project

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

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

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

error: pathspec 'examples/multiproto/sample_output/MultiProtocol.bsv' did not match any file(s) known to git


add ddr3controller with axibits

add ddr3controller with axibits

// Copyright (c) 2015 Connectal Project

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

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

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

import Clocks          ::*;
import GetPut          ::*;
import ClientServer    ::*;
import AxiDdr3Wrapper  ::*;
import AxiBits         ::*;
import Axi4MasterSlave ::*;
import ConnectalClocks ::*;
`include "ConnectalProjectConfig.bsv"

typedef 30 Ddr3AddrWidth;
typedef 512 Ddr3DataWidth;

interface Ddr3Pins;
   interface AxiDdr3Ddr3 ddr3;
   interface Clock sysclk_deleteme_unused_clock;
   interface Reset sysrst_deleteme_unused_reset;
endinterface

interface Ddr3;
   interface Axi4SlaveBits#(Ddr3AddrWidth, Ddr3DataWidth, 6, Empty) axiBits;
   interface Ddr3Pins ddr3; // pins
   interface Clock uiClock;
   interface Reset uiReset;
endinterface

function Axi4SlaveBits#(Ddr3AddrWidth,Ddr3DataWidth,6,Empty) toAxiSlaveBits(AxiDdr3S_axi s_axi);
   return (interface Axi4SlaveBits;
      method araddr = s_axi.araddr;
      method arburst = s_axi.arburst;
      method arcache = s_axi.arcache;
      method Bit#(1) aresetn(); return 1; endmethod
      method arid = s_axi.arid;
      method arlen = s_axi.arlen;
      method Action arlock(Bit#(2) l); s_axi.arlock(truncate(l)); endmethod //unused
      method arprot = s_axi.arprot;
      method arqos = s_axi.arqos;
      method arready = s_axi.arready;
      method arsize = s_axi.arsize;
      method arvalid = s_axi.arvalid;
      method awaddr = s_axi.awaddr;
      method awburst = s_axi.awburst;
      method awcache = s_axi.awcache;
      method awid = s_axi.awid;
      method awlen = s_axi.awlen;
      method Action awlock(Bit#(2) l); s_axi.awlock(truncate(l)); endmethod //unused
      method awprot = s_axi.awprot;
      method awqos = s_axi.awqos;
      method awready = s_axi.awready;
      method awsize = s_axi.awsize;
      method awvalid = s_axi.awvalid;
      method bid = s_axi.bid;
      method bready = s_axi.bready;
      method bresp = s_axi.bresp;
      method bvalid = s_axi.bvalid;
      method rdata = s_axi.rdata;
      method rlast = s_axi.rlast;
      method rready = s_axi.rready;
      method rresp = s_axi.rresp;
      method rvalid = s_axi.rvalid;
      method wdata = s_axi.wdata;
      method Action wid(Bit#(6) tag); /* no wid method */ endmethod
      method wlast = s_axi.wlast;
      method wready = s_axi.wready;
      method wstrb = s_axi.wstrb;
      method wvalid = s_axi.wvalid;
      method rid = s_axi.rid;
      interface Empty extra; endinterface
      endinterface);
endfunction

(* synthesize *)
module mkDdr3#(Clock clk200)(Ddr3);
   let clock <- exposeCurrentClock();
   let reset <- exposeCurrentReset();

   Reset rst200 <- mkSyncReset( 10, reset, clk200 );

`ifndef BSV_POSITIVE_RESET
   let mcReset = rst200;
`else
   // fixme later
`endif

   //fixme mc.aresetn

   let aresetn        <- mkB2R(clocked_by clk200, reset_by mcReset);
   AxiDdr3     mc <- mkAxiDdr3(clk200, mcReset, aresetn.r);
   let ui_reset_n <- mkResetInverter(mc.ui_clk_sync_rst, clocked_by mc.ui_clk);
   let ui_reset_b <- mkR2B(ui_reset_n);
   rule rl_aresetn;
         aresetn.inputreset(ui_reset_b.o);
   endrule
   let axibits = toAxiSlaveBits(mc.s_axi);

   rule misc_pins;
      mc.app.ref_req(0);
      mc.app.sr_req(0);
      mc.app.zq_req(0);
   endrule

   interface axiBits = axibits;
   interface Ddr3Pins ddr3;
      interface AxiDdr3Ddr3 ddr3 = mc.ddr3;
      interface Clock sysclk_deleteme_unused_clock = clock; //fixme
      interface Reset sysrst_deleteme_unused_reset = reset; //fixme
   endinterface
   interface Clock uiClock = mc.ui_clk;
   interface Reset uiReset = ui_reset_n;
endmodule

export Ddr3AddrWidth;
export Ddr3DataWidth;
export Ddr3Pins(..);
export Ddr3(..);
export AxiDdr3Ddr3(..);
export mkDdr3;

error: pathspec 'hw/bsv/Ddr3Controller.bsv' did not match any file(s) known to git


Initial SFIFO implementation

Initial SFIFO implementation

package SFIFO;

import Ehr::*;
import List::*;

// If you are running into a problem because MAX_SFIFO_SIZE is too small, you
// can increase it here, or you can define it
`ifndef MAX_SFIFO_SIZE
`define MAX_SFIFO_SIZE 16
`endif

interface SFIFO#(type dataType, type searchType);
    method Action enq(dataType x);
    method Action deq;
    method dataType first;
    method Action clear;
    method Bool search(searchType x);
endinterface

// search < {enq , deq} < clear
// first < deq
module mkSFIFO#(Integer size, function Bool isMatch(searchType s, dataType d))(SFIFO#(dataType, searchType)) provisos (Bits#(dataType, dataSize));
    // use valid bits to make search logic smaller
    List#(Reg#(Maybe#(dataType))) data <- List::replicateM(size, mkRegU);
    Reg#(Bit#(TLog#(`MAX_SFIFO_SIZE))) enqP <- mkReg(0);
    Reg#(Bit#(TLog#(`MAX_SFIFO_SIZE))) deqP <- mkReg(0);
    Reg#(Bool) full <- mkReg(False);
    Reg#(Bool) empty <- mkReg(True);
    // EHRs to avoid conflicts between enq and deq
    Ehr#(3, Bool) deqReq <- mkEhr(False);
    Ehr#(3, Maybe#(dataType)) enqReq <- mkEhr(tagged Invalid);

    // Canonicalize rule to handle enq and deq.
    // These attributes are statically checked by the compiler.
    (* fire_when_enabled *)         // WILL_FIRE == CAN_FIRE
    (* no_implicit_conditions *)    // CAN_FIRE == guard (True)
    rule canonicalize;
        Bool enqueued = False;
        let nextEnqP = enqP;
        Bool dequeued = False;
        let nextDeqP = deqP;

        // enqueue logic
        if (enqReq[2] matches tagged Valid .enqVal) begin
            enqueued = True;
            nextEnqP = (enqP == fromInteger(size - 1)) ? 0 : enqP + 1;
            // perform state updates
            data[enqP] <= tagged Valid enqVal;
            enqP <= nextEnqP;
        end

        // dequeue logic
        if (deqReq[2] == True) begin
            dequeued = True;
            nextDeqP = (deqP == fromInteger(size - 1)) ? 0 : deqP + 1;
            // perform state updates
            deqP <= nextDeqP;
            data[deqP] <= tagged Invalid;
        end

        // update empty and full if an element was enqueued or dequeued
        if (enqueued || dequeued) begin
            full <= (nextEnqP == nextDeqP) ? enqueued : False;
            empty <= (nextEnqP == nextDeqP) ? dequeued : False;
            enqP <= nextEnqP;
            deqP <= nextDeqP;
        end

        // clear request EHRs
        enqReq[2] <= tagged Invalid;
        deqReq[2] <= False;
    endrule

    method Action enq(dataType x) if (!full && !isValid(enqReq[0]));
        enqReq[0] <= tagged Valid x;
    endmethod
    method Action deq if (!empty && !deqReq[0]);
        deqReq[0] <= True;
    endmethod
    method dataType first if (!empty && !deqReq[0]);
        return fromMaybe(?, data[deqP]);
    endmethod
    method Action clear;
        for (Integer i = 0 ; i < size ; i = i+1) begin
            data[i] <= tagged Invalid;
        end
        enqP <= 0;
        deqP <= 0;
        full <= False;
        empty <= True;
        // clear any pending enq or deq
        enqReq[1] <= tagged Invalid;
        deqReq[1] <= False;
    endmethod

    // different search implementations
    // search < {enq, deq}
    method Bool search(searchType x) if (!isValid(enqReq[0]) && !deqReq[0]);
        // helper function for isMatch when dataType has valid bits
        function Bool maybeIsMatch(searchType s, Maybe#(dataType) md);
            return md matches tagged Valid. d ? isMatch(s, d) : False;
        endfunction
        return any(id, map(compose(maybeIsMatch(x), readReg), data));
    endmethod

    // // Alternate search implementation with the scheulde:
    // //   deq < search < enq
    // method Bool search(searchType x) if (!isValid(enqReq[0]));
    //     // compute dataPostDeq by considering deqReq[1]
    //     List#(Maybe#(dataType)) dataPostDeq = map(readReg, data);
    //     if (deqReq[1]) begin
    //         dataPostDeq[deqP] = tagged Invalid;
    //     end
    //     // helper function for isMatch when dataType has valid bits
    //     function Bool maybeIsMatch(searchType s, Maybe#(dataType) md);
    //         return md matches tagged Valid. d ? isMatch(s, d) : False;
    //     endfunction
    //     return any(map(maybeIsMatch(x), dataPostDeq));
    // endmethod
endmodule

endpackage

error: pathspec 'bsv-lib/src/bsv/SFIFO.bsv' did not match any file(s) known to git


Murali's EHR implementation

Murali's EHR implementation

// Copyright (C) 2012 Muralidaran Vijayaraghavan <vmurali@csail.mit.edu>

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

/*
Comments: This EHR design generates the following scheduling constraints (forall i):
forall j >= i, r[i] < w[j]
forall j < i, r[i] > w[j]
forall j > i, w[i] < w[j]
w[i] conflicts with w[i]
forall j, r[i] is conflict free with r[j]
*/

import Vector::*;
import RWire::*;

typedef  Vector#(n, Reg#(t)) Ehr#(numeric type n, type t);

module mkEhr#(t init)(Ehr#(n, t)) provisos(Bits#(t, tSz));
  Vector#(n, RWire#(t)) lat <- replicateM(mkUnsafeRWire);

  Vector#(n, Vector#(n, RWire#(Maybe#(t)))) dummy <- replicateM(replicateM(mkUnsafeRWire));
  Vector#(n, Reg#(Bool)) dummy2 <- replicateM(mkReg(True));

  Reg#(t) rl <- mkReg(init);

  Ehr#(n, t) r = newVector;

  rule canon;
    t upd = rl;
    for(Integer i = 0; i < valueOf(n); i = i + 1)
      if(lat[i].wget matches tagged Valid .x)
        upd = x;
    rl <= upd;
  endrule

  for(Integer i = 0; i < valueOf(n); i = i + 1)
    r[i] = (interface Reg;
              method Action _write(t x);
                lat[i].wset(x);
                dummy2[i] <= True;
                for(Integer j = 0; j < i; j = j + 1)
                  dummy[i][j].wset(lat[j].wget);
              endmethod

              method t _read;
                t upd = rl;
                Bool yes = True;
                for(Integer j = i; j < valueOf(n); j = j + 1)
                  yes = yes && dummy2[j];
                for(Integer j = 0; j < i; j = j + 1)
                begin
                  if(lat[j].wget matches tagged Valid .x)
                    upd = x;
                end
                return yes? upd : ?;
              endmethod
            endinterface);

   return r;
endmodule

error: pathspec 'bsv/EHRM.bsv' did not match any file(s) known to git


new idea for a stack implementation

new idea for a stack implementation

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

/*
 * Implementation of:
 *    simple stack for a type
 *
 * Single cycle push and pop, provided that consecutive pops aren't
 * too far apart
 */

import BRAM::*;

interface StackReg#(numeric type stackSize, type pctype, type argstype, type varstype);
   method Action doreturn();
   method Action docall(pctype jumpto, pctype returnto, argtype args);
   interface Reg#(argstype) args;
   interface Reg#(varstype) vars;
endinterface

module mkStackReg#(int stackSize, pctype initialpc)(StackReg#(stackSize, pctype, argstype, varstype))
   provisos(Log#(stackSize, addressBits),
      Literal#(pctype),
      Literal#(argstype),
      Literal#(varstype),
      Bits#(pctype, a__),
      Bits#(argstype, b__),
      Bits#(varstype, c__));

   BRAM1Port#(Bit#(addressBits), pctype) pcstack  <- mkBRAM1Server(defaultValue);
   BRAM1Port#(Bit#(addressBits), argstype) argsstack  <- mkBRAM1Server(defaultValue);
   BRAM1Port#(Bit#(addressBits), varstype) varsstack  <- mkBRAM1Server(defaultValue);
   Reg#(pctype) pctop <- mkReg(initialpc);
   Reg#(pctype) pcnext <- mkReg(?);
   Reg#(argstype) argstop <- mkReg(?);
   Reg#(argstype) argsnext <- mkReg(?);
   Reg#(varstype) varstop <- mkReg(?);
   Reg#(varstype) varsnext <- mkReg(?);
   Reg#(Bit#(addressBits)) fp <- mkReg(0);

   rule poppc;
     let v = ?;
      v <- pcstack.portA.response.get();
      pcnext <= v;
   endrule

   rule popargs;
     let v = ?;
      v <- argsstack.portA.response.get();
      argsnext <= v;
   endrule

   rule popvars;
     let v = ?;
      v <- varsstack.portA.response.get();
      varsnext <= v;
   endrule

   method Action docall(pctype jumpto, pctype returnto, argtype args);
      fp <= min(fp+1, maxBound);
      pcstack.portA.request.put(BRAMRequest{write: True,
	 responseOnWrite: False,
	 address: fp, datain: pcnext});
      argsstack.portA.request.put(BRAMRequest{write: True,
	 responseOnWrite: False,
	 address: fp, datain: argsnext});
      varsstack.portA.request.put(BRAMRequest{write: True,
	 responseOnWrite: False,
	 address: fp, datain: varsnext});
      pcnext <= returnto;
      pctop <= jumpto;
      argsnext <= argstop;
      varsnext <= varstop;
   endmethod

   method Action doreturn();
      fp <= max(fp-1, 0);
      pcstack.portA.request.put(BRAMRequest{write: False,
	 responseOnWrite: False,
	 address: fp-1, datain: 0});
      argsstack.portA.request.put(BRAMRequest{write: False,
	 responseOnWrite: False,
	 address: fp-1, datain: 0});
      varsstack.portA.request.put(BRAMRequest{write: False,
	 responseOnWrite: False,
	 address: fp-1, datain: 0});
      pctop <= pcnext;
      argstop <= argsnext;
      varstop <= varsnext;
   endmethod

interface args = argstop;
interface vars = varstop;

endmodule

error: pathspec 'examples/fib/StackReg.bsv' did not match any file(s) known to git


Create module to wire up the incoming ADC DDR data Follow example of IserdesDatadeser.bsv plus Jamey advice

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

(* always_enabled *)
interface FMComms1ADCPins;
   method Action io_adc_p(Bit#(14) v);
   method Action io_adc_n(Bit#(14) v);
   method Action io_adc_dco_p(Bit#(1) v);
   method Action io_adc_dco_n(Bit#(1) v);
   method Action io_adc_or_p(Bit#(1) v);
   method Action io_adc_or_n(Bit#(1) v);
endinterface

interface FMComms1ADCData;
   method Bit#(14) in_data();
   method Bit#(1) in_or();
endinterface

interface FMComms1ADC;
   interface FMComms1ADCPins pins;
   interface FMComms1ADCData adc;
endinterface

module mkFMComms1ADC(FMComms1ADC);

   Vector#(14, Wire#(Bit#(1))) adc_data_p <- replicateM(mkDWire(0));
   Vector#(14, Wire#(Bit#(1))) adc_data_n <- replicateM(mkDWire(0));

   Wire#(Bit#(1)) adc_or_p <- mkDWire(0);
   Wire#(Bit#(1)) adc_or_n <- mkDWire(0);
   Wire#(Bit#(1)) adc_dco_p <- mkDWire(0);
   Wire#(Bit#(1)) adc_dco_p <- mkDWire(0);

   Vector#(14, Wire#(Bit#(1))) adc_data_p <- replicateM(mkDWire(0));
   ReadOnly#(bit#(14)) adc_data;   /* data */
   ReadOnly#(bit#(1)) adc_or;      /* overrange */
   Clock adc_dco;     /* DDR clock */

   adc_dco <- mkClockIBUFGDS(adc_dco_p, adc_dco_n);

   for (Integer i = 0; i < 14; i = i + 1)
      adc_data[i] <- mkIBUFDS(adc_data_p[i], adc_data_n[i], clocked_by adc_dco);
   adc_or <- mkIBUFDS(adc_or_p, adc_or_n, clocked_by adc_dco);

   IDDRParams#(Bit#(14)) iddrparams_data = defaultValue;
   iddrparams_data.ddr_clk_edge = "SAME_EDGE_PIPELINED";
   IDDR#(Bit#(14)) adc_sdr_data <= mkIDDR(iddrparams_data, clocked_by adc_dco);

   IDDRParams#(Bit#(11)) iddrparams_or = defaultValue;
   iddrparams_or.ddr_clk_edge = "SAME_EDGE_PIPELINED";
   IDDR#(Bit#(1)) adc_sdr_or <= mkIDDR(iddrparams_or, clocked_by adc_dco);

   rule sendup_adc_data;
      adc_sdr_data.d(adc_data);
   endrule

   rule sendup_adc_data;
      adc_sdr_or.d(adc_or);
   endrule

   interface FMComms1ADCPins;

      method Action io_adc_data_p(Bit#(14) v);
	 for (Integer i = 0; i < 14; i = i + 1)
	    adc_data_p[i] = v[i];
      endmethod

      method Action io_adc_data_n(Bit#(14) v);
	 for (Integer i = 0; i < 14; i = i + 1)
	    adc_data_n[i] = v[i];
      endmethod

      method Action io_adc_dco_p(Bit#(1));
	 adc_dco_p <= v;
      endmethod

      method Action io_adc_dco_n(Bit#(1));
	 adc_dco_n <= v;
      endmethod

      method Action io_adc_or_p(Bit#(1));
	 adc_or_p <= v;
      endmethod

      method Action io_adc_or_n(Bit#(1));
	 adc_or_n <= v;
      endmethod

   endinterface;

endmodule

error: pathspec 'examples/fmcomms1/FMComms1ADC.bsv' did not match any file(s) known to git