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!!!
8 Responses
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?
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
Hi Cristi,
Thanks! It’s a messy implementation, but it makes sense.
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 ?
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
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.
Whether adding super.post_randomize() will work as shown below?
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.