Calling randomize() from a sequence

Hi,
The structure of my environment looks like this

tbEnv> ovcEnv

ovcagent

ovcseqr

ovcdriver

ovcmonitor

tbcfg

seq1

In the run() of tbEnv class, the sequence seq1 has been started.

A pointer of the class tbEnv (tbEnvPtr) has been passed to tbcfg and seq1.

The class tbcfg has a variable declared as follows
rand bit [15:0] x;
constraint con_x {x inside {[1:10]};}

In the sequence “seq1” the following code is present in body().
tbEnvPtr.tbcfg.randomize(x);
$display(“value of x :”,tbEnvPtr.tbcfg.x);

When I run my testcase, I find that the displayed value of x is 0 which is outside the constrained range. No other constraint on x is present.

Kindly point out what might be going wrong.

Regards,
Sujit

Check the return value of randomize() call, if it was 0 - then there was some problem with randomization. Other (little unlikely, given the simple constraint) is a bug in tool. Can you mimic this in a smaller case such as:

class tbcfg;
  rand bit [15:0] x;
  constraint con_x {x inside {[1:10]};}
endclass

Srini
www.cvcblr.com

Hi,
the randomize method call is returning 0. Can I get some documentation on under what conditions it returns 0. Can it be because of the back pointers that I am using?
Regards,
Sujit

Hi,
the randomize method call is returning 0. Can I get some documentation on under what conditions it returns 0. Can it be because of the back pointers that I am using?
Regards,
Sujit

Sujit,
It is documented in LRM, books and maybe even VCS/Questa tutorials. Basically the randomize() is a function that returns status as 1/0. 0 - failure. Your tool should have reported a warn/error. In a good methodology it is recommended to route that through messaging component (ovm_report/vmm_warn etc.).

Now to the cause - it is unlikely to do with back pointers. Are you sure there are no additional constraints? Can you trace the generation? Depending on the tool you use there are features to trace the generation.

Srini
www.cvcblr.com

Hi Sujit,

I am not 100% whether randomize() will work for a single variable. I have always seen randomize method to act on an object of a class, in which we keep random constraints for correct values.

I agree that LRM gives one example to randomize a struct outside class but it uses inline values as well.

What I would suggest is you can simply you $urandom_range(). As you have one single variable to randomize within a valid range, this function is perfectly suitable.

Ashish

Sujit,
Ashish has good/better eyes :-) I believe the extra argument to object.randomize() is causing the issue (in the absence constraint violation). Try removing the (x) from

// Instead of this: 
// tbcfg.randomize(x);
// Try
tbcfg.randomize();

The $urandom_range is also a possible solution but is not as flexible as the constraint block based one as the inheritance feature shall be lost. Depends on the requirements…

Cheers
Srini
www.cvcblr.com

Hi Ashis, Srini,
Removing the argument to randomize worked :) . Thanks for the suggestion.
But my aim is to randomize a particular variable, not all. Is there any way to achieve this? urandom doesnot seem to be adequate for me.

Regards,
Sujit

Hi Ashis, Srini,
Removing the argument to randomize worked :) . Thanks for the suggestion.
But my aim is to randomize a particular variable, not all. Is there any way to achieve this? urandom doesnot seem to be adequate for me.
Regards,
Sujit

You should be using std::randomize(), look for “Scope variable randomization” in LRM. Not sure why $urandom_range is not sufficient? Do you want powerful constraints on that variable?

Srini, CVC
www.cvcblr.com

Hi Srini,
I will have a look at “Scope variable randomization” .
can I use $urandom_range to specify something like , “I want the value of x to be inside {1,2,4,5,7}”.
Also I need weighted constraints (dist) on the variable.

Regards,
Sujit

Hi,
I tried using std::randomize().
code:
randomize(tbEnvPtr.tbcfg.x);

I am getting the following error.
error : Argument for randomize() function must be a field of ‘this’

Does this means that I cannot randomize a variable of a class from another class?
Is there any way in sys verilog where we can randomize a particular variable (not all at a time) of a class from another class by using the dot operator?

Regards,
Sujit

Hi,
I tried using std::randomize().
code:
randomize(tbEnvPtr.tbcfg.x);
I am getting the following error.
error : Argument for randomize() function must be a field of ‘this’
Does this means that I cannot randomize a variable of a class from another class?
Is there any way in sys verilog where we can randomize a particular variable (not all at a time) of a class from another class by using the dot operator?
Regards,
Sujit

Hi Sujit,I’m afraid that there is no direct way to do so.
Although you can try following code. I’m not sure whether it would work or not (I am not having a SystemVerilog tool to test it) but theoretically it should work.

class tbcfg;
  rand bit [15:0] x;
  constraint con_x {x inside {[1:10]};}
  rand int y;
  constraint con_y {/* Some constraint*/}
endclass

In your sequence, you can do something similar to:

//Turn off randomization of all variables in the object
tbEnvPtr.tbcfg.rand_mode(0);
//Enable randomization of desired variable
tbEnvPtr.tbcfg.x.rand_mode(1);
//Randomize the whole object (though only x should get randomized)
tbEnvPtr.tbcfg.randomize();
//Don't forget to turn ON what you turned OFF
tbEnvPtr.tbcfg.rand_mode(1);

Do let me know if this works (I’ve never tried this before ;))
Cheers,

Farhan

Sujit,
Instead you can write some local function which will randomize the particular element of your interest. And you can call that function where ever you want and use as per the requirement.

Hi,
I tried what Farhan suggested. It doesnot work. randomization fails if the rand_mode of the class is 0 and that of a particular variable is 1.

It is ridiculous that system verilog doesnot support such a simple thing. I dont know how verification engineers are working with such limitations. May be people who are ignorant of other verification languages such as “e” are praising sys verilog. Complete control over randomization is what is expected from a verification language.

I call upon all system verilog experts to have a look at this problem.

Regards,
Sujit

LRM 2009 draft in section 18.8 does show an example very close to that of yours and is supposed to work. In one of the tools I tried I didn’t get any failure. though “y” was also randomized. I would recommend you contact your vendor.

Srini
www.cvcblr.com

After a brief discussion with Mentor support it turns out Questa indeed does the correct thing. My previous trial didn’t work b’cos I had tbEnv declaring rand tbcfg tbcfg;. If we do that then the following LRM clause applies:

If the random variable is an object handle, only the mode of the variable is changed, not the mode of random variables within that object (see global constraints in 18.5.8).

I got your scenario running with the following code. Try it out in your tool, it works fine in Questa.

class tbcfg;
  rand bit [15:0] x;
  constraint con_x {x inside {[1:10]};}
  rand int y;
  constraint con_y {/* Some constraint*/}
  function void display();
    $display ("x %0d y %0d ", x,y);
  endfunction

endclass
class tbenv;
  tbcfg tbcfg;

endclass : tbenv

program p;

  tbenv tbEnvPtr;

  initial begin : test
    tbEnvPtr = new();
    tbEnvPtr.tbcfg = new();
    //Turn off randomization of all variables in the object
    tbEnvPtr.tbcfg.rand_mode(0);
    //Enable randomization of desired variable
    tbEnvPtr.tbcfg.x.rand_mode(1);
     tbEnvPtr.tbcfg.display();
    //Randomize the whole object (though only x should get randomized)
    tbEnvPtr.tbcfg.randomize();
     tbEnvPtr.tbcfg.display();
    //Don't forget to turn ON what you turned OFF
    tbEnvPtr.tbcfg.rand_mode(1);

  end : test

endprogram : p

Regards
Srini
www.cvcblr.com
P.S. Due credits are to excellent Mentor support who turned this query around in short time!

Hi Srini,
What you have done extra is, you have called new() on the tbEnvPtr.
In that case you are creating an object. It is no more a pointer.
Now say I have 2 sequences. I want to generate a variable in one seq and use it in the other. If I use your method, I will not be accessing the same variable when I say tbEnvPtr.tbCfg.x in seq1 and tbEnvPtr.tbCfg.x in seq 2 since tbEnvPtr is no nore a pointer now. It is an object inside the respective sequence. Am I right?
Regards,
Sujit

Sujit,
You better post your code if you need precise assistance. As far as I understand the LRM it has nothing to do with object vs. pointer in this issue, rather the scope of “rand_mode” effect. It should behave well in both pointer and object.

Show us your full/sample code and demo the problem (if there is one).

Warm Regards,
Srini
www.cvcblr.com

Hi,
I tried what Farhan suggested. It doesnot work. randomization fails if the rand_mode of the class is 0 and that of a particular variable is 1.
It is ridiculous that system verilog doesnot support such a simple thing. I dont know how verification engineers are working with such limitations. May be people who are ignorant of other verification languages such as “e” are praising sys verilog. Complete control over randomization is what is expected from a verification language.
I call upon all systemverilog experts to have a look at this problem.
Regards,
Sujit

Sujit,

Please do not take this the wrong way, but the problem is that you have not taken the time to study SystemVerilog and you are trying to randomize using an ‘e’ methodology, You need to understand how constraints are associated with whole classes, not individual variables, and under what conditions the call to randomize returns 0, even if no variables are randomized.

In your call

randomize(tbEnvPtr.tbcfg.x);

you are not calling **std::**randomize() because you haven’t prefixed it with std::. Instead you are implicitly calling *this.*randomize()

If instead you called

std::randomize(tbEnvPtr.tbcfg.x);

Then the single variable x would be randomized. However, there would be no constraints on the variable unless you used the randomize() with clause, since the class constraints are not used with with std::randomize.

What you probably should do is re-organize your class objects into groups that can be randomized as individual objects, not as individual variables. That way you can group the variables with the constraints that need to be inter-related.

Dave Rich

Hi Dave,
Thanks for your suggestons. I know that this can be achieved by grouping the variables. But it just complicates the environment. I have been working in this field for the past 5 years. I feel that randomizing individual variables give more flexibility to the verification engineer. Perhaps the designers of system verilog were not foreseeing enough to see this. May be they can look into other languages and take in the good features.

Section 12.10 (In-line random variable control ) in the LRM seems to suggest that we can pass arguments to randomize() to specify the particular variable you want to randomize. Could you please comment on this?

Regards,
Sujit

Sujit,

I agree that randomizing individual variables give more flexibility to the verification engineer, but that in itself does not mean it’s a good thing to do. It would be a good idea to take a step back from the individual language features and get a better idea of what you are trying to do.

In any case, let me explain in-line random variable control. When you call the randomize method of a class (not std::randomize), you can provide a list of class properties that will be treated as random variables for that call. This is equivalent to pushing the current rand_mode() of each class property on a stack, turningon the rand_mode() of all class properties that appear in the list, and turning off the the rand_mode() of all class properties that do not appear in the list. After the call to randomize() the rand_mode() of each class property is restored by popping them off the stack. Like any other call to randomize(), the constraint solver will try to meet all of the constraints that are currently enabled for that class.

You also have the ability to call randomize(null). In this case, the rand_mode() of all class properties are turned off and the call will return true if the current state of all class properties are within the active constraints.

When you provide a list of random variables to the randomize() method, that list must only contain class properties of the object implicitly pointed to by this. The list cannot contain variables outside that object.

When you call std::randomize(), you are not calling a method of a class, you are calling a built-in function. The list of variables can now point to any variable that is legal as a random variable. (e.g. a real variables would not be allowed). Unless on of the variables in the list is a class object, there are no constraints associated with any variable on the list. The only way to add constraints is using the with clause.

For example

class A;
  rand bit [7:0] x=2;
  rand bit [7:0] y=11; 
  constraint C1 {y inside {[1:10]};}
  constraint C2 {x < y;}
endclass

module top;
A a1,a2;
initial begin
  a1 = new();
  a2 = new();
  assert(a1.randomize(y)); // x=2(unchanged state), y=3-10 (random)
  assert(std::randomize(a2.x,a1.y) with {a2.x > 0; a1.y < a2.y ; }<a2.y;}>);
  //Constraints C1 and C2 do not apply
  // a1.x = 2 (unchanged state variable)
  // a1.y = 0-10 
  // a2.x = 1-255
  // a2.y = 11(unchanged state variable)
end
endmodule

Hope this helps,

Dave Rich