Quantcast
Channel: UVM SystemVerilog Discussions Forum RSS Feed
Viewing all articles
Browse latest Browse all 410

proper layering in an ethernet transaction class

$
0
0

I am creating an "Ethernet packet" class, extended from uvm_seq_item.  My first implementation was to include of course the Ethernet header, and then a polymorphic base class which holds all the data following the Ethernet header.  In this case, it could be either an ARP datagram, or an IP packet.  ("mydata" in the following code)

class eth_pkt_txn extends my_base_seq_item;
  `uvm_object_utils(eth_pkt_txn);

  const string report_id = "eth_pkt_txn";

  // Ethernet header
  rand bit [47:0]  SrcMAC;
  rand bit [47:0]  DstMAC;
  rand enum bit [15:0] { ARP=16'h0806, IP=16'h0800 } EthType;

  // Ethernet data
  my_base_seq_item mydata;

So when this class is randomized, EthType randomly chooses either ARP, or IP, and then in post_randomize(), the child object is created, and the handle assigned to the base (mydata) handle:

  function void post_randomize();

    if (EthType==ARP) begin
      mydata = ARP_data::type_id::create("mydata"); // assign an ARP child to base class
    end else if (EthType==IP) begin
      mydata = IP_pkt::type_id::create("mydata"); // assign an IP_ESAP child to base class
    ...

This works just fine.  This layered approach could continue inside the IP packet again, as you might have TCP, UDP, etc.

 

The layering is a powerful feature, but at the same time, it seems to make the transaction class harder to create, and modify, either manually or during randomization.

 

For example, say I want to do a randomize with {...} in my virtual sequence, the simulator can't find "mydata.IP_packet".  

if(!EthPkt.randomize() with {EthType == IP; mydata.IP_packet.IP_header.SrcIPaddr==4; }) `uvm_fatal(report_id,"EthPkt randomize() failed!")

It's not a member of the polymorphic base from which the children extend, so I wouldn't expect it to.  At the same time, I want to be able to quickly randomize and create a particular kind of packet.

 

In addition, method calls which are particular to a child class which are down in the class hierarchy (e.g. updateUDPchecksum() ) have to be accessed only by tunneling in through the heirarchy (cumbersome). 

 

Any thoughts on the best way to do this, and still have a convenient transaction class?  Should I forget about layering it and just have handles for everything I need at the top level of the transaction class?


Viewing all articles
Browse latest Browse all 410

Trending Articles