I am trying to generate the following behavior:
ip will randomize with an even distribution from the value of
A
B
zero
all ones
a random number from the full range <------- How do I do this?
[0:]:/1 is incorrect, but I think it helps illustrate my intent. I want something like "inside [0:] := 1",
if(!txn.randomize() with { ip dist { A:=1, B:=1, '0:=1, '1:=1, ??? }; })
In reply to bmorris:
Of course as soon as I hit “submit” I had an idea. I simply added a extra “helper variable” into my txn class:
randc uint32_t rand_ip;
if(!txn.randomize() with { ip dist { A:=1, B:=1, '0:=1, '1:=1, rand_ip:=1 }; })
Please feel free to weigh in, though.
On a side note, the reason I’m adding an in-line distribution is because the VALUES I want to constrain to are in the configuration database (A and B, for examples). If I were to extend my transaction class, it would doing a database access every time I created a transaction. That’s a no-no on performance, or so I’m told. Hence, I add the in-line constraint in the sequence, where I pull the values from the database only once. The reason I mention this, is because I get the sense that I should be leaning towards factory use and class extension, rather than in-line constraints. Thoughts?
In reply to bmorris:
You could also do
parameter type(ip) max_ip = '1;
...
if(!txn.randomize() with { ip dist { A:=1, B:=1, 0:=1, max_ip:=1, [0:max_ip]:/1 }; })
I wouldn’t use randc on such a large value unless there is a specific requirement for it.
I don’t see why extending a class results in extra config_db accesses. You will have to explain further.
In reply to dave_59:
[0:max_ip]:/1
I thought this would attempt to distribute 1 “distribution point” among each of the members of the specified array?
Edit: This appears to work. I assume it successfully divides up the number 1 into (2**32)-1 tiny pieces.
I don’t see why extending a class results in extra config_db accesses. You will have to explain further.
my (madeup) rule: I should not place database accesses into classes of type uvm_sequence_item. Why? If there are several hundreds of them made, then that is lot of database accesses, resulting in an enigmatic quantity of performance degradation. This “rule” of mine might be completely bogus, and if so I would love to hear why. Especially because I would prefer to extend the transaction class!
parameter type(ip) max_ip = '1;
Why use parameters to hardcode this instead of using $?
In reply to bmorris:
I agree if you mean a database access means doing uvm_config_db::get() each time you create a class derived from uvm_sequence_item. What you can do is have the sequence that constructs the items get the configuration object once and pass a handle to that object to the item.
$ not currently allowed in a dist constraint. You have to realize that SystemVerilog was designed by a number of committees, and sometimes features created for one specific purpose do not always make it uniformly across the LRM.
In reply to dave_59:
I agree if you mean a database access means doing uvm_config_db::get() each time you create a class derived from uvm_sequence_item. What you can do is have the sequence that constructs the items get the configuration object once and pass a handle to that object to the item.
Correct. Not a bad idea; I’ll try it out.
$ not currently allowed in a dist constraint. You have to realize that SystemVerilog was designed by a number of committees, and sometimes features created for one specific purpose do not always make it uniformly across the LRM.
It haven’t had any issues using it: $ in a dist constraint - EDA Playground