Move msgtype field to the top of paxos header

import ClientServer::*;
import Connectable::*;
import Ethernet::*;
import FIFO::*;
import FIFOF::*;
import GetPut::*;
import MatchTable::*;
import Pipe::*;
import RegFile::*;
import Vector::*;
import DefaultValue::*;
import ConnectalTypes::*;
import Utils::*;

typedef union tagged {
   struct {
      PacketInstance pkt;
   } PacketMemRequest;

   struct {
      PacketInstance pkt;
      MetadataT meta;
   } DstMacLookupRequest;

   struct {
      PacketInstance pkt;
      MetadataT meta;
   } RoleLookupRequest;

   struct {
      PacketInstance pkt;
      MetadataT meta;
   } RoundTblRequest;

   struct {
      PacketInstance pkt;
      MetadataT meta;
   } SequenceTblRequest;

   struct {
      PacketInstance pkt;
      MetadataT meta;
   } AcceptorTblRequest;

   struct {
      PacketInstance pkt;
      MetadataT meta;
   } ForwardQueueRequest;

   struct {
      PacketInstance pkt;
      MetadataT meta;
   } DefaultRequest;
} MetadataRequest deriving (Bits, Eq, FShow);

typedef union tagged {
   struct {
      PacketInstance pkt;
      MetadataT meta;
   } DstMacResponse;

   struct {
      PacketInstance pkt;
      MetadataT meta;
   } RoleResponse;

   struct {
      PacketInstance pkt;
      MetadataT meta;
   } RoundTblResponse;

   struct {
      PacketInstance pkt;
      MetadataT meta;
   } SequenceTblResponse;

   struct {
      PacketInstance pkt;
      MetadataT meta;
   } AcceptorTblResponse;
} MetadataResponse deriving (Bits, Eq, FShow);

typedef union tagged {
   struct {
      PacketInstance pkt;
      Bit#(9) port;
   } BBForwardRequest;
   struct {
      PacketInstance pkt;
   } BBIncreaseInstanceRequest;
   struct {
      PacketInstance pkt;
      Bit#(InstanceSize) inst;
      Bit#(RoundSize) rnd;
   } BBHandle1aRequest;
   struct {
      PacketInstance pkt;
      Bit#(InstanceSize) inst;
      Bit#(RoundSize) rnd;
      Bit#(ValueSize) paxosval;
   } BBHandle2aRequest;
   struct {
      PacketInstance pkt;
   } BBDropRequest;
   struct {
      PacketInstance pkt;
      Bit#(InstanceSize) paxos$inst;
   } BBRoundRequest;
   struct {
      PacketInstance pkt;
   } BBRoleRequest;
} BBRequest deriving (Bits, Eq, FShow);

typedef union tagged {
   struct {
      PacketInstance pkt;
      Bit#(9) egress;
   } BBForwardResponse;
   struct {
      PacketInstance pkt;
      Bit#(InstanceSize) inst;
   } BBIncreaseInstanceResponse;
   struct {
      PacketInstance pkt;
      Bit#(DatapathSize) datapath;
      Bit#(RoundSize) vround;
      Bit#(ValueSize) value;
   } BBHandle1aResponse;
   struct {
      PacketInstance pkt;
      Bit#(DatapathSize) datapath;
   } BBHandle2aResponse;
   struct {
      PacketInstance pkt;
   } BBDropResponse;
   struct {
      PacketInstance pkt;
      IngressMetadataT ingress_metadata;
   } BBRoundResponse;
   struct {
      PacketInstance pkt;
      Role role;
   } BBRoleResponse;
} BBResponse deriving (Bits, Eq, FShow);

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

instance FShow#(Ipv6T);
    function Fmt fshow(Ipv6T p);
        return $format("Ipv6T: version=%h, trafficClass=%h, flowLabel=%h, payloadLen=%h, nextHdr=%h, hopLimit=%h, srcAddr=%h, dstAddr=%h" , p.version, p.trafficClass, p.flowLabel, p.payloadLen, p.nextHdr, p.hopLimit, p.srcAddr, p.dstAddr);
    endfunction
endinstance

function Ipv6T extract_ipv6(Bit#(320) data);
    Vector#(320, Bit#(1)) dataVec=unpack(data);
    Vector#(4, Bit#(1)) version = takeAt(0, dataVec);
    Vector#(8, Bit#(1)) trafficClass = takeAt(4, dataVec);
    Vector#(20, Bit#(1)) flowLabel = takeAt(12, dataVec);
    Vector#(16, Bit#(1)) payloadLen = takeAt(32, dataVec);
    Vector#(8, Bit#(1)) nextHdr = takeAt(48, dataVec);
    Vector#(8, Bit#(1)) hopLimit = takeAt(56, dataVec);
    Vector#(128, Bit#(1)) srcAddr = takeAt(64, dataVec);
    Vector#(128, Bit#(1)) dstAddr = takeAt(192, dataVec);
    Ipv6T ipv6_t = defaultValue;
    ipv6_t.version = pack(version);
    ipv6_t.trafficClass = pack(trafficClass);
    ipv6_t.flowLabel = pack(flowLabel);
    ipv6_t.payloadLen = pack(payloadLen);
    ipv6_t.nextHdr = pack(nextHdr);
    ipv6_t.hopLimit = pack(hopLimit);
    ipv6_t.srcAddr = pack(srcAddr);
    ipv6_t.dstAddr = pack(dstAddr);
    return ipv6_t;
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

instance FShow#(UdpT);
    function Fmt fshow(UdpT p);
        return $format("UdpT: srcPort=%h, dstPort=%h, length_=%h, checksum=%h" , p.srcPort, p.dstPort, p.length_, p.checksum);
    endfunction
endinstance

function UdpT extract_udp(Bit#(64) data);
    Vector#(64, Bit#(1)) dataVec=unpack(data);
    Vector#(16, Bit#(1)) srcPort = takeAt(0, dataVec);
    Vector#(16, Bit#(1)) dstPort = takeAt(16, dataVec);
    Vector#(16, Bit#(1)) length_ = takeAt(32, dataVec);
    Vector#(16, Bit#(1)) checksum = takeAt(48, dataVec);
    UdpT udp_t = defaultValue;
    udp_t.srcPort = pack(srcPort);
    udp_t.dstPort = pack(dstPort);
    udp_t.length_ = pack(length_);
    udp_t.checksum = pack(checksum);
    return udp_t;
endfunction

typedef struct {
    Bit#(16) msgtype;
    Bit#(32) inst;
    Bit#(16) rnd;
    Bit#(16) vrnd;
    Bit#(16) acptid;
    Bit#(256) paxosval;
} PaxosT deriving (Bits, Eq);

instance DefaultValue#(PaxosT);
defaultValue = unpack(0);
endinstance
instance DefaultMask#(PaxosT);
defaultMask = unpack(maxBound);
endinstance

instance FShow#(PaxosT);
    function Fmt fshow(PaxosT p);
        return $format("PaxosT: msgtype=%h, inst=%h, rnd=%h, vrnd=%h, acptid=%h, paxosval=%h" , p.msgtype, p.inst, p.rnd, p.vrnd, p.acptid, p.paxosval);
    endfunction
endinstance

function PaxosT extract_paxos(Bit#(352) data);
    Vector#(352, Bit#(1)) dataVec=unpack(data);
    Vector#(16, Bit#(1)) msgtype = takeAt(0, dataVec);
    Vector#(32, Bit#(1)) inst = takeAt(16, dataVec);
    Vector#(16, Bit#(1)) rnd = takeAt(48, dataVec);
    Vector#(16, Bit#(1)) vrnd = takeAt(64, dataVec);
    Vector#(16, Bit#(1)) acptid = takeAt(80, dataVec);
    Vector#(256, Bit#(1)) paxosval = takeAt(96, dataVec);
    PaxosT paxos_t = defaultValue;
    paxos_t.msgtype = pack(msgtype);
    paxos_t.inst = pack(inst);
    paxos_t.rnd = pack(rnd);
    paxos_t.vrnd = pack(vrnd);
    paxos_t.acptid = pack(acptid);
    paxos_t.paxosval = pack(paxosval);
    return paxos_t;
endfunction

typedef struct {
    Bit#(16) hrd;
    Bit#(16) pro;
    Bit#(8) hln;
    Bit#(8) pln;
    Bit#(16) op;
    Bit#(48) sha;
    Bit#(32) spa;
    Bit#(48) tha;
    Bit#(32) tpa;
} ArpT deriving (Bits, Eq);

instance DefaultValue#(ArpT);
defaultValue = unpack(0);
endinstance
instance DefaultMask#(ArpT);
defaultMask = unpack(maxBound);
endinstance

instance FShow#(ArpT);
    function Fmt fshow(ArpT p);
        return $format("ArpT: hrd=%h, pro=%h, hln=%h, pln=%h, op=%h, sha=%h, spa=%h, tha=%h, tpa=%h" , p.hrd, p.pro, p.hln, p.pln, p.op, p.sha, p.spa, p.tha, p.tpa);
    endfunction
endinstance

function ArpT extract_arp(Bit#(224) data);
    Vector#(224, Bit#(1)) dataVec=unpack(data);
    Vector#(16, Bit#(1)) hrd = takeAt(0, dataVec);
    Vector#(16, Bit#(1)) pro = takeAt(16, dataVec);
    Vector#(8, Bit#(1)) hln = takeAt(32, dataVec);
    Vector#(8, Bit#(1)) pln = takeAt(40, dataVec);
    Vector#(16, Bit#(1)) op = takeAt(48, dataVec);
    Vector#(48, Bit#(1)) sha = takeAt(64, dataVec);
    Vector#(32, Bit#(1)) spa = takeAt(112, dataVec);
    Vector#(48, Bit#(1)) tha = takeAt(144, dataVec);
    Vector#(32, Bit#(1)) tpa = takeAt(192, dataVec);
    ArpT arp_t = defaultValue;
    arp_t.hrd = pack(hrd);
    arp_t.pro = pack(pro);
    arp_t.hln = pack(hln);
    arp_t.pln = pack(pln);
    arp_t.op = pack(op);
    arp_t.sha = pack(sha);
    arp_t.spa = pack(spa);
    arp_t.tha = pack(tha);
    arp_t.tpa = pack(tpa);
    return arp_t;
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

instance FShow#(Ipv4T);
    function Fmt fshow(Ipv4T p);
        return $format("Ipv4T: version=%h, ihl=%h, diffserv=%h, totalLen=%h, identification=%h, flags=%h, fragOffset=%h, ttl=%h, protocol=%h, hdrChecksum=%h, srcAddr=%h, dstAddr=%h" , p.version, p.ihl, p.diffserv, p.totalLen, p.identification, p.flags, p.fragOffset, p.ttl, p.protocol, p.hdrChecksum, p.srcAddr, p.dstAddr);
    endfunction
endinstance

function Ipv4T extract_ipv4(Bit#(160) data);
    Vector#(160, Bit#(1)) dataVec=unpack(data);
    Vector#(4, Bit#(1)) version = takeAt(0, dataVec);
    Vector#(4, Bit#(1)) ihl = takeAt(4, dataVec);
    Vector#(8, Bit#(1)) diffserv = takeAt(8, dataVec);
    Vector#(16, Bit#(1)) totalLen = takeAt(16, dataVec);
    Vector#(16, Bit#(1)) identification = takeAt(32, dataVec);
    Vector#(3, Bit#(1)) flags = takeAt(48, dataVec);
    Vector#(13, Bit#(1)) fragOffset = takeAt(51, dataVec);
    Vector#(8, Bit#(1)) ttl = takeAt(64, dataVec);
    Vector#(8, Bit#(1)) protocol = takeAt(72, dataVec);
    Vector#(16, Bit#(1)) hdrChecksum = takeAt(80, dataVec);
    Vector#(32, Bit#(1)) srcAddr = takeAt(96, dataVec);
    Vector#(32, Bit#(1)) dstAddr = takeAt(128, dataVec);
    Ipv4T ipv4_t = defaultValue;
    ipv4_t.version = pack(version);
    ipv4_t.ihl = pack(ihl);
    ipv4_t.diffserv = pack(diffserv);
    ipv4_t.totalLen = pack(totalLen);
    ipv4_t.identification = pack(identification);
    ipv4_t.flags = pack(flags);
    ipv4_t.fragOffset = pack(fragOffset);
    ipv4_t.ttl = pack(ttl);
    ipv4_t.protocol = pack(protocol);
    ipv4_t.hdrChecksum = pack(hdrChecksum);
    ipv4_t.srcAddr = pack(srcAddr);
    ipv4_t.dstAddr = pack(dstAddr);
    return ipv4_t;
endfunction

typedef struct {
    Bit#(RoundSize) round;
} IngressMetadataT deriving (Bits, Eq);

instance DefaultValue#(IngressMetadataT);
defaultValue = unpack(0);
endinstance
instance DefaultMask#(IngressMetadataT);
defaultMask = unpack(maxBound);
endinstance

instance FShow#(IngressMetadataT);
    function Fmt fshow(IngressMetadataT p);
        return $format("IngressMetadataT: round=%h" , p.round);
    endfunction
endinstance

function IngressMetadataT extract_ingress_metadata(Bit#(16) data);
    Vector#(16, Bit#(1)) dataVec=unpack(data);
    Vector#(16, Bit#(1)) round = takeAt(0, dataVec);
    IngressMetadataT ingress_metadata_t = defaultValue;
    ingress_metadata_t.round = pack(round);
    return ingress_metadata_t;
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

instance FShow#(EthernetT);
    function Fmt fshow(EthernetT p);
        return $format("EthernetT: dstAddr=%h, srcAddr=%h, etherType=%h" , p.dstAddr, p.srcAddr, p.etherType);
    endfunction
endinstance

function EthernetT extract_ethernet(Bit#(112) data);
    Vector#(112, Bit#(1)) dataVec=unpack(data);
    Vector#(48, Bit#(1)) dstAddr = takeAt(0, dataVec);
    Vector#(48, Bit#(1)) srcAddr = takeAt(48, dataVec);
    Vector#(16, Bit#(1)) etherType = takeAt(96, dataVec);
    EthernetT ethernet_t = defaultValue;
    ethernet_t.dstAddr = pack(dstAddr);
    ethernet_t.srcAddr = pack(srcAddr);
    ethernet_t.etherType = pack(etherType);
    return ethernet_t;
endfunction

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

instance FShow#(StandardMetadataT);
    function Fmt fshow(StandardMetadataT p);
        return $format("StandardMetadataT: ingress_port=%h, packet_length=%h, egress_spec=%h, egress_port=%h, egress_instance=%h, instance_type=%h, clone_spec=%h, _padding=%h" , p.ingress_port, p.packet_length, p.egress_spec, p.egress_port, p.egress_instance, p.instance_type, p.clone_spec, p._padding);
    endfunction
endinstance

function StandardMetadataT extract_standard_metadata(Bit#(160) data);
    Vector#(160, Bit#(1)) dataVec=unpack(data);
    Vector#(9, Bit#(1)) ingress_port = takeAt(0, dataVec);
    Vector#(32, Bit#(1)) packet_length = takeAt(9, dataVec);
    Vector#(9, Bit#(1)) egress_spec = takeAt(41, dataVec);
    Vector#(9, Bit#(1)) egress_port = takeAt(50, dataVec);
    Vector#(32, Bit#(1)) egress_instance = takeAt(59, dataVec);
    Vector#(32, Bit#(1)) instance_type = takeAt(91, dataVec);
    Vector#(32, Bit#(1)) clone_spec = takeAt(123, dataVec);
    Vector#(5, Bit#(1)) _padding = takeAt(155, dataVec);
    StandardMetadataT standard_metadata_t = defaultValue;
    standard_metadata_t.ingress_port = pack(ingress_port);
    standard_metadata_t.packet_length = pack(packet_length);
    standard_metadata_t.egress_spec = pack(egress_spec);
    standard_metadata_t.egress_port = pack(egress_port);
    standard_metadata_t.egress_instance = pack(egress_instance);
    standard_metadata_t.instance_type = pack(instance_type);
    standard_metadata_t.clone_spec = pack(clone_spec);
    standard_metadata_t._padding = pack(_padding);
    return standard_metadata_t;
endfunction

typedef struct {
    Bit#(8) role;
} SwitchMetadataT deriving (Bits, Eq);

instance DefaultValue#(SwitchMetadataT);
defaultValue = unpack(0);
endinstance
instance DefaultMask#(SwitchMetadataT);
defaultMask = unpack(maxBound);
endinstance

instance FShow#(SwitchMetadataT);
    function Fmt fshow(SwitchMetadataT p);
        return $format("SwitchMetadataT: role=%h" , p.role);
    endfunction
endinstance

function SwitchMetadataT extract_switch_metadata(Bit#(8) data);
    Vector#(8, Bit#(1)) dataVec=unpack(data);
    Vector#(8, Bit#(1)) role = takeAt(0, dataVec);
    SwitchMetadataT switch_metadata_t = defaultValue;
    switch_metadata_t.role = pack(role);
    return switch_metadata_t;
endfunction

typedef struct {
   Maybe#(Bit#(16)) msgtype; // ethernet$msgtype
   Maybe#(Bit#(48)) dstAddr; // ethernet$dstAddr
   Maybe#(Bit#(16)) etherType; // ethernet$etherType
   Maybe#(Bit#(8))  protocol; // ipv4$protocol
   Maybe#(Bit#(16)) dstPort; // ipv4$dstPort
   Maybe#(Bit#(InstanceSize)) paxos$inst; // paxos$inst
   Maybe#(Bit#(RoundSize)) paxos$rnd;
   Maybe#(Bit#(RoundSize)) paxos$vrnd;
   Maybe#(Bit#(256)) paxos$paxosval;
   Maybe#(Bit#(16)) paxos$acptid;
   Maybe#(Bit#(16)) paxos$msgtype;
   Maybe#(Bit#(RoundSize)) paxos_packet_meta$round;
   Maybe#(Role) switch_metadata$role;
   Maybe#(Bool) valid_ethernet;
   Maybe#(Bool) valid_arp;
   Maybe#(Bool) valid_ipv4;
   Maybe#(Bool) valid_ipv6;
   Maybe#(Bool) valid_udp;
   Maybe#(Bool) valid_paxos;
} MetadataT deriving (Bits, Eq);

instance DefaultValue#(MetadataT);
defaultValue =
MetadataT {
   msgtype: tagged Invalid,
   dstAddr: tagged Invalid,
   etherType: tagged Invalid,
   protocol: tagged Invalid,
   dstPort: tagged Invalid,
   paxos$inst: tagged Invalid,
   paxos$rnd: tagged Invalid,
   paxos$vrnd: tagged Invalid,
   paxos$paxosval: tagged Invalid,
   paxos$acptid: tagged Invalid,
   paxos$msgtype: tagged Invalid,
   paxos_packet_meta$round: tagged Invalid,
   switch_metadata$role: tagged Invalid,
   valid_ethernet: tagged Invalid,
   valid_arp: tagged Invalid,
   valid_ipv4: tagged Invalid,
   valid_ipv6: tagged Invalid,
   valid_udp: tagged Invalid,
   valid_paxos: tagged Invalid
};
endinstance

instance FShow#(MetadataT);
   function Fmt fshow(MetadataT p);
      return $format("msgtype=", fshow(p.msgtype), ",")+
             $format("dstAddr=", fshow(p.dstAddr), ",")+
             $format("etherType=", fshow(p.etherType), ",")+
             $format("protocol=", fshow(p.protocol), ",")+
             $format("dstPort=", fshow(p.dstPort), ",")+
             $format("role=", fshow(p.switch_metadata$role), ",")+
             $format("round=", fshow(p.paxos_packet_meta$round), ",")+
             $format("paxos$inst=", fshow(p.paxos$inst), ",")+
             $format("paxos$rnd=", fshow(p.paxos$rnd), ",")+
             $format("paxos$vrnd=", fshow(p.paxos$vrnd), ",")+
             $format("paxos$val=", fshow(p.paxos$paxosval), ",")+
             $format("paxos$acpt=", fshow(p.paxos$acptid), ",")+
             $format("paxos$msgtype=", fshow(p.paxos$msgtype));
   endfunction
endinstance

typedef Client#(MetadataRequest, MetadataResponse) MetadataClient;
typedef Server#(MetadataRequest, MetadataResponse) MetadataServer;

typedef Client#(BBRequest, BBResponse) BBClient;
typedef Server#(BBRequest, BBResponse) BBServer;

/* generate tables */
typedef struct {
    Bit#(6) padding;
    Bit#(48) dstAddr;
} DmacTblReqT deriving (Bits, Eq, FShow);

//typedef union tagged {
//    struct {
//        Bit#(9) port;
//    } Forward;
//
//    struct {
//        Bit#(4) group;
//    } Broadcast;
//} DmacTblRespT deriving (Bits, Eq, FShow);

typedef struct {
   Bit#(9) port;
} DmacTblParamT deriving (Bits, Eq, FShow);

typedef struct {
   DmacTblActionT act;
   DmacTblParamT param;
} DmacTblRespT deriving (Bits, Eq, FShow);

typedef struct {
    Bit#(2) padding;
    Bit#(16) msgtype;
} SequenceTblReqT deriving (Bits, Eq, FShow);

typedef struct {
   SequenceTblActionT act;
} SequenceTblRespT deriving (Bits, Eq, FShow);

typedef struct {
    Bit#(2) padding;
    Bit#(16) msgtype;
} AcceptorTblReqT deriving (Bits, Eq, FShow);

typedef struct {
   AcceptorTblActionT act;
} AcceptorTblRespT deriving (Bits, Eq, FShow);

(* synthesize *)
module mkMatchTable_256_dmacTable(MatchTable#(256, SizeOf#(DmacTblReqT), SizeOf#(DmacTblRespT)));
   MatchTable#(256, SizeOf#(DmacTblReqT), SizeOf#(DmacTblRespT)) ifc <- mkMatchTable();
   return ifc;
endmodule

(* synthesize *)
module mkMatchTable_256_acceptorTable(MatchTable#(256, SizeOf#(AcceptorTblReqT), SizeOf#(AcceptorTblRespT)));
   MatchTable#(256, SizeOf#(AcceptorTblReqT), SizeOf#(AcceptorTblRespT)) ifc <- mkMatchTable();
   return ifc;
endmodule

(* synthesize *)
module mkMatchTable_256_sequenceTable(MatchTable#(256, SizeOf#(SequenceTblReqT), SizeOf#(SequenceTblRespT)));
   MatchTable#(256, SizeOf#(SequenceTblReqT), SizeOf#(SequenceTblRespT)) ifc <- mkMatchTable();
   return ifc;
endmodule

import ClientServer::*;
import Connectable::*;
import Ethernet::*;
import FIFO::*;
import FIFOF::*;
import GetPut::*;
import MatchTable::*;
import Pipe::*;
import RegFile::*;
import Vector::*;
import DefaultValue::*;
import ConnectalTypes::*;
import Utils::*;

typedef union tagged {
   struct {
      PacketInstance pkt;
   } PacketMemRequest;

   struct {
      PacketInstance pkt;
      MetadataT meta;
   } DstMacLookupRequest;

   struct {
      PacketInstance pkt;
      MetadataT meta;
   } RoleLookupRequest;

   struct {
      PacketInstance pkt;
      MetadataT meta;
   } RoundTblRequest;

   struct {
      PacketInstance pkt;
      MetadataT meta;
   } SequenceTblRequest;

   struct {
      PacketInstance pkt;
      MetadataT meta;
   } AcceptorTblRequest;

   struct {
      PacketInstance pkt;
      MetadataT meta;
   } ForwardQueueRequest;

   struct {
      PacketInstance pkt;
      MetadataT meta;
   } DefaultRequest;
} MetadataRequest deriving (Bits, Eq, FShow);

typedef union tagged {
   struct {
      PacketInstance pkt;
      MetadataT meta;
   } DstMacResponse;

   struct {
      PacketInstance pkt;
      MetadataT meta;
   } RoleResponse;

   struct {
      PacketInstance pkt;
      MetadataT meta;
   } RoundTblResponse;

   struct {
      PacketInstance pkt;
      MetadataT meta;
   } SequenceTblResponse;

   struct {
      PacketInstance pkt;
      MetadataT meta;
   } AcceptorTblResponse;
} MetadataResponse deriving (Bits, Eq, FShow);

typedef union tagged {
   struct {
      PacketInstance pkt;
      Bit#(9) port;
   } BBForwardRequest;
   struct {
      PacketInstance pkt;
   } BBIncreaseInstanceRequest;
   struct {
      PacketInstance pkt;
      Bit#(InstanceSize) inst;
      Bit#(RoundSize) rnd;
   } BBHandle1aRequest;
   struct {
      PacketInstance pkt;
      Bit#(InstanceSize) inst;
      Bit#(RoundSize) rnd;
      Bit#(ValueSize) paxosval;
   } BBHandle2aRequest;
   struct {
      PacketInstance pkt;
   } BBDropRequest;
   struct {
      PacketInstance pkt;
      Bit#(InstanceSize) paxos$inst;
   } BBRoundRequest;
   struct {
      PacketInstance pkt;
   } BBRoleRequest;
} BBRequest deriving (Bits, Eq, FShow);

typedef union tagged {
   struct {
      PacketInstance pkt;
      Bit#(9) egress;
   } BBForwardResponse;
   struct {
      PacketInstance pkt;
      Bit#(InstanceSize) inst;
   } BBIncreaseInstanceResponse;
   struct {
      PacketInstance pkt;
      Bit#(DatapathSize) datapath;
      Bit#(RoundSize) vround;
      Bit#(ValueSize) value;
   } BBHandle1aResponse;
   struct {
      PacketInstance pkt;
      Bit#(DatapathSize) datapath;
   } BBHandle2aResponse;
   struct {
      PacketInstance pkt;
   } BBDropResponse;
   struct {
      PacketInstance pkt;
      IngressMetadataT ingress_metadata;
   } BBRoundResponse;
   struct {
      PacketInstance pkt;
      Role role;
   } BBRoleResponse;
} BBResponse deriving (Bits, Eq, FShow);

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

instance FShow#(Ipv6T);
    function Fmt fshow(Ipv6T p);
        return $format("Ipv6T: version=%h, trafficClass=%h, flowLabel=%h, payloadLen=%h, nextHdr=%h, hopLimit=%h, srcAddr=%h, dstAddr=%h" , p.version, p.trafficClass, p.flowLabel, p.payloadLen, p.nextHdr, p.hopLimit, p.srcAddr, p.dstAddr);
    endfunction
endinstance

function Ipv6T extract_ipv6(Bit#(320) data);
    Vector#(320, Bit#(1)) dataVec=unpack(data);
    Vector#(4, Bit#(1)) version = takeAt(0, dataVec);
    Vector#(8, Bit#(1)) trafficClass = takeAt(4, dataVec);
    Vector#(20, Bit#(1)) flowLabel = takeAt(12, dataVec);
    Vector#(16, Bit#(1)) payloadLen = takeAt(32, dataVec);
    Vector#(8, Bit#(1)) nextHdr = takeAt(48, dataVec);
    Vector#(8, Bit#(1)) hopLimit = takeAt(56, dataVec);
    Vector#(128, Bit#(1)) srcAddr = takeAt(64, dataVec);
    Vector#(128, Bit#(1)) dstAddr = takeAt(192, dataVec);
    Ipv6T ipv6_t = defaultValue;
    ipv6_t.version = pack(version);
    ipv6_t.trafficClass = pack(trafficClass);
    ipv6_t.flowLabel = pack(flowLabel);
    ipv6_t.payloadLen = pack(payloadLen);
    ipv6_t.nextHdr = pack(nextHdr);
    ipv6_t.hopLimit = pack(hopLimit);
    ipv6_t.srcAddr = pack(srcAddr);
    ipv6_t.dstAddr = pack(dstAddr);
    return ipv6_t;
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

instance FShow#(UdpT);
    function Fmt fshow(UdpT p);
        return $format("UdpT: srcPort=%h, dstPort=%h, length_=%h, checksum=%h" , p.srcPort, p.dstPort, p.length_, p.checksum);
    endfunction
endinstance

function UdpT extract_udp(Bit#(64) data);
    Vector#(64, Bit#(1)) dataVec=unpack(data);
    Vector#(16, Bit#(1)) srcPort = takeAt(0, dataVec);
    Vector#(16, Bit#(1)) dstPort = takeAt(16, dataVec);
    Vector#(16, Bit#(1)) length_ = takeAt(32, dataVec);
    Vector#(16, Bit#(1)) checksum = takeAt(48, dataVec);
    UdpT udp_t = defaultValue;
    udp_t.srcPort = pack(srcPort);
    udp_t.dstPort = pack(dstPort);
    udp_t.length_ = pack(length_);
    udp_t.checksum = pack(checksum);
    return udp_t;
endfunction

typedef struct {
    Bit#(32) inst;
    Bit#(16) rnd;
    Bit#(16) vrnd;
    Bit#(16) acptid;
    Bit#(16) msgtype;
    Bit#(256) paxosval;
} PaxosT deriving (Bits, Eq);

instance DefaultValue#(PaxosT);
defaultValue = unpack(0);
endinstance
instance DefaultMask#(PaxosT);
defaultMask = unpack(maxBound);
endinstance

instance FShow#(PaxosT);
    function Fmt fshow(PaxosT p);
        return $format("PaxosT: inst=%h, rnd=%h, vrnd=%h, acptid=%h, msgtype=%h, paxosval=%h" , p.inst, p.rnd, p.vrnd, p.acptid, p.msgtype, p.paxosval);
    endfunction
endinstance

function PaxosT extract_paxos(Bit#(352) data);
    Vector#(352, Bit#(1)) dataVec=unpack(data);
    Vector#(32, Bit#(1)) inst = takeAt(0, dataVec);
    Vector#(16, Bit#(1)) rnd = takeAt(32, dataVec);
    Vector#(16, Bit#(1)) vrnd = takeAt(48, dataVec);
    Vector#(16, Bit#(1)) acptid = takeAt(64, dataVec);
    Vector#(16, Bit#(1)) msgtype = takeAt(80, dataVec);
    Vector#(256, Bit#(1)) paxosval = takeAt(96, dataVec);
    PaxosT paxos_t = defaultValue;
    paxos_t.inst = pack(inst);
    paxos_t.rnd = pack(rnd);
    paxos_t.vrnd = pack(vrnd);
    paxos_t.acptid = pack(acptid);
    paxos_t.msgtype = pack(msgtype);
    paxos_t.paxosval = pack(paxosval);
    return paxos_t;
endfunction

typedef struct {
    Bit#(16) hrd;
    Bit#(16) pro;
    Bit#(8) hln;
    Bit#(8) pln;
    Bit#(16) op;
    Bit#(48) sha;
    Bit#(32) spa;
    Bit#(48) tha;
    Bit#(32) tpa;
} ArpT deriving (Bits, Eq);

instance DefaultValue#(ArpT);
defaultValue = unpack(0);
endinstance
instance DefaultMask#(ArpT);
defaultMask = unpack(maxBound);
endinstance

instance FShow#(ArpT);
    function Fmt fshow(ArpT p);
        return $format("ArpT: hrd=%h, pro=%h, hln=%h, pln=%h, op=%h, sha=%h, spa=%h, tha=%h, tpa=%h" , p.hrd, p.pro, p.hln, p.pln, p.op, p.sha, p.spa, p.tha, p.tpa);
    endfunction
endinstance

function ArpT extract_arp(Bit#(224) data);
    Vector#(224, Bit#(1)) dataVec=unpack(data);
    Vector#(16, Bit#(1)) hrd = takeAt(0, dataVec);
    Vector#(16, Bit#(1)) pro = takeAt(16, dataVec);
    Vector#(8, Bit#(1)) hln = takeAt(32, dataVec);
    Vector#(8, Bit#(1)) pln = takeAt(40, dataVec);
    Vector#(16, Bit#(1)) op = takeAt(48, dataVec);
    Vector#(48, Bit#(1)) sha = takeAt(64, dataVec);
    Vector#(32, Bit#(1)) spa = takeAt(112, dataVec);
    Vector#(48, Bit#(1)) tha = takeAt(144, dataVec);
    Vector#(32, Bit#(1)) tpa = takeAt(192, dataVec);
    ArpT arp_t = defaultValue;
    arp_t.hrd = pack(hrd);
    arp_t.pro = pack(pro);
    arp_t.hln = pack(hln);
    arp_t.pln = pack(pln);
    arp_t.op = pack(op);
    arp_t.sha = pack(sha);
    arp_t.spa = pack(spa);
    arp_t.tha = pack(tha);
    arp_t.tpa = pack(tpa);
    return arp_t;
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

instance FShow#(Ipv4T);
    function Fmt fshow(Ipv4T p);
        return $format("Ipv4T: version=%h, ihl=%h, diffserv=%h, totalLen=%h, identification=%h, flags=%h, fragOffset=%h, ttl=%h, protocol=%h, hdrChecksum=%h, srcAddr=%h, dstAddr=%h" , p.version, p.ihl, p.diffserv, p.totalLen, p.identification, p.flags, p.fragOffset, p.ttl, p.protocol, p.hdrChecksum, p.srcAddr, p.dstAddr);
    endfunction
endinstance

function Ipv4T extract_ipv4(Bit#(160) data);
    Vector#(160, Bit#(1)) dataVec=unpack(data);
    Vector#(4, Bit#(1)) version = takeAt(0, dataVec);
    Vector#(4, Bit#(1)) ihl = takeAt(4, dataVec);
    Vector#(8, Bit#(1)) diffserv = takeAt(8, dataVec);
    Vector#(16, Bit#(1)) totalLen = takeAt(16, dataVec);
    Vector#(16, Bit#(1)) identification = takeAt(32, dataVec);
    Vector#(3, Bit#(1)) flags = takeAt(48, dataVec);
    Vector#(13, Bit#(1)) fragOffset = takeAt(51, dataVec);
    Vector#(8, Bit#(1)) ttl = takeAt(64, dataVec);
    Vector#(8, Bit#(1)) protocol = takeAt(72, dataVec);
    Vector#(16, Bit#(1)) hdrChecksum = takeAt(80, dataVec);
    Vector#(32, Bit#(1)) srcAddr = takeAt(96, dataVec);
    Vector#(32, Bit#(1)) dstAddr = takeAt(128, dataVec);
    Ipv4T ipv4_t = defaultValue;
    ipv4_t.version = pack(version);
    ipv4_t.ihl = pack(ihl);
    ipv4_t.diffserv = pack(diffserv);
    ipv4_t.totalLen = pack(totalLen);
    ipv4_t.identification = pack(identification);
    ipv4_t.flags = pack(flags);
    ipv4_t.fragOffset = pack(fragOffset);
    ipv4_t.ttl = pack(ttl);
    ipv4_t.protocol = pack(protocol);
    ipv4_t.hdrChecksum = pack(hdrChecksum);
    ipv4_t.srcAddr = pack(srcAddr);
    ipv4_t.dstAddr = pack(dstAddr);
    return ipv4_t;
endfunction

typedef struct {
    Bit#(RoundSize) round;
} IngressMetadataT deriving (Bits, Eq);

instance DefaultValue#(IngressMetadataT);
defaultValue = unpack(0);
endinstance
instance DefaultMask#(IngressMetadataT);
defaultMask = unpack(maxBound);
endinstance

instance FShow#(IngressMetadataT);
    function Fmt fshow(IngressMetadataT p);
        return $format("IngressMetadataT: round=%h" , p.round);
    endfunction
endinstance

function IngressMetadataT extract_ingress_metadata(Bit#(16) data);
    Vector#(16, Bit#(1)) dataVec=unpack(data);
    Vector#(16, Bit#(1)) round = takeAt(0, dataVec);
    IngressMetadataT ingress_metadata_t = defaultValue;
    ingress_metadata_t.round = pack(round);
    return ingress_metadata_t;
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

instance FShow#(EthernetT);
    function Fmt fshow(EthernetT p);
        return $format("EthernetT: dstAddr=%h, srcAddr=%h, etherType=%h" , p.dstAddr, p.srcAddr, p.etherType);
    endfunction
endinstance

function EthernetT extract_ethernet(Bit#(112) data);
    Vector#(112, Bit#(1)) dataVec=unpack(data);
    Vector#(48, Bit#(1)) dstAddr = takeAt(0, dataVec);
    Vector#(48, Bit#(1)) srcAddr = takeAt(48, dataVec);
    Vector#(16, Bit#(1)) etherType = takeAt(96, dataVec);
    EthernetT ethernet_t = defaultValue;
    ethernet_t.dstAddr = pack(dstAddr);
    ethernet_t.srcAddr = pack(srcAddr);
    ethernet_t.etherType = pack(etherType);
    return ethernet_t;
endfunction

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

instance FShow#(StandardMetadataT);
    function Fmt fshow(StandardMetadataT p);
        return $format("StandardMetadataT: ingress_port=%h, packet_length=%h, egress_spec=%h, egress_port=%h, egress_instance=%h, instance_type=%h, clone_spec=%h, _padding=%h" , p.ingress_port, p.packet_length, p.egress_spec, p.egress_port, p.egress_instance, p.instance_type, p.clone_spec, p._padding);
    endfunction
endinstance

function StandardMetadataT extract_standard_metadata(Bit#(160) data);
    Vector#(160, Bit#(1)) dataVec=unpack(data);
    Vector#(9, Bit#(1)) ingress_port = takeAt(0, dataVec);
    Vector#(32, Bit#(1)) packet_length = takeAt(9, dataVec);
    Vector#(9, Bit#(1)) egress_spec = takeAt(41, dataVec);
    Vector#(9, Bit#(1)) egress_port = takeAt(50, dataVec);
    Vector#(32, Bit#(1)) egress_instance = takeAt(59, dataVec);
    Vector#(32, Bit#(1)) instance_type = takeAt(91, dataVec);
    Vector#(32, Bit#(1)) clone_spec = takeAt(123, dataVec);
    Vector#(5, Bit#(1)) _padding = takeAt(155, dataVec);
    StandardMetadataT standard_metadata_t = defaultValue;
    standard_metadata_t.ingress_port = pack(ingress_port);
    standard_metadata_t.packet_length = pack(packet_length);
    standard_metadata_t.egress_spec = pack(egress_spec);
    standard_metadata_t.egress_port = pack(egress_port);
    standard_metadata_t.egress_instance = pack(egress_instance);
    standard_metadata_t.instance_type = pack(instance_type);
    standard_metadata_t.clone_spec = pack(clone_spec);
    standard_metadata_t._padding = pack(_padding);
    return standard_metadata_t;
endfunction

typedef struct {
    Bit#(8) role;
} SwitchMetadataT deriving (Bits, Eq);

instance DefaultValue#(SwitchMetadataT);
defaultValue = unpack(0);
endinstance
instance DefaultMask#(SwitchMetadataT);
defaultMask = unpack(maxBound);
endinstance

instance FShow#(SwitchMetadataT);
    function Fmt fshow(SwitchMetadataT p);
        return $format("SwitchMetadataT: role=%h" , p.role);
    endfunction
endinstance

function SwitchMetadataT extract_switch_metadata(Bit#(8) data);
    Vector#(8, Bit#(1)) dataVec=unpack(data);
    Vector#(8, Bit#(1)) role = takeAt(0, dataVec);
    SwitchMetadataT switch_metadata_t = defaultValue;
    switch_metadata_t.role = pack(role);
    return switch_metadata_t;
endfunction

typedef struct {
   Maybe#(Bit#(16)) msgtype; // ethernet$msgtype
   Maybe#(Bit#(48)) dstAddr; // ethernet$dstAddr
   Maybe#(Bit#(16)) etherType; // ethernet$etherType
   Maybe#(Bit#(8))  protocol; // ipv4$protocol
   Maybe#(Bit#(16)) dstPort; // ipv4$dstPort
   Maybe#(Bit#(InstanceSize)) paxos$inst; // paxos$inst
   Maybe#(Bit#(RoundSize)) paxos$rnd;
   Maybe#(Bit#(RoundSize)) paxos$vrnd;
   Maybe#(Bit#(256)) paxos$paxosval;
   Maybe#(Bit#(16)) paxos$acptid;
   Maybe#(Bit#(16)) paxos$msgtype;
   Maybe#(Bit#(RoundSize)) paxos_packet_meta$round;
   Maybe#(Role) switch_metadata$role;
   Maybe#(Bool) valid_ethernet;
   Maybe#(Bool) valid_arp;
   Maybe#(Bool) valid_ipv4;
   Maybe#(Bool) valid_ipv6;
   Maybe#(Bool) valid_udp;
   Maybe#(Bool) valid_paxos;
} MetadataT deriving (Bits, Eq);

instance DefaultValue#(MetadataT);
defaultValue =
MetadataT {
   msgtype: tagged Invalid,
   dstAddr: tagged Invalid,
   etherType: tagged Invalid,
   protocol: tagged Invalid,
   dstPort: tagged Invalid,
   paxos$inst: tagged Invalid,
   paxos$rnd: tagged Invalid,
   paxos$vrnd: tagged Invalid,
   paxos$paxosval: tagged Invalid,
   paxos$acptid: tagged Invalid,
   paxos$msgtype: tagged Invalid,
   paxos_packet_meta$round: tagged Invalid,
   switch_metadata$role: tagged Invalid,
   valid_ethernet: tagged Invalid,
   valid_arp: tagged Invalid,
   valid_ipv4: tagged Invalid,
   valid_ipv6: tagged Invalid,
   valid_udp: tagged Invalid,
   valid_paxos: tagged Invalid
};
endinstance

instance FShow#(MetadataT);
   function Fmt fshow(MetadataT p);
      return $format("msgtype=", fshow(p.msgtype), ",")+
             $format("dstAddr=", fshow(p.dstAddr), ",")+
             $format("etherType=", fshow(p.etherType), ",")+
             $format("protocol=", fshow(p.protocol), ",")+
             $format("dstPort=", fshow(p.dstPort), ",")+
             $format("role=", fshow(p.switch_metadata$role), ",")+
             $format("round=", fshow(p.paxos_packet_meta$round), ",")+
             $format("paxos$inst=", fshow(p.paxos$inst), ",")+
             $format("paxos$rnd=", fshow(p.paxos$rnd), ",")+
             $format("paxos$vrnd=", fshow(p.paxos$vrnd), ",")+
             $format("paxos$val=", fshow(p.paxos$paxosval), ",")+
             $format("paxos$acpt=", fshow(p.paxos$acptid), ",")+
             $format("paxos$msgtype=", fshow(p.paxos$msgtype));
   endfunction
endinstance

typedef Client#(MetadataRequest, MetadataResponse) MetadataClient;
typedef Server#(MetadataRequest, MetadataResponse) MetadataServer;

typedef Client#(BBRequest, BBResponse) BBClient;
typedef Server#(BBRequest, BBResponse) BBServer;

/* generate tables */
typedef struct {
    Bit#(6) padding;
    Bit#(48) dstAddr;
} DmacTblReqT deriving (Bits, Eq, FShow);

//typedef union tagged {
//    struct {
//        Bit#(9) port;
//    } Forward;
//
//    struct {
//        Bit#(4) group;
//    } Broadcast;
//} DmacTblRespT deriving (Bits, Eq, FShow);

typedef struct {
   Bit#(9) port;
} DmacTblParamT deriving (Bits, Eq, FShow);

typedef struct {
   DmacTblActionT act;
   DmacTblParamT param;
} DmacTblRespT deriving (Bits, Eq, FShow);

typedef struct {
    Bit#(2) padding;
    Bit#(16) msgtype;
} SequenceTblReqT deriving (Bits, Eq, FShow);

typedef struct {
   SequenceTblActionT act;
} SequenceTblRespT deriving (Bits, Eq, FShow);

typedef struct {
    Bit#(2) padding;
    Bit#(16) msgtype;
} AcceptorTblReqT deriving (Bits, Eq, FShow);

typedef struct {
   AcceptorTblActionT act;
} AcceptorTblRespT deriving (Bits, Eq, FShow);

(* synthesize *)
module mkMatchTable_256_dmacTable(MatchTable#(256, SizeOf#(DmacTblReqT), SizeOf#(DmacTblRespT)));
   MatchTable#(256, SizeOf#(DmacTblReqT), SizeOf#(DmacTblRespT)) ifc <- mkMatchTable();
   return ifc;
endmodule

(* synthesize *)
module mkMatchTable_256_acceptorTable(MatchTable#(256, SizeOf#(AcceptorTblReqT), SizeOf#(AcceptorTblRespT)));
   MatchTable#(256, SizeOf#(AcceptorTblReqT), SizeOf#(AcceptorTblRespT)) ifc <- mkMatchTable();
   return ifc;
endmodule

(* synthesize *)
module mkMatchTable_256_sequenceTable(MatchTable#(256, SizeOf#(SequenceTblReqT), SizeOf#(SequenceTblRespT)));
   MatchTable#(256, SizeOf#(SequenceTblReqT), SizeOf#(SequenceTblRespT)) ifc <- mkMatchTable();
   return ifc;
endmodule


add a cycle counter to HDMI indication.vsync()

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

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

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

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

import Vector::*;
import Clocks::*;
import FIFO::*;
import FIFOF::*;
import GetPut::*;
import SyncBits::*;
import YUV::*;

interface HDMI;
    method Bit#(1) vsync;
    method Bit#(1) hsync;
    method Bit#(1) de;
    method Bit#(16) data;
    interface Clock clock_if;
    interface Reset reset_if;
endinterface

interface HdmiInternalRequest;
    method Action setTestPattern(Bit#(1) v);
    method Action setPatternColor(Bit#(32) v);
    method Action setHsyncWidth(Bit#(12) hsyncWidth);
    method Action setDePixelCountMinMax(Bit#(12) min, Bit#(12) max);
    method Action setVsyncWidth(Bit#(11) vsyncWidth);
    method Action setDeLineCountMinMax(Bit#(11) min, Bit#(11) max);
    method Action setNumberOfLines(Bit#(11) lines);
    method Action setNumberOfPixels(Bit#(12) pixels);
    method Action waitForVsync(Bit#(32) unused);
endinterface
interface HdmiInternalIndication;
    method Action vsync(Bit#(64) v);
endinterface

interface HdmiGenerator;
    interface HdmiInternalRequest control;
    interface HDMI hdmi;
    interface Put#(Bit#(64)) request;
endinterface

module mkHdmiGenerator#(Clock axi_clock, Reset axi_reset,
        SyncPulseIfc vsyncPulse, HdmiInternalIndication indication)(HdmiGenerator);
    Clock defaultClock <- exposeCurrentClock();
    Reset defaultReset <- exposeCurrentReset();
    // 1920 * 1080
    Reg#(Bit#(12)) hsyncWidth <- mkSyncReg(44, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(12)) dePixelCountMinimum <- mkSyncReg(192, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(12)) dePixelCountMaximum <- mkSyncReg(1920 + 192, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(12)) pixelMidpoint <- mkSyncReg((1920/2) + 192, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(11)) vsyncWidth <- mkSyncReg(5, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(11)) deLineCountMinimum <- mkSyncReg(41, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(11)) deLineCountMaximum <- mkSyncReg(1080+41, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(11)) lineMidpoint <- mkSyncReg((1080/2) + 41, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(11)) numberOfLines <- mkSyncReg(1080 + 45, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(12)) numberOfPixels <- mkSyncReg(1920 + 192 + 44 + 44, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(11)) lineCount <- mkReg(0);
    Reg#(Bit#(12)) pixelCount <- mkReg(0);
    Vector#(4, Reg#(Bit#(24))) patternRegs <- replicateM(mkSyncReg(24'h00FFFFFF, axi_clock, axi_reset, defaultClock));
    Reg#(Bit#(1)) shadowTestPatternEnabled <- mkSyncReg(1, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(1)) testPatternEnabled <- mkReg(1);
    Reg#(Bool) waitingForVsync <- mkSyncReg(False, axi_clock, axi_reset, defaultClock);
    SyncPulseIfc sendVsyncIndication <- mkSyncPulse(defaultClock, defaultReset, axi_clock);
    Reg#(Bit#(24)) pixelData <- mkReg(24'h00ff00ff);

    Reg#(Rgb888Stage) rgb888StageReg <- mkReg(unpack(0));
    Reg#(Yuv444IntermediatesStage) yuv444IntermediatesStageReg <- mkReg(unpack(0));
    Reg#(Yuv444Stage) yuv444StageReg <- mkReg(unpack(0));
    Reg#(Yuv422Stage) yuv422StageReg <- mkReg(unpack(0));
    Reg#(Bool) evenOddPixelReg <- mkReg(False);

   Reg#(Bit#(32)) counter <- mkReg(0, clocked_by axi_clock, reset_by axi_reset);
   Reg#(Bit#(32)) elapsed <- mkReg(0, clocked_by axi_clock, reset_by axi_reset);
   rule axicyclecount;
      counter <= counter + 1;
   endrule

    rule vsyncReceived if (sendVsyncIndication.pulse());
       elapsed <= counter;
       indication.vsync(extend(counter - elapsed));
       waitingForVsync <= False;
    endrule

    rule init_pattern;
        patternRegs[1] <= 24'h00FF0000; // blue
        patternRegs[2] <= 24'h0000FF00; // green
        patternRegs[3] <= 24'h000000FF; // red
        //patternRegs[1] <= 32'h80ff80ff; // yuv422 white
        //patternRegs[2] <= 32'h2c961596; // yuv422 green
        //patternRegs[3] <= 32'hff1d6b1d; // yuv422 red
    endrule

    rule inc_counters;
        if (lineCount == 0 && pixelCount == 0)
            begin
            vsyncPulse.send();
            if (waitingForVsync) begin
	       sendVsyncIndication.send();
	    end
            testPatternEnabled <= shadowTestPatternEnabled;
            end
        if (pixelCount == numberOfPixels-1)
           begin
           pixelCount <= 0;
           if (lineCount == numberOfLines-1)
               lineCount <= 0;
           else
               lineCount <= lineCount+1;
           end
        else
            pixelCount <= pixelCount + 1;
    endrule

    rule output_data_rule;
        let hsync = (pixelCount < hsyncWidth) ? 1 : 0;
        let vsync = (lineCount < vsyncWidth) ? 1 : 0;
        let isActiveLine = (lineCount >= deLineCountMinimum && lineCount < deLineCountMaximum);
        let dataEnable = (pixelCount >= dePixelCountMinimum && pixelCount < dePixelCountMaximum && isActiveLine);
        Rgb888 pixel = unpack(pixelData);
        rgb888StageReg <= Rgb888Stage{de: pack(dataEnable),
            vsync: vsync, hsync: hsync, pixel: pixel };
    endrule

    rule test_rule if (testPatternEnabled != 0);
        pixelData <= patternRegs[{pack(lineCount >= lineMidpoint), pack(pixelCount >= pixelMidpoint)}];
    endrule

    rule yuv444int_rule;
        let previous = rgb888StageReg;
        let pixel = previous.pixel;
        yuv444IntermediatesStageReg <= Yuv444IntermediatesStage {
            vsync: previous.vsync, hsync: previous.hsync, de: previous.de,
            data: (previous.de != 0) ? rgbToYuvIntermediates(pixel) : unpack(0)
        };
    endrule

    rule yuv444_rule;
        let previous = yuv444IntermediatesStageReg;
        yuv444StageReg <= Yuv444Stage {
            vsync: previous.vsync, hsync: previous.hsync, de: previous.de,
            data: (previous.de != 0) ? yuvIntermediatesToYuv444(previous.data) : unpack(0)
        };
    endrule

    rule yuv422_rule;
        let previous = yuv444StageReg;
        if (previous.de != 0)
            evenOddPixelReg <= !evenOddPixelReg;
        Bit#(16) data = { evenOddPixelReg ? previous.data.u : previous.data.v,
                          previous.data.y };
        yuv422StageReg <= Yuv422Stage {
            vsync: previous.vsync, hsync: previous.hsync, de: previous.de,
            data: data
        };
    endrule

    interface Put request;
        method Action put(Bit#(64) v) if (testPatternEnabled == 0);
	    pixelData <= v[23:0];
        endmethod
    endinterface: request

    interface HdmiInternalRequest control;
        method Action setPatternColor(Bit#(32) v);
            patternRegs[0] <= v[23:0];
        endmethod
        method Action setTestPattern(Bit#(1) v);
            shadowTestPatternEnabled <= v;
        endmethod
        method Action setHsyncWidth(Bit#(12) width);
            hsyncWidth <= width;
        endmethod
        method Action setDePixelCountMinMax(Bit#(12) min, Bit#(12) max);
            dePixelCountMinimum <= min;
            dePixelCountMaximum <= max;
            pixelMidpoint <= (min + max) / 2;
        endmethod
        method Action setVsyncWidth(Bit#(11) width);
            vsyncWidth <= width;
        endmethod
        method Action setDeLineCountMinMax(Bit#(11) min, Bit#(11) max);
            deLineCountMinimum <= min;
            deLineCountMaximum <= max;
            lineMidpoint <= (min + max) / 2;
        endmethod
        method Action setNumberOfLines(Bit#(11) lines);
            numberOfLines <= lines;
        endmethod
        method Action setNumberOfPixels(Bit#(12) pixels);
            numberOfPixels <= pixels;
        endmethod
        method Action waitForVsync(Bit#(32) unused);
            waitingForVsync <= True;
        endmethod
    endinterface
    interface HDMI hdmi;
        method Bit#(1) vsync;
            return yuv422StageReg.vsync;
        endmethod
        method Bit#(1) hsync;
            return yuv422StageReg.hsync;
        endmethod
        method Bit#(1) de;
            return yuv422StageReg.de;
        endmethod
        method Bit#(16) data;
            return yuv422StageReg.data;
        endmethod
        interface clock_if = defaultClock;
        interface reset_if = defaultReset;
    endinterface
endmodule

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

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

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

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

import Vector::*;
import Clocks::*;
import FIFO::*;
import FIFOF::*;
import GetPut::*;
import SyncBits::*;
import YUV::*;

interface HDMI;
    method Bit#(1) vsync;
    method Bit#(1) hsync;
    method Bit#(1) de;
    method Bit#(16) data;
    interface Clock clock_if;
    interface Reset reset_if;
endinterface

interface HdmiInternalRequest;
    method Action setTestPattern(Bit#(1) v);
    method Action setPatternColor(Bit#(32) v);
    method Action setHsyncWidth(Bit#(12) hsyncWidth);
    method Action setDePixelCountMinMax(Bit#(12) min, Bit#(12) max);
    method Action setVsyncWidth(Bit#(11) vsyncWidth);
    method Action setDeLineCountMinMax(Bit#(11) min, Bit#(11) max);
    method Action setNumberOfLines(Bit#(11) lines);
    method Action setNumberOfPixels(Bit#(12) pixels);
    method Action waitForVsync(Bit#(32) unused);
endinterface
interface HdmiInternalIndication;
    method Action vsync(Bit#(64) v);
endinterface

interface HdmiGenerator;
    interface HdmiInternalRequest control;
    interface HDMI hdmi;
    interface Put#(Bit#(64)) request;
endinterface

module mkHdmiGenerator#(Clock axi_clock, Reset axi_reset,
        SyncPulseIfc vsyncPulse, HdmiInternalIndication indication)(HdmiGenerator);
    Clock defaultClock <- exposeCurrentClock();
    Reset defaultReset <- exposeCurrentReset();
    // 1920 * 1080
    Reg#(Bit#(12)) hsyncWidth <- mkSyncReg(44, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(12)) dePixelCountMinimum <- mkSyncReg(192, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(12)) dePixelCountMaximum <- mkSyncReg(1920 + 192, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(12)) pixelMidpoint <- mkSyncReg((1920/2) + 192, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(11)) vsyncWidth <- mkSyncReg(5, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(11)) deLineCountMinimum <- mkSyncReg(41, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(11)) deLineCountMaximum <- mkSyncReg(1080+41, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(11)) lineMidpoint <- mkSyncReg((1080/2) + 41, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(11)) numberOfLines <- mkSyncReg(1080 + 45, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(12)) numberOfPixels <- mkSyncReg(1920 + 192 + 44 + 44, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(11)) lineCount <- mkReg(0);
    Reg#(Bit#(12)) pixelCount <- mkReg(0);
    Vector#(4, Reg#(Bit#(24))) patternRegs <- replicateM(mkSyncReg(24'h00FFFFFF, axi_clock, axi_reset, defaultClock));
    Reg#(Bit#(1)) shadowTestPatternEnabled <- mkSyncReg(1, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(1)) testPatternEnabled <- mkReg(1);
    Reg#(Bool) waitingForVsync <- mkSyncReg(False, axi_clock, axi_reset, defaultClock);
    SyncPulseIfc sendVsyncIndication <- mkSyncPulse(defaultClock, defaultReset, axi_clock);
    Reg#(Bit#(24)) pixelData <- mkReg(24'h00ff00ff);

    Reg#(Rgb888Stage) rgb888StageReg <- mkReg(unpack(0));
    Reg#(Yuv444IntermediatesStage) yuv444IntermediatesStageReg <- mkReg(unpack(0));
    Reg#(Yuv444Stage) yuv444StageReg <- mkReg(unpack(0));
    Reg#(Yuv422Stage) yuv422StageReg <- mkReg(unpack(0));
    Reg#(Bool) evenOddPixelReg <- mkReg(False);

    rule vsyncReceived if (sendVsyncIndication.pulse());
        Bit#(64) v = 0;
        //v[31:0] = vsyncPulseCountReg;
        //v[47:32] = extend(numberOfPixels);
        //v[63:48] = extend(numberOfLines);
        indication.vsync(v);
        waitingForVsync <= False;
    endrule

    rule init_pattern;
        patternRegs[1] <= 24'h00FF0000; // blue
        patternRegs[2] <= 24'h0000FF00; // green
        patternRegs[3] <= 24'h000000FF; // red
        //patternRegs[1] <= 32'h80ff80ff; // yuv422 white
        //patternRegs[2] <= 32'h2c961596; // yuv422 green
        //patternRegs[3] <= 32'hff1d6b1d; // yuv422 red
    endrule

    rule inc_counters;
        if (lineCount == 0 && pixelCount == 0)
            begin
            vsyncPulse.send();
            if (waitingForVsync)
                sendVsyncIndication.send();
            testPatternEnabled <= shadowTestPatternEnabled;
            end
        if (pixelCount == numberOfPixels-1)
           begin
           pixelCount <= 0;
           if (lineCount == numberOfLines-1)
               lineCount <= 0;
           else
               lineCount <= lineCount+1;
           end
        else
            pixelCount <= pixelCount + 1;
    endrule

    rule output_data_rule;
        let hsync = (pixelCount < hsyncWidth) ? 1 : 0;
        let vsync = (lineCount < vsyncWidth) ? 1 : 0;
        let isActiveLine = (lineCount >= deLineCountMinimum && lineCount < deLineCountMaximum);
        let dataEnable = (pixelCount >= dePixelCountMinimum && pixelCount < dePixelCountMaximum && isActiveLine);
        Rgb888 pixel = unpack(pixelData);
        rgb888StageReg <= Rgb888Stage{de: pack(dataEnable),
            vsync: vsync, hsync: hsync, pixel: pixel };
    endrule

    rule test_rule if (testPatternEnabled != 0);
        pixelData <= patternRegs[{pack(lineCount >= lineMidpoint), pack(pixelCount >= pixelMidpoint)}];
    endrule

    rule yuv444int_rule;
        let previous = rgb888StageReg;
        let pixel = previous.pixel;
        yuv444IntermediatesStageReg <= Yuv444IntermediatesStage {
            vsync: previous.vsync, hsync: previous.hsync, de: previous.de,
            data: (previous.de != 0) ? rgbToYuvIntermediates(pixel) : unpack(0)
        };
    endrule

    rule yuv444_rule;
        let previous = yuv444IntermediatesStageReg;
        yuv444StageReg <= Yuv444Stage {
            vsync: previous.vsync, hsync: previous.hsync, de: previous.de,
            data: (previous.de != 0) ? yuvIntermediatesToYuv444(previous.data) : unpack(0)
        };
    endrule

    rule yuv422_rule;
        let previous = yuv444StageReg;
        if (previous.de != 0)
            evenOddPixelReg <= !evenOddPixelReg;
        Bit#(16) data = { evenOddPixelReg ? previous.data.u : previous.data.v,
                          previous.data.y };
        yuv422StageReg <= Yuv422Stage {
            vsync: previous.vsync, hsync: previous.hsync, de: previous.de,
            data: data
        };
    endrule

    interface Put request;
        method Action put(Bit#(64) v) if (testPatternEnabled == 0);
	    pixelData <= v[23:0];
        endmethod
    endinterface: request

    interface HdmiInternalRequest control;
        method Action setPatternColor(Bit#(32) v);
            patternRegs[0] <= v[23:0];
        endmethod
        method Action setTestPattern(Bit#(1) v);
            shadowTestPatternEnabled <= v;
        endmethod
        method Action setHsyncWidth(Bit#(12) width);
            hsyncWidth <= width;
        endmethod
        method Action setDePixelCountMinMax(Bit#(12) min, Bit#(12) max);
            dePixelCountMinimum <= min;
            dePixelCountMaximum <= max;
            pixelMidpoint <= (min + max) / 2;
        endmethod
        method Action setVsyncWidth(Bit#(11) width);
            vsyncWidth <= width;
        endmethod
        method Action setDeLineCountMinMax(Bit#(11) min, Bit#(11) max);
            deLineCountMinimum <= min;
            deLineCountMaximum <= max;
            lineMidpoint <= (min + max) / 2;
        endmethod
        method Action setNumberOfLines(Bit#(11) lines);
            numberOfLines <= lines;
        endmethod
        method Action setNumberOfPixels(Bit#(12) pixels);
            numberOfPixels <= pixels;
        endmethod
        method Action waitForVsync(Bit#(32) unused);
            waitingForVsync <= True;
        endmethod
    endinterface
    interface HDMI hdmi;
        method Bit#(1) vsync;
            return yuv422StageReg.vsync;
        endmethod
        method Bit#(1) hsync;
            return yuv422StageReg.hsync;
        endmethod
        method Bit#(1) de;
            return yuv422StageReg.de;
        endmethod
        method Bit#(16) data;
            return yuv422StageReg.data;
        endmethod
        interface clock_if = defaultClock;
        interface reset_if = defaultReset;
    endinterface
endmodule


fixing clock domain crossings and connections

import FIFOF::*;
import BRAMFIFO::*;
import GetPut::*;
import Clocks::*;
import Connectable::*;
import Probe::*;
import Vector::*;

import AxiBits::*;
import AxiStream::*;
import AxiEthBufferBvi::*;
import GetPutWithClocks::*;
import TriModeMacBvi::*;
import GigEthPcsPmaBvi::*;
import AxiEth1000BaseX::*;
import SyncAxisFifo32x1024::*;

interface AxiEthSubsystem;
   interface TrimodemacRx_axis_mac m_axis_rxd;
   //interface AxiStreamMaster#(32) m_axis_rxs;
   interface TrimodemacTx_axis_mac  s_axis_txd;
   //interface AxiStreamSlave#(32)  s_axis_txc;
   interface TrimodemacRx     rx;
   interface TrimodemacTx     tx;

   interface TrimodemacS_axi s_axi;
   interface TrimodemacMac mac;
   interface AxiethbviSfp sfp;
   interface AxiethbviMgt mgt;
   interface GigethpcspmabviSignal signal;
   interface GigethpcspmabviMmcm mmcm;
endinterface

instance Connectable#(TrimodemacGmii,GigethpcspmabviGmii);
   module mkConnection#(TrimodemacGmii mac, GigethpcspmabviGmii phy)(Empty);
      rule rx;
	 mac.rx_dv(phy.rx_dv());
	 mac.rx_er(phy.rx_er());
	 mac.rxd(phy.rxd());
      endrule
      rule tx;
	 phy.tx_en(mac.tx_en());
	 phy.tx_er(mac.tx_er());
	 phy.txd(mac.txd());
      endrule
   endmodule
endinstance

instance Connectable#(TrimodemacMdio,GigethpcspmabviMdio);
   module mkConnection#(TrimodemacMdio macMdio, GigethpcspmabviMdio phyMdio)(Empty);
      rule rl_mdio;
	 macMdio.i(phyMdio.o());
	 phyMdio.i(macMdio.o());
      endrule
   endmodule
endinstance

instance Connectable#(TriModeMac,GigEthPcsPma);
   module mkConnection#(TriModeMac mac, GigEthPcsPma phy)(Empty);
      let mdcCnx  <- mkConnection(phy.mdc,  mac.mdc); // should be a clock, but PHY is providing a clock to MAC and this would make a cycle
      let mdioCnx <- mkConnection(mac.mdio, phy.mdio);
      let gmiiCnx <- mkConnection(mac.gmii, phy.gmii);
   endmodule
endinstance

instance ConnectableWithClocks#(AxiStreamMaster#(32), TrimodemacTx_axis_mac);
   module mkConnectionWithClocks#(AxiStreamMaster#(32) from, TrimodemacTx_axis_mac to, Clock fromClock, Reset fromReset, Clock toClock, Reset toReset)(Empty);
      Reg#(Bit#(2)) phaseReg <- mkReg(0, clocked_by toClock, reset_by toReset);
      let sfifo <- mkSyncAxisFifo32x1024(fromClock, fromReset, toClock, toReset);

      Probe#(Bit#(32)) fromDataProbe <- mkProbe(clocked_by fromClock, reset_by fromReset);
      Probe#(Bit#(4)) fromKeepProbe <- mkProbe(clocked_by fromClock, reset_by fromReset);
      Probe#(Bit#(1)) fromLastProbe <- mkProbe(clocked_by fromClock, reset_by fromReset);
      Probe#(Bit#(8)) toDataProbe <- mkProbe(clocked_by toClock, reset_by toReset);
      Probe#(Bit#(1)) toLastProbe <- mkProbe(clocked_by toClock, reset_by toReset);
      Probe#(Bit#(2)) phaseProbe    <- mkProbe(clocked_by toClock, reset_by toReset);

      mkConnection(from, sfifo.s_axis);

      Wire#(Bool) doDeq <- mkDWire(False, clocked_by toClock, reset_by toReset);
      rule rl_expand if (to.tready() == 1 && sfifo.m_axis.tvalid() == 1);
	 Vector#(4,Bit#(8)) data = unpack(sfifo.m_axis.tdata());
	 let keep = sfifo.m_axis.tkeep();
	 let last = sfifo.m_axis.tlast();
	 //match { .data, .keep, .last } = sfifo.first();
	 let phase = phaseReg;
	 Bool lastPhase = (phaseReg == 3);
	 Bit#(4) moreData = keep[3:phase+1];
	 if (!lastPhase)
	    lastPhase = (moreData != 0);
	 phase = phase + 1;

	 to.tdata(data[phase]);
	 //to.tkeep(keep[phase]);
	 to.tlast(pack(last == 1 && lastPhase));

	 toDataProbe <= data[phase];
	 toLastProbe <= pack(last == 1 && lastPhase);

	 if (lastPhase) begin
	    //sfifo.deq();
	    doDeq <= True;
	    phase = 0;
	 end
	 phaseProbe <= phaseReg;
	 phaseReg <= phase;
      endrule

      rule rl_to_handshake;
	 to.tvalid(sfifo.m_axis.tvalid());
	 sfifo.m_axis.tready(pack(doDeq));
      endrule
   endmodule
endinstance

instance ConnectableWithClocks#(TrimodemacRx_axis_mac, AxiStreamSlave#(32));
   module mkConnectionWithClocks#(TrimodemacRx_axis_mac from, AxiStreamSlave#(32) to, Clock fromClock, Reset fromReset, Clock toClock, Reset toReset)(Empty);
      Reg#(Bit#(2)) phaseReg <- mkReg(0, clocked_by fromClock, reset_by fromReset);
      Vector#(4,Reg#(Bit#(8))) dataReg <- replicateM(mkReg(0), clocked_by fromClock, reset_by fromReset);
      Reg#(Bit#(4)) keepReg <- mkReg(0, clocked_by fromClock, reset_by fromReset);
      let sfifo <- mkSyncAxisFifo32x1024(fromClock, fromReset, toClock, toReset);

      Wire#(Bool) doEnq <- mkDWire(False, clocked_by fromClock, reset_by fromReset);

      Probe#(Bool) probeOverrun <- mkProbe(clocked_by fromClock, reset_by fromReset);
      rule rl_overrun if (from.tvalid() == 1 && sfifo.s_axis.tready() == 0);
	 probeOverrun <= True;
      endrule

      rule rl_combine if (unpack(from.tvalid()));
	 Bool last = unpack(from.tlast());
	 let phase = phaseReg + 1;
	 Vector#(4,Bit#(8)) data = readVReg(dataReg);
	 let keep = keepReg;
	 keep[phase]             = 1; //from.tkeep();
	 data[phase] = from.tdata();

	 sfifo.s_axis.tdata(pack(data));
	 sfifo.s_axis.tkeep(keep);
	 sfifo.s_axis.tlast(pack(last));

	 if (last || phaseReg == 3) begin
	    phase = 0;
	    data  = unpack(0);
	    keep  = 0;
	    doEnq <= True;
	    //sfifo.enq(tuple3(pack(data), keep, pack(last)));
	 end
	 phaseReg <= phase;
	 writeVReg(dataReg, data);
	 keepReg  <= keep;
      endrule

      rule rl_from_handshake;
	 //from.tready(pack(sfifo.s_axis.tready())); // scary -- no backpressure
	 sfifo.s_axis.tvalid(pack(doEnq));
      endrule

      mkConnection(sfifo.m_axis, to);
   endmodule
endinstance

module mkAxiEthBvi#(Clock axis_clk, Clock ref_clk)(AxiEthSubsystem);
   let reset <- exposeCurrentReset;

  // connect_bd_net -net eth_buf_RESET2PCSPMA [get_bd_pins eth_buf/RESET2PCSPMA] [get_bd_pins pcs_pma/reset] //FIXME
//   let resetToPcsPma <- mkReset(10, True, ref_clk);

   let pcs <- mkGigEthPcsPmaBvi(ref_clk, reset);
  // connect_bd_net -net pcs_pma_userclk2_out [get_bd_ports userclk2_out] [get_bd_pins eth_buf/GTX_CLK] [get_bd_pins eth_mac/gtx_clk] [get_bd_pins pcs_pma/userclk2_out]
   Clock gtx_clk = pcs.userclk2.out;

   let trimodemac <- mkTriModeMacBvi(gtx_clk, axis_clk, reset, reset, reset, reset);

  // connect_bd_intf_net -intf_net eth_mac_gmii [get_bd_intf_pins eth_mac/gmii] [get_bd_intf_pins pcs_pma/gmii_pcs_pma]
   let gmiiConnection <- mkConnection(trimodemac.gmii, pcs.gmii);

  // connect_bd_net -net eth_mac_mdc [get_bd_pins eth_mac/mdc] [get_bd_pins pcs_pma/mdc]
   rule rl_misc;
      pcs.mdc(trimodemac.mdc()); // actually a clock
   endrule
  // connect_bd_net -net eth_mac_mdio_o [get_bd_pins eth_mac/mdio_o] [get_bd_pins pcs_pma/mdio_i]
  // connect_bd_net -net pcs_pma_mdio_o [get_bd_pins eth_mac/mdio_i] [get_bd_pins pcs_pma/mdio_o]
  let mdioConnection <- mkConnection(trimodemac.mdio, pcs.mdio);

  // connect_bd_net -net reset_inv_Res [get_bd_pins eth_mac/glbl_rstn] [get_bd_pins eth_mac/rx_axi_rstn] [get_bd_pins eth_mac/tx_axi_rstn] [get_bd_pins reset_inv/Res]

   // ports:
   // connect_bd_intf_net -intf_net eth_mac_rx_statistics [get_bd_intf_ports rx_statistics] [get_bd_intf_pins eth_mac/rx_statistics]
   // connect_bd_intf_net -intf_net eth_mac_tx_statistics [get_bd_intf_ports tx_statistics] [get_bd_intf_pins eth_mac/tx_statistics]
   // connect_bd_intf_net -intf_net mgt_clk_1 [get_bd_intf_ports mgt_clk] [get_bd_intf_pins pcs_pma/gtrefclk_in]
   // connect_bd_intf_net -intf_net pcs_pma_sfp [get_bd_intf_ports sfp] [get_bd_intf_pins pcs_pma/sfp]
   // connect_bd_intf_net -intf_net s_axi_1 [get_bd_intf_ports s_axi] [get_bd_intf_pins eth_mac/s_axi]
   // connect_bd_intf_net -intf_net s_axis_pause_1 [get_bd_intf_ports s_axis_pause] [get_bd_intf_pins eth_mac/s_axis_pause]
   // connect_bd_intf_net -intf_net s_axis_tx_1 [get_bd_intf_ports s_axis_tx] [get_bd_intf_pins eth_mac/s_axis_tx]
   // connect_bd_net -net eth_mac_mac_irq [get_bd_ports mac_irq] [get_bd_pins eth_mac/mac_irq]
   // connect_bd_net -net eth_mac_rx_axis_filter_tuser [get_bd_ports rx_axis_filter_tuser] [get_bd_pins eth_mac/rx_axis_filter_tuser]
   // connect_bd_net -net eth_mac_rx_mac_aclk [get_bd_ports rx_mac_aclk] [get_bd_pins eth_mac/rx_mac_aclk]
   // connect_bd_net -net eth_mac_rx_reset [get_bd_ports rx_reset] [get_bd_pins eth_mac/rx_reset]
   // connect_bd_net -net eth_mac_tx_mac_aclk [get_bd_ports tx_mac_aclk] [get_bd_pins eth_mac/tx_mac_aclk]
   // connect_bd_net -net eth_mac_tx_reset [get_bd_ports tx_reset] [get_bd_pins eth_mac/tx_reset]
   // connect_bd_net -net glbl_rst_1 [get_bd_ports glbl_rst] [get_bd_pins pcs_pma/reset] [get_bd_pins reset_inv/Op1]
   // connect_bd_net -net pcs_pma_gt0_qplloutclk_out [get_bd_ports gt0_qplloutclk_out] [get_bd_pins pcs_pma/gt0_qplloutclk_out]
   // connect_bd_net -net pcs_pma_gt0_qplloutrefclk_out [get_bd_ports gt0_qplloutrefclk_out] [get_bd_pins pcs_pma/gt0_qplloutrefclk_out]
   // connect_bd_net -net pcs_pma_gtrefclk_bufg_out [get_bd_ports gtref_clk_buf_out] [get_bd_pins pcs_pma/gtrefclk_bufg_out]
   // connect_bd_net -net pcs_pma_gtrefclk_out [get_bd_ports gtref_clk_out] [get_bd_pins pcs_pma/gtrefclk_out]
   // connect_bd_net -net pcs_pma_mmcm_locked_out [get_bd_ports mmcm_locked_out] [get_bd_pins pcs_pma/mmcm_locked_out]
   // connect_bd_net -net pcs_pma_pma_reset_out [get_bd_ports pma_reset_out] [get_bd_pins pcs_pma/pma_reset_out]
   // connect_bd_net -net pcs_pma_rxuserclk2_out [get_bd_ports rxuserclk2_out] [get_bd_pins pcs_pma/rxuserclk2_out]
   // connect_bd_net -net pcs_pma_rxuserclk_out [get_bd_ports rxuserclk_out] [get_bd_pins pcs_pma/rxuserclk_out]
   // connect_bd_net -net pcs_pma_status_vector [get_bd_ports status_vector] [get_bd_pins pcs_pma/status_vector]
   // connect_bd_net -net pcs_pma_userclk2_out [get_bd_ports userclk2_out] [get_bd_pins eth_mac/gtx_clk] [get_bd_pins pcs_pma/userclk2_out]
   // connect_bd_net -net pcs_pma_userclk_out [get_bd_ports userclk_out] [get_bd_pins pcs_pma/userclk_out]
   // connect_bd_net -net ref_clk_1 [get_bd_ports ref_clk] [get_bd_pins pcs_pma/independent_clock_bufg]
   // connect_bd_intf_net -intf_net eth_mac_m_axis_rx [get_bd_intf_ports m_axis_rx] [get_bd_intf_pins eth_mac/m_axis_rx]
   // connect_bd_net -net s_axi_lite_clk_1 [get_bd_ports s_axi_lite_clk] [get_bd_pins eth_mac/s_axi_aclk]
   // connect_bd_net -net s_axi_lite_resetn_1 [get_bd_ports s_axi_lite_resetn] [get_bd_pins eth_mac/s_axi_resetn]
   // connect_bd_net -net signal_detect_1 [get_bd_ports signal_detect] [get_bd_pins pcs_pma/signal_detect]
   // connect_bd_net -net tx_ifg_delay_1 [get_bd_ports tx_ifg_delay] [get_bd_pins eth_mac/tx_ifg_delay]

   interface m_axis_rxd = trimodemac.rx_axis_mac;
   interface s_axis_txd = trimodemac.tx_axis_mac;
   interface rx = trimodemac.rx;
   interface tx = trimodemac.tx;
   interface s_axi = trimodemac.s_axi;
   interface mac   = trimodemac.mac;

   interface signal = pcs.signal;
   interface mmcm = pcs.mmcm;
   interface AxiethbviMgt mgt;
      method clk_clk_p = pcs.gtrefclk.p;
      method clk_clk_n = pcs.gtrefclk.n;
   endinterface
   interface AxiethbviSfp sfp;
      method txp = pcs.txp;
      method txn = pcs.txn;
      method rxp = pcs.rxp;
      method rxn = pcs.rxn;
   endinterface
endmodule

import GetPut::*;
import Clocks::*;
import Connectable::*;
import AxiBits::*;
import AxiStream::*;
import AxiEthBufferBvi::*;
import TriModeEthMacBvi::*;
import GigEthPcsPmaBvi::*;
import AxiEth1000BaseX::*;

interface AxiEthSubsystem;
   interface AxiStreamMaster#(32) m_axis_rxd;
   interface AxiStreamMaster#(32) m_axis_rxs;
   interface AxiStreamSlave#(32)  s_axis_txd;
   interface AxiStreamSlave#(32)  s_axis_txc;
   interface TrimodeethbviS_axi s_axi;
   interface TrimodeethbviMac mac;
   interface AxiethbviSfp sfp;
   interface AxiethbviMgt mgt;
   interface GigethpcspmabviSignal signal;
   interface GigethpcspmabviMmcm mmcm;
endinterface

module mkAxiEthBvi#(Clock axis_clk, Clock ref_clk)(AxiEthSubsystem);
   let reset <- exposeCurrentReset;

  // connect_bd_net -net eth_buf_RESET2PCSPMA [get_bd_pins eth_buf/RESET2PCSPMA] [get_bd_pins pcs_pma/reset] //FIXME
//   let resetToPcsPma <- mkReset(10, True, ref_clk);

   let pcs <- mkGigEthPcsPmaBvi(ref_clk, reset);
  // connect_bd_net -net pcs_pma_userclk2_out [get_bd_ports userclk2_out] [get_bd_pins eth_buf/GTX_CLK] [get_bd_pins eth_mac/gtx_clk] [get_bd_pins pcs_pma/userclk2_out]
   Clock gtx_clk = pcs.userclk2.out;

   let trimodemac <- mkTriModeMacBvi(gtx_clk, axis_clk, reset, reset, reset);

  // connect_bd_intf_net -intf_net eth_mac_gmii [get_bd_intf_pins eth_mac/gmii] [get_bd_intf_pins pcs_pma/gmii_pcs_pma]
   let gmiiConnection <- mkConnection(trimodemac.gmii, pcs.gmii);

  // connect_bd_net -net eth_mac_mdc [get_bd_pins eth_mac/mdc] [get_bd_pins pcs_pma/mdc]
   rule rl_misc;
      pcs.mdc(trimodemac.mdc()); // actually a clock
   endrule
  // connect_bd_net -net eth_mac_mdio_o [get_bd_pins eth_mac/mdio_o] [get_bd_pins pcs_pma/mdio_i]
  // connect_bd_net -net pcs_pma_mdio_o [get_bd_pins eth_mac/mdio_i] [get_bd_pins pcs_pma/mdio_o]
  let mdioConnection <- mkConnection(trimodemac.mdio, pcs.mdio);

  // connect_bd_net -net reset_inv_Res [get_bd_pins eth_mac/glbl_rstn] [get_bd_pins eth_mac/rx_axi_rstn] [get_bd_pins eth_mac/tx_axi_rstn] [get_bd_pins reset_inv/Res]

   // ports:
   // connect_bd_intf_net -intf_net eth_mac_rx_statistics [get_bd_intf_ports rx_statistics] [get_bd_intf_pins eth_mac/rx_statistics]
   // connect_bd_intf_net -intf_net eth_mac_tx_statistics [get_bd_intf_ports tx_statistics] [get_bd_intf_pins eth_mac/tx_statistics]
   // connect_bd_intf_net -intf_net mgt_clk_1 [get_bd_intf_ports mgt_clk] [get_bd_intf_pins pcs_pma/gtrefclk_in]
   // connect_bd_intf_net -intf_net pcs_pma_sfp [get_bd_intf_ports sfp] [get_bd_intf_pins pcs_pma/sfp]
   // connect_bd_intf_net -intf_net s_axi_1 [get_bd_intf_ports s_axi] [get_bd_intf_pins eth_mac/s_axi]
   // connect_bd_intf_net -intf_net s_axis_pause_1 [get_bd_intf_ports s_axis_pause] [get_bd_intf_pins eth_mac/s_axis_pause]
   // connect_bd_intf_net -intf_net s_axis_tx_1 [get_bd_intf_ports s_axis_tx] [get_bd_intf_pins eth_mac/s_axis_tx]
   // connect_bd_net -net eth_mac_mac_irq [get_bd_ports mac_irq] [get_bd_pins eth_mac/mac_irq]
   // connect_bd_net -net eth_mac_rx_axis_filter_tuser [get_bd_ports rx_axis_filter_tuser] [get_bd_pins eth_mac/rx_axis_filter_tuser]
   // connect_bd_net -net eth_mac_rx_mac_aclk [get_bd_ports rx_mac_aclk] [get_bd_pins eth_mac/rx_mac_aclk]
   // connect_bd_net -net eth_mac_rx_reset [get_bd_ports rx_reset] [get_bd_pins eth_mac/rx_reset]
   // connect_bd_net -net eth_mac_tx_mac_aclk [get_bd_ports tx_mac_aclk] [get_bd_pins eth_mac/tx_mac_aclk]
   // connect_bd_net -net eth_mac_tx_reset [get_bd_ports tx_reset] [get_bd_pins eth_mac/tx_reset]
   // connect_bd_net -net glbl_rst_1 [get_bd_ports glbl_rst] [get_bd_pins pcs_pma/reset] [get_bd_pins reset_inv/Op1]
   // connect_bd_net -net pcs_pma_gt0_qplloutclk_out [get_bd_ports gt0_qplloutclk_out] [get_bd_pins pcs_pma/gt0_qplloutclk_out]
   // connect_bd_net -net pcs_pma_gt0_qplloutrefclk_out [get_bd_ports gt0_qplloutrefclk_out] [get_bd_pins pcs_pma/gt0_qplloutrefclk_out]
   // connect_bd_net -net pcs_pma_gtrefclk_bufg_out [get_bd_ports gtref_clk_buf_out] [get_bd_pins pcs_pma/gtrefclk_bufg_out]
   // connect_bd_net -net pcs_pma_gtrefclk_out [get_bd_ports gtref_clk_out] [get_bd_pins pcs_pma/gtrefclk_out]
   // connect_bd_net -net pcs_pma_mmcm_locked_out [get_bd_ports mmcm_locked_out] [get_bd_pins pcs_pma/mmcm_locked_out]
   // connect_bd_net -net pcs_pma_pma_reset_out [get_bd_ports pma_reset_out] [get_bd_pins pcs_pma/pma_reset_out]
   // connect_bd_net -net pcs_pma_rxuserclk2_out [get_bd_ports rxuserclk2_out] [get_bd_pins pcs_pma/rxuserclk2_out]
   // connect_bd_net -net pcs_pma_rxuserclk_out [get_bd_ports rxuserclk_out] [get_bd_pins pcs_pma/rxuserclk_out]
   // connect_bd_net -net pcs_pma_status_vector [get_bd_ports status_vector] [get_bd_pins pcs_pma/status_vector]
   // connect_bd_net -net pcs_pma_userclk2_out [get_bd_ports userclk2_out] [get_bd_pins eth_mac/gtx_clk] [get_bd_pins pcs_pma/userclk2_out]
   // connect_bd_net -net pcs_pma_userclk_out [get_bd_ports userclk_out] [get_bd_pins pcs_pma/userclk_out]
   // connect_bd_net -net ref_clk_1 [get_bd_ports ref_clk] [get_bd_pins pcs_pma/independent_clock_bufg]
   // connect_bd_intf_net -intf_net eth_mac_m_axis_rx [get_bd_intf_ports m_axis_rx] [get_bd_intf_pins eth_mac/m_axis_rx]
   // connect_bd_net -net s_axi_lite_clk_1 [get_bd_ports s_axi_lite_clk] [get_bd_pins eth_mac/s_axi_aclk]
   // connect_bd_net -net s_axi_lite_resetn_1 [get_bd_ports s_axi_lite_resetn] [get_bd_pins eth_mac/s_axi_resetn]
   // connect_bd_net -net signal_detect_1 [get_bd_ports signal_detect] [get_bd_pins pcs_pma/signal_detect]
   // connect_bd_net -net tx_ifg_delay_1 [get_bd_ports tx_ifg_delay] [get_bd_pins eth_mac/tx_ifg_delay]

   interface m_axis_rxd = buffer.axi_str_rxd;
   //interface m_axis_rxs = buffer.axi_str_rxs;
   interface s_axis_txd = buffer.axi_str_txd;
   //interface s_axis_txc = buffer.axi_str_txc;
   interface s_axi = trimodemac.s_axi;
   interface mac   = trimodemac.mac;

   interface signal = pcs.signal;
   interface mmcm = pcs.mmcm;
   interface AxiethbviMgt mgt;
      method clk_clk_p = pcs.gtrefclk.p;
      method clk_clk_n = pcs.gtrefclk.n;
   endinterface
   interface AxiethbviSfp sfp;
      method txp = pcs.txp;
      method txn = pcs.txn;
      method rxp = pcs.rxp;
      method rxn = pcs.rxn;
   endinterface
endmodule


Paxos: simplify defaultValue

Paxos: simplify defaultValue