Jump to content

Any generic method in UVM to find the packet length of incoming packets?


Recommended Posts

Hello all,

I am receiving serial bits in the monitor from DUT. This is RX path and independent from TX path i.e driver path. Then I have to make parallel data out of it using sipo(serial in parallel out) and then I have to decode the data to form the packet from the decoded bytes. In order to receive the all the bits of all the packets in RX path(monitor class), I have to give packet_length inside the for loop. Right now in order to check he functionality of monitor (in loop back mode), I am sending only one packet(8 bytes) so I know the number of bits, which I can use for packet_length parameter. But I want to make it generic because in real world I wont know how many packets might be coming.

 

So the issue is, Is there any generic way in UVM to calculate the number of bytes(OR serial bits) coming into monitor? Is there any uvm method by which I can find this packet_length in a generic way?

 

 

Packet structure is shown below:


 class transaction extends uvm_sequence_item; 
           rand bit [7:0] sync;
           rand bit [7:0] sof;  
           rand bit [15:0] header; 
           rand bit [7:0] payload[]; 
           rand bit [15:0] crc;
           rand bit [7:0] eof;
 
 
 constraint data_size_c { payload.size inside { [6 : 6]};}; 
                  .............
                  .............
endclass: transaction
 
 class monitor extends uvm_monitor;
         .....
      virtual task run_phase(uvm_phase phase);
        transaction pkt;         
          forever
             begin
            int pkt_len = 130; //This is in bits,HERE I NEED TO PASS THE CALCULATED LENGTH FROM SOME GENERIC UVM FUNCTION,TO START RECEIVING ALL THE SERIAL BITS.
            
         repeat(3)@(dut_vi.clock); 
         for (int j = 0; j < pkt_len; j++)  
           
            begin
                serialin = dut_vi.data;                                  
                  $display("san14- Display of the serial line serialin %b",serialin);
                  $display("san15- Display of the Serial Line dut_vi.data %b",dut_vi.data);
                 
                  sipo(serialin); 
                 
              end  
              void'(decode(bytes));   
            
              pkt = transaction::type_id::create("pkt1");        
              $display("SM447- Display of the bytes array received after decoding %h",decdrout2);  
              void'(pkt.unpack_bytes(decdrout2));
              uvm_report_info(get_full_name(),"Decoded completely 10bits into 8bits ...",UVM_LOW);
              uvm_report_info(get_full_name(),"Started unpacking of received bytes ...",UVM_LOW); 
           
              pkt.print(); 
              uvm_report_info(get_full_name(),"Completed unpacking of received bytes ...",UVM_LOW);          
                      Montr2Agnt_port.write(pkt);
              
          end 
        
         uvm_report_info(get_full_name(),"Sending received packet from monitor to the Scoreboard ...",UVM_LOW);
        
     endtask: run_phase   
        
           ...........
           ..........
 
endclass: monitor
 
 

 

Any help is appreciated, thanks
Link to post
Share on other sites

There's a system function $bits which returns the size of certain types in bits - but it's not supposed to be used on dynamic data types (see 1800-2012 20.6.2).

 

But in your case, you know that there is 56 bits of fixed data plus 8 bits * the length of the packet, i.e.

 

  (pkt.payload.size) * 8 + 56

 

The neatest solution would be to add a length method to your transaction class.

 

regards

Alan

Link to post
Share on other sites

There's a system function $bits which returns the size of certain types in bits - but it's not supposed to be used on dynamic data types (see 1800-2012 20.6.2).

 

 

regards

Alan

 

There's a difference between a data type and a variable or expression of a certain data type. It's only the type (i.e. typedef) that is not allowed to be dynamic. You can use it on a dynamically sized variable, and in this case, a member of a class.

Link to post
Share on other sites

$bits(object)  would work very well to give you the packet length. I dont believe there is any  restriction on using

dynamic types.

 

In fact, you will find an example of $bits being used on an class  object in page 242 of the recent LRM  (1800-2012).

 

Hope this helps!

 

Loganath

Link to post
Share on other sites

Dear all,

I appreciate the feedback from all of you. I used $bits in the unpack function in the transaction class as shown below in the code:

 

 
class transaction extends uvm_sequence_item;
 
  rand bit [7:0] sync;
  rand bit [7:0] sof;  
  rand bit [15:0] header; 
 
  rand bit [7:0] payload[]; 
  rand bit [15:0] crc;
  rand bit [7:0] eof;
 
 
 constraint data_size_c { payload.size inside { [6 : 6]};}; 
 
 
`uvm_object_utils_begin(transaction)
     
      `uvm_field_int(sync, UVM_ALL_ON|UVM_NOPACK)
      `uvm_field_int(sof, UVM_ALL_ON|UVM_NOPACK)
      `uvm_field_int(header, UVM_ALL_ON|UVM_NOPACK)
      `uvm_field_array_int(payload, UVM_ALL_ON|UVM_NOPACK)
      `uvm_field_int(crc, UVM_ALL_ON|UVM_NOPACK)
      `uvm_field_int(eof, UVM_ALL_ON|UVM_NOPACK)
     
   `uvm_object_utils_end 
 
 
    function void do_pack(uvm_packer packer); 
      int i;
     super.do_pack(packer);
     
    packer.pack_field_int(sync,$bits(sync)); 
    packer.pack_field_int(sof,$bits(sof));
    packer.pack_field_int(header,$bits(header));
  
     foreach(payload[i])  
         packer.pack_field_int(payload[i],8);  
       packer.pack_field_int(crc,$bits(crc));
       packer.pack_field_int(eof,$bits(eof));       
    endfunction : do_pack  
 
   function void do_unpack(uvm_packer packer); //The unpack methods extract property values from an array of bits,bytes or ints.
      int i;         //The do_unpack method is the user-definable hook called by the unpack method.
       int unsigned packet_size_in_bytes, payload_size_in_bytes; 
        super.do_unpack(packer); 
        sync = packer.unpack_field_int($bits(sync));
       sof = packer.unpack_field_int($bits(sof));
       header = packer.unpack_field_int($bits(header));  
       
       packet_size_in_bytes = packer.get_packed_size() / $bits(byte);   // get_packed_size returns the number of bits that were packed.
       payload_size_in_bytes = packet_size_in_bytes -(($bits(sync) + $bits(sof) + $bits(header) + $bits(crc) + $bits(eof)) / $bits(byte) );
 
      $display("san999- Display of the packet size %h",packet_size_in_bytes); 
       pkt_len = packet_size_in_bytes * 10;   // CAN I PASS THIS VARIABLE  pkt_len  TO MONITOR CLASS AND GET IT'S VALUE EVEN BEFORE THE SERIAL BITS ARE ACTUALLY BEING RECEIVED?
       $display("san996- Display of the packet length in bits %h",pkt_len); 
 
        payload = new [payload_size_in_bytes];
       foreach (payload[i]) //`uvm_unpack_int(payload[i])  
         //  payload = new[sz];       
         //   for ( i=0; i<sz; i++) 
       payload[i] = packer.unpack_field_int(8); //8 less than or equal to 64 bits
   
 
       $display("san995-tran- Display of the payload contents %h",payload.size()); 
       $display("san998-tran- Display of the payload contents %h",payload_size_in_bytes); 
              
       crc = packer.unpack_field_int($bits(crc));
       eof = packer.unpack_field_int($bits(eof));       
   endfunction : do_unpack 
endclass:transaction
 
class monitor extends uvm_monitor;
         .....
      virtual task run_phase(uvm_phase phase);
        transaction pkt;         
          forever
             begin
            int pkt_len = 130; //This is in bits,HERE I NEED TO PASS THE CALCULATED LENGTH FROM SOME GENERIC UVM FUNCTION,TO START RECEIVING ALL THE SERIAL BITS.
            
         repeat(3)@(dut_vi.clock); 
         for (int j = 0; j < pkt_len; j++)  
           
            begin
                serialin = dut_vi.data;                                  
                  $display("san14- Display of the serial line serialin %b",serialin);
                  $display("san15- Display of the Serial Line dut_vi.data %b",dut_vi.data);
                 
                  sipo(serialin); 
                 
              end  
              void'(decode(bytes));   
            
              pkt = transaction::type_id::create("pkt1");        
              $display("SM447- Display of the bytes array received after decoding %h",decdrout2);  
              void'(pkt.unpack_bytes(decdrout2));
              uvm_report_info(get_full_name(),"Decoded completely 10bits into 8bits ...",UVM_LOW);
              uvm_report_info(get_full_name(),"Started unpacking of received bytes ...",UVM_LOW); 
           
              pkt.print(); 
              uvm_report_info(get_full_name(),"Completed unpacking of received bytes ...",UVM_LOW);          
                      Montr2Agnt_port.write(pkt);
              
          end 
        
         uvm_report_info(get_full_name(),"Sending received packet from monitor to the Scoreboard ...",UVM_LOW);
        
     endtask: run_phase   
        
           ...........
           ..........
 
endclass: monitor
 

 

 CAN I PASS THIS VARIABLE  pkt_len  TO MONITOR CLASS IN THAT FORLOOP AND GET IT'S VALUE EVEN BEFORE THE SERIAL BITS ARE ACTUALLY BEING RECEIVED? BECAUSE UNPACK FUNCTION WILL GET THE PACKET LENGTH AFTER DECODE FUNCTION. AND THE pkt_len  VARIABLE COMES EARLY IN THE CODE. IF I CAN PASS, THEN HOW IS IT DONE?  PLEASE GIVE SOME GUIDANCE ON THIS. I APPRECIATE YOUR HELP, THANKS

Link to post
Share on other sites
  • 2 weeks later...

hello all,


Can I get to know the packet length from a Packing function(i.e. do_pack), like by using get_packed_size() method in do_pack function? So that I would know the packet length up in advance even before I receive that packet in monitor. Can this be done?


please give some feedback, would appreciate it.


Thanks,

Link to post
Share on other sites

Can't you detect SOF and EOF from the serial input that you're monitoring?  Wouldn't that be a more reliable way to collect your packets instead of knowing the packet length ahead of time, and drive a fixed loop with that?  How can you know the packet length before you even start collecting the packet in the monitor?  I don't get it.

 

I would also add the pkt_len variable to the transaction class, and let do_unpack determine the length and save it to the variable in the transaction.  That way, the length is always coupled with the packet it belongs to.  Anyone else interested in a packet's length can do a simple query or get to obtain the value.  I'm not sure it really makes much sense to store SOF and EOF in the transaction.

 

I would imagine that whatever your serial bitstream is that the SOF and EOF are encoded, so you can set up a state machine in your monitor to detect the packet boundaries.  Otherwise, I just don't understand how you can realistically determine where packets begin and end from a random stream of bits.

 

Does any of this make sense?  Or, have I completely misunderstood what you are trying to do?

Link to post
Share on other sites

Hello mea1201, 

Yea, what you are saying makes sense. But I want to know that, in the end, the packets are travelling as an object to the monitor and I can get the packet length when I pack the packet bytes in do_pack function (in transaction class itself). So I know whats the length of the packet before even I send the packet to driver/ monitor. So in this way, I will have packet length for each and every packet beforehand, even before I send it across. So can this not be done, if I happen to pass the Variable in which I stored that packet length, through a package, to the monitor? This is my question? I hope whatever I am saying is understandable. Can this be done? Please throw some light. I appreciate your feedback.

Link to post
Share on other sites
  • 2 weeks later...

The answer to the question is a question "How does your hardware determine the packet length?"

 

Once you know that, you can implement the same logic in your monitor.

 

It will be either so interface signaling the start and end of packet. Or some common header format. If it's the latter, you'll need a base class for your packet that can decode the common header (both for the length and to determine the actual packet type).

Link to post
Share on other sites
  • 2 weeks later...

To swapnilm,

 

I'm not sure to understand what you need. My suggestion is add a pkt_len member variable to the class transaction, and constrain the pkt_len {8..1000}, then constrain the  payload.size() == pkt_len - 8. If you can get the item directly, you will get the length just by the varialbe pkt_len. If you need to get the item by the monitor, this variable pkt_len doesn't work, you need get the infomation by pack the transaction, or just count the cycle of the transaction.

 

Best regards

Link to post
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...