Problem with Using do_pack and do_unpack

Hi All,

I am stuck with do_pack and do_unpack, I want to pack the objects fields into bytes and bits. But I am unable to find out a good example on this in UserGuides. Please someone help out by providing one good example for packing and unpacking using OVM.

Thanks in Advance,
Maverick

Hi maverick,

There is no need to implement do_pack and do_unpack. You can use the automation macros to implement the pack/unpack automatically. Here is an example of how to use the automation macros and how to call the pack/unpack methods.

Transaction definition with automation macros:

typedef enum bit { BAD_PARITY, GOOD_PARITY } parity_e;

class yapp_packet extends ovm_sequence_item;

// Packet Structure
   rand bit [5:0] length;
   rand bit [1:0] addr;
   rand bit [7:0] payload[];   
   bit [7:0] parity;          // calculated in post_randomize()

// Control Knobs
   rand parity_e parity_type;
   rand int packet_delay;

// Default Constraints
   constraint default_length { length > 0; length < 64; }
   constraint payload_size   { length == payload.size(); }
   constraint default_delay  { packet_delay  >= 0; packet_delay < 20;}  

   `ovm_object_utils_begin(yapp_packet)
     `ovm_field_int(length, OVM_ALL_ON | OVM_UNSIGNED )
     `ovm_field_int(addr, OVM_ALL_ON)
     `ovm_field_array_int(payload, OVM_ALL_ON)  
     `ovm_field_int(parity, OVM_ALL_ON)
     `ovm_field_enum(parity_e, parity_type,  OVM_ALL_ON | OVM_NOCOMPARE | OVM_NOPACK)
     `ovm_field_int(packet_delay, OVM_ALL_ON | OVM_DEC  | OVM_NOCOMPARE  | OVM_NOPACK)
   `ovm_object_utils_end

   function new(string name="yapp_packet");
      super.new(name);
   endfunction 
   
endclass : yapp_packet

Here is the code example of how to call pack/unpack; note that I show how to pack/unpack into/from both bit vector and byte stream

module test;
  `include "ovm_macros.svh"
  import ovm_pkg::*;

  `include "yapp_packet.sv"
   
yapp_packet packet;
yapp_packet copy_packet;
yapp_packet clone_packet;

   yapp_packet unpacked_packet1, unpacked_packet2;

   byte unsigned us_packed_packet[];
   
   bit  bit_packed_packet[]; int bv_size; int byte_size;
   
   
string name;

initial begin
  copy_packet = new("copy");
  for (int i=0; i<1; i++)  
  begin
     packet = new($psprintf("packet_%0d", i));
     assert(packet.randomize());
     packet.print();
     
     // copy usage
     copy_packet.copy(packet);
     copy_packet.print();
     // clone usage
     $cast(clone_packet, packet.clone()); 
     // rename the cloned packet
     clone_packet.set_name("cloned_packet");
     clone_packet.print(ovm_default_tree_printer);
  end
   
   //PH> Test built-in pack()
   bv_size= clone_packet.pack(bit_packed_packet);
   $display("bv_size= %0d", bv_size);
   
   for(int i=0; i<bit_packed_packet.size(); i++)="" begin=""><bit_packed_packet.size(); i++)="" begin="">
      $display("PH>>>>> bit[%0d]=           %b", i, bit_packed_packet[i]);
   end
   //
   $display("\n\nPH>------- Now pack into bytestream...");
   byte_size= clone_packet.pack_bytes(us_packed_packet);
   $display("byte_size= %0d", byte_size);
   for(int i=0; i<us_packed_packet.size(); i++)="" begin=""><us_packed_packet.size(); i++)="" begin="">
      $display("PH>>>>> Byte[%0d]=           %0h",i,us_packed_packet[i]);
   end

   // Now, unpacking from bit stream...
   unpacked_packet1 = new("unpacked_packet1");
   unpacked_packet1.payload = new[56];
   void'(unpacked_packet1.unpack(bit_packed_packet));
   unpacked_packet1.print();
   
   // Now, unpacking from byte stream...   
   unpacked_packet2 = new("unpacked_packet2");
   unpacked_packet2.payload = new[56];
   void'(unpacked_packet2.unpack_bytes(us_packed_packet));
   unpacked_packet2.print();
   
end

endmodule : test

</us_packed_packet.size();></us_packed_packet.size();></bit_packed_packet.size();></bit_packed_packet.size();>

HI phuynh,

When you are packing/unpacking an object which contains more than 4096 bits the inbuilt ovm pack/unpack won’t work. If Packing/Unpacking results in more than 4096 bit you need to write your own packing and unpacking function.

Thank you Phuynh and Prashanth. I will try and I will get back to you.

Regards,
Maverick

Hi Prashanth,
You are correct about the current limitation of 4096 bits for packing/unpacking. This limitation will be “removed” in the OVM-2.0.3.

Hi Phuynh ,
is there any option for us to pack only physical fields. And I would also like to know the order in which the fields are packed (will they packed in the order we have declared in our class)?

      When OVM 2.0.3 is going to be released?

Thanks in Advance.

Best Regards,
Maverick

is there any option for us to pack only physical fields

There is no such option to tell only pack physical fields.

I would also like to know the order in which the fields are packed

Case1) If you use field macros for packing operation it will packed in the order you declared the field_macros.
For example:
int y;
int x;

ovm_object_utils_begin(trasns) ovm_field_int(x, OVM_PACK)
ovm_field_int(y,OVM_PACK) ovm_object_utils_end

In the above case first macro for x is declared and next macro for y is declared. So it will pack first x and y next.

Case2) If you have user defined pack function which are do_pack/do_unpack functions, it will pack in the order specified in do_pack/do_unpack functions.

Hi all,

I want to post here my problem because it’s related to do_pack function!

I was expecting to call the do_pack function and then i should have been able to get the packed bits out of a function or a field, but i could not do that unless i call a specific function (set_packed_size()) from ovm_packer class. That function refreshes the field m_packed_size with the count value and resets the count! I guess you people know better then me the internals of OVM :)

Is this a bug, or is it the default behaviour i should implement every time when using do_pack?

module do_pack;
    
    //`include "ovm.svh";
    import ovm_pkg::*;
`include "ovm_macros.svh"
    
    class item2 extends ovm_sequence_item;
        rand bit[0:4] field2;
        rand int my_int;
        
        function new(string name="item2");
            super.new(name);
        endfunction
            
        `ovm_object_utils_begin(item2)
            `ovm_field_int(field2,OVM_ALL_ON)
            `ovm_field_int(my_int,OVM_ALL_ON)
        `ovm_object_utils_end
        function void do_pack(ovm_packer packer);
            super.do_pack(packer);
            packer.pack_field(field2, $bits(field2));
        endfunction
    endclass;
        
    class item3 extends ovm_sequence_item;
        rand bit[0:8] field3;
        rand item2 my_item2;
            
        function new(string name="item3");
            super.new(name);
            my_item2 = new(name);
        endfunction
            
        `ovm_object_utils_begin(item3)
            `ovm_field_int(field3,OVM_ALL_ON)
            `ovm_field_object(my_item2,OVM_ALL_ON)
        `ovm_object_utils_end
            
        function void do_pack(ovm_packer packer);
            super.do_pack(packer);
            packer.pack_field(field3, $bits(field3));
            my_item2.do_pack(packer);
        endfunction : do_pack
    endclass
    
    item3 my_item; 
    bit unsigned bits[];
    
    initial begin
        my_item = new();
        my_item.randomize();
        my_item.print();
        my_item.do_pack(ovm_default_packer);
        ovm_default_packer.set_packed_size();// if this line is missing the get bits will return an empty dynamic array of bits
        ovm_default_packer.get_bits(bits);
        $display("bits=%p",bits);
    end
endmodule

Thanks a lot Vishnu Prashanth…

Best Regards,
Maverivck

Hi Phuynh ,
is there any option for us to pack only physical fields.

Best Regards,
Maverick

In SystemVerilog, there is no “tagging” for the physical fields (like in Specman); so, there is no automatic way to do it. However, if you don’t want to pack the “virtual” fields, you can either leave those out of the `ovm_field_* macros or use the OVM_NOPACK option for these fields (see my code example in previous message, the “virtual” field: parity_type, was specified with the OVM_NOPACK).

Hi Phuynh ,

When OVM 2.0.3 is going to be released?
Thanks in Advance.
Best Regards,
Maverick

OVM 2.0.3 was released yesterday. You can download it now :)

Thanks a lot Phu Huynh…

Best Regards,
Maverick

Hi All,

Now I have one more issue, I am trying to use OVM unpack_bytes macro but I am getting the error as:

ref formal and actual do not have equivalent data types ( expecting datatype compatible with ‘dynamic array of byte’ but found a different ‘dynamic array of byte’ instead).

actually I want to unpack into a pkt type which is inherited from ovm_object.

I am storing all the packed bytes into a dynamic array, now I want to unpack the entire dynamic array into this packet which is inherited from ovm_object.

Thanks in Advance,

Best Regards,
Maverick

I would say that the limitation can be “changed” in 2.0.3. You can globally change the limit using OVM_STREAMBITS, but be be warned of the performance impact because the packer treats every integral field as if it were OVM_STREAMBITS wide.

My suggestion is to use the SystemVerilog strearming operator and bitstream casts to perform packing/unpacking if performance is an issue. Here is the example submitted by aimunteanu re-written using bitstream casts and the streaming operators.

typedef bit bitstream[$];


module do_pack;
    
   import ovm_pkg::*;
`include "ovm_macros.svh"
    
class item2 extends ovm_sequence_item;
   rand bit[0:4] field2;
   rand int my_int;
        
   function new(string name="item2");
      super.new(name);
   endfunction
   
   `ovm_object_utils_begin(item2)
      `ovm_field_int(field2,OVM_ALL_ON)
      `ovm_field_int(my_int,OVM_ALL_ON)
   `ovm_object_utils_end
   virtual function bitstream pack();
      return bitstream'(field2);
   endfunction
endclass;
        
class item3 extends ovm_sequence_item;
   rand bit[0:8] field3;
   rand item2 my_item2;
   
   function new(string name="item3");
      super.new(name);
      my_item2 = new(name);
   endfunction
   
   `ovm_object_utils_begin(item3)
      `ovm_field_int(field3,OVM_ALL_ON)
      `ovm_field_object(my_item2,OVM_ALL_ON)
   `ovm_object_utils_end
   
   function bitstream pack();
      return {>>{field3,my_item2.pack()}};
   endfunction
endclass
    
   item3 my_item; 
   bit        unsigned bits[];
   
   initial begin
      my_item = new();
      my_item.randomize();
      my_item.print();
      bits = my_item.pack();
      $display("bits=%p",bits);
   end
endmodule // do_pack

Hi All,
Now I have one more issue, I am trying to use OVM unpack_bytes macro but I am getting the error as:
ref formal and actual do not have equivalent data types ( expecting datatype compatible with ‘dynamic array of byte’ but found a different ‘dynamic array of byte’ instead).
actually I want to unpack into a pkt type which is inherited from ovm_object.
I am storing all the packed bytes into a dynamic array, now I want to unpack the entire dynamic array into this packet which is inherited from ovm_object.
Thanks in Advance,
Best Regards,
Maverick

Hi Maverick,
My guess is that you unpacked from a “byte array” instead of from a
“byte unsigned array”. unpack_bytes() expects its argument to be a “byte unsigned array”. If you look at my code example in previous message:

...
byte unsigned us_packed_packet[]; 
...
void'(unpacked_packet2.unpack_bytes(us_packed_packet)); 
...

Note that us_packed_packet was declared as “byte unsigned”.

Thank you Phu Huynh,

Now I am trying to print the unpacked packet… but to my surprize the packet is null with out any fields. Could you please tell me where I went wrong.

Best Regards,
Maverick

Thank you Phu Huynh,
Now I am trying to print the unpacked packet… but to my surprize the packet is null with out any fields. Could you please tell me where I went wrong.
Best Regards,
Maverick

Hi Maverick,
You might want to check to see that the unpacked packet was “newed” and has the correct fields. Check the return value of the unpack_bytes() too; it tells you how many bytes were extracted from the array. By the way, the example that I provided in the earlier message is a runnable example that you can play with to get familiar with the pack/unpack methods.

Hi phu yunh,
sorry phu, I have mistakenly written packed instead of writing unpacked… now I have modified it. so with the following code I am getting problem.
unpack is not working for me…I have newed the object but still I am getting the null result and the unpack method returned value is zero. I am unable to figure out the problem.

int pack_int;
packet unpacked;
byte unsigned up ;

unpacked= new();

-------- here i am collecting the packed data into the dynamic array
-------- and printing it successfully
after that I have this line
pack_int = (unpacked.unpack_bytes(up));

when i am printing the unpacked it is showing null.

Please help me out as soon as possible.

Thanks in Advance

Best Regards,
Maverick

Hi phu yunh,
unpack is not working for me…I have newed the object but still I am getting the null result and the unpack method returned value is zero. I am unable to figure out the problem.
int pack_int;
packet packed_packet;
byte unsigned up ;
packed_packet= new();
-------- here i am collecting the packed data into the dynamic array
-------- and printing it successfully
after that I have this line
pack_int = (unpacked.unpack_bytes(up));
when i am printing the unpacked it is showing null.
Please help me out as soon as possible.
Thanks in Advance
Best Regards,
Maverick

Maverick,
Looking at your code above, I didn’t see “unpacked” defined anywhere. Also, make sure that any dynamic array fields in the “unpacked packet” have been allocated before you unpack the byte stream into it; otherwise, there will be no place for those bytes :).
Phu

Hi phu yunh,

I am using OVM 2.0.3. Now I am getting new error. The Dut error I am getting is “Can not unpack into Null object”. I am trying to unpack array of bytes into a class object. I have newed the class object before unpacking into it. I have also used ovm_default_packer.use_metadata = 1. But still I am unable to get clear the error. Please help me out.

Thanks in Advance.

Best Regards,
Maverick