Gotcha: SystemVerilog’s post_randomize() is Called Top-Down Not Bottom-Up

SystemVerilog classes contain the pre-defined function post_randomize(), which is automatically called at the end of the randomization. One can override this function to do extra processing after randomization.

In SystemVerilog post_randomize() is called top-down and not bottom-up!

The top-down call of post_randomize() is counter-intuitive, especially for those of you in love with e-Language, and it can cause problems that require extra debug effort.

Let’s consider for the sake of the example that we have a simple packet made of a header, 8 bytes of data and a CRC. The header has its own CRC.

Both Header’s and Packet’s CRCs are computed once randomization is finished:

class header;
  //random info
  rand byte header_info[2];
   
  //crc calculated based on the generated data
  byte header_crc;
  ...
  function void post_randomize();
    header_crc = compute_header_crc();
    $display("header: calling post_randomize() - CRC is: %X", header_crc);
  endfunction
endclass

class packet;
  rand header header_i;
	
  rand byte data[8];
   
  // crc calculated based on the generated header
  byte packet_crc;
  ...
  function void post_randomize();
    // At this point the header is randomized, but its CRC ia not computed yet
    packet_crc = compute_packet_crc();
    $display("packet: calling post_randomize() - header_i.CRC is: %X", header_i.header_crc);
  endfunction
endclass

The issue in the code snippet above is: header_crc isn’t available at the time packet_crc is computed since packet.post_randomize() is called before header.post_randomize(). packet_crc will be computed using the default value of header_crc which is 8’h00.
Here is the output:

OUTPUT:
packet: calling post_randomize() - header_i.CRC is: 00
header: calling post_randomize() - CRC is: 8e

Take care e-Language speakers!!!


Comments

Hamilton February 27th, 2015 05:58:07

Hi Christian!

I’m trying to work out the inheritance and calling scheme here. Is every class in SystemVerilog inherited from a common base class that contains the post_randomize() method? Is this something the factory does? What are the mechanics behind the behaivor?


    Cristian Slav March 2nd, 2015 15:00:03

    Hi Hamilton!

    post_randomize() is a build-in function existing in any SystemVerilog class. Here is a snippet from SystemVerilog LRM:

    Every class contains built-in pre_randomize() and post_randomize() functions, that are automatically called by randomize() before and after computing new random values.

    This behavior is explained by the LRM:

    After the new random values are computed and assigned, randomize() invokes post_randomize() on obj and also all of its random object members that are enabled.

    Is this answering your question?

    Cristi


Hamilton April 2nd, 2015 16:54:17

Hi Cristi,

Thanks! It’s a messy implementation, but it makes sense.


Graeme July 26th, 2017 16:39:21

So what is the solution ???
If you need the header CRC to be correctly generated and put into the packet ….what do you have to do ?


    Stefan Birman July 26th, 2017 23:37:37

    Hi!
    The solution would be to explicitly call header.compute_header_crc() just before the call of compute_packet_crc() in packet’s post_randomize() method.

    Stefan


kidphat January 3rd, 2019 21:34:11

P.S. You can call functions within constraints, so you can make “byte header_crc;” into “rand byte header_crc;”. Then construct a constraint:

constraint c_header_crc {
header_crc == compute_crc( header_info );
}

You can get even fancier and compute the packet CRC as well in the constraint.


Sreekanth January 19th, 2019 22:27:39

Whether adding super.post_randomize() will work as shown below?

class packet;
  rand header header_i;
	
  rand byte data[8];
   
  // crc calculated based on the generated header
  byte packet_crc;
  ...
  function void post_randomize();
     super.post_randomize();
    // At this point the header is randomized, but its CRC ia not computed yet
    packet_crc = compute_packet_crc();
    $display("packet: calling post_randomize() - header_i.CRC is: %X", header_i.header_crc);
  endfunction
endclass

    Aurelian Ionel Munteanu January 25th, 2019 08:06:25

    I don’t understand your question. But looking at your code the class packet has no parent (it does not extend another class). Thus, calling super.post_randomize() should trigger an error since there is no super class.


Leave a Comment:

Your comment will be visible after approval.

(will not be published)

This site uses Akismet to reduce spam. Learn how your comment data is processed.