Pre/post randomze behavior in randomize(null)

Hi all,
I’ve an issue on how SV checks the constraint.

To be sure that my values meet the constraint I usually call

randomize(null);

But I’ve found that SV calls pre_ and post_ randomize() also in this case.


class randomize_proof;
	rand int val;
	constraint c_val {val inside {[0:100]}; };

	// function_description
	function void pre_randomize();
		$display("pre_rand \n",val);
	endfunction : pre_randomize
	function void post_randomize();
		$display("post_rand \n",val);
	endfunction : post_randomize
endclass : randomize_proof

module top_dp;
	initial begin
		randomize_proof rp;
		rp = new;
		assert(rp.randomize());
		assert(rp.randomize(null));
	end
endmodule

output

pre_rand

0

post_rand

9

pre_rand

9

post_rand

9

As workaround I was thinking to use some flags and check those in pre and post, but this solution becomes really ugly when trying to work with 3rd party library.
Do you know if there is a better way to check the constraint without trigger this issue ?

Thanks
Cisco

There is no direct way to influence whether pre_ and post_ are called. That’s a good thing in most situations - even for constraint checking - because pre_randomize() is typically used to set up some structural requirement for the constraints to be valid, and post_randomize is typically used to perform some final validity check.

If post_randomize has side-effects, though, I can see that you may want to disable it.
The only other method I can think of is to extend the class, declare empty pre_ and post_randomize, and use a handle of that type for your constraint check:

class randomize_proof_noprepost extends randomize_proof;
  function void pre_randomize(); endfunction
  function void post_randomize(); endfunction
endclass

note: post_randomize is never called if the constraint FAILS.

Methodology advice: pre_randomize() and post_randomize() are very rarely needed and should do only what is necessary to maintain the constraints. Wanting to disable them may be a symptom that they are doing something with side effects that may better be done after/outside the randomize() call altogether.

In reply to gordon:

BTW, you probably want to add a flag so that the same object can be used for both. Hopefully your 3rd party library is set up to use the factory.


class randomize_proof_prepost extends randomize_proof;
  enum bit {ENABLE, DISABLE} prepost = ENABLE;
  function void pre_randomize(); 
    if (prepost == ENABLE) super.pre_randomize();
  endfunction
   function void post_randomize(); 
    if (prepost == ENABLE) super.post_randomize();
  endfunction
endclass

module top_dp;
	initial begin
		randomize_proof_prepost rp;
		rp = new;
		assert(rp.randomize());
                rp.prepost = DISABLE;
		assert(rp.randomize(null));
                rp.prepost = ENABLE;
	end
endmodule

In reply to dave_59:

Thanks.
I was thinking to implement your solution but, as I said, I think is really “ugly” to do this for each and every affected class.
The library at the moment, in post_randomize(), randomizes the payload of the transaction. Do you think it is a good practice ?

Thanks
Cisco

In reply to ciscer01:

Ideally, if you were the one writing the randomized classes, you could enforce a pre_post randomize policy that would allow them to work together with randomize(null). But since that is not the case, you are left with what you have.

All of the pre_/post_ methods throughout SystemVerilog and the UVM make things quick and easy for the initial test developer, but in the long run are much less manageable.