SystemVerilog Constraints from Above

After reading the title, some of you might be asking yourselves "What are constraints from above?". Constraints from above (CFAs) are an e term. As Reuven Naveh explains in this post on Team Specman's blog, CFAs have the following properties:


This is a companion discussion topic for the original entry at https://verificationgentleman.netlify.app/2014/06/26/systemverilog-constraints-from-above.html

Very nice, Tudor! I’ll keep this trick in mind. I do have one question though. I didn’t understand why you had to call req.set_item_context(this, get_sequencer). Isn’t the context set when the sequence item is sent through the sequencer to the driver? I’ve never set it before and the context always shows up nicely when printed.

Hi, thanks a lot for the nice words!

start_item(req) sets the context of the item, but for some reason, when we do this.randomize(req), a new req is created (although the standard states that randomize() does not create new items). The jury’s still out on this one whether it’s a bug, because this happens on two different simulators. The new item that gets created doesn’t have its context set, so we have to set it again. What we can also do if we don’t need late randomization is:

if (!this.randomize(req)) // creates a new item and assigns it to req
`uvm_error(“RANDERR”, “Randomization error”)
start_item(req); // sets the context of the item
finish_item(req); // waits until the item is finished

I see, makes sense. I probably never ran across this issue before because I rarely randomize an object by passing it as an argument to the randomize function.

Good stuff!

Hi Tudor,

I recently came across your blog, it seems pretty interesting. Keep up the good work!

Just to mention a minor typo mistake in the traffic loop where the `uvm_error should run when the randomize function returns zero. :wink:

Thanks,

Artemios.

Hi, thanks a lot for the kind words! And also thanks for pointing out the typo; it’s fixed now :slight_smile:

Hi Tudor,
your blog is pretty knowledgeable!
Maybe you should name the new item differently. It is a bit confusing to name it ‘req’.

Hi Cedric, thanks for the compliment.

Do you mean it’s confusing because it overrides the ‘req’ field defined in uvm_sequence? It stands for “request”. I chose the term “req” as it is used in multiple places in UVM and I thought it would actually make it clearer.

Exactly, ‘req’ is already the current default item. So override it makes confusion, especially for people not familiar with UVM or using it time-to-time.
By the way, it’s also strange that the overriding declaration does not raise an error at compilation. How does it work behind the scene ?

This is a “feature” of SystemVerilog that not many people know. I stumbled upon it by mistake some years back. If you define the same field in a sub-class that the super-class already has, it will be overridden. I don’t know the exact semantics of what happens in that case (with any code in the super-class that was using this field), but I was thinking of doing a blog post on the topic at some point.

The field “req” is not used at all in uvm_sequence and I liked the name so I overrode it. I’m pretty sure the code would work also without me defining ‘req’ at all, as the call to randomize(req) will force it to be treated as a random field (even though it isn’t tagged as random in uvm_sequence).

And a follow up question from my side: Did you ever use this ‘req’ field up to now? If so, for what exactly? I’m not really sure what it’s supposed to do.

Thank you for the tip (subclass overwrite).
I only use it as the default item to randomize and send the transaction.
That’s why your name choice confused me and I think that for a beginner it is tricky to understand your article.
If you call it “nested_item”, it’ll be clearer but maybe I mislead.

As soon as I saw that you hadn’t declared it anywhere, I peeked in the BCL to go find it. My only guess is that it’s just a convenience declaration; I’ll start using it now, as it saves me a line of code :wink:

An aside… I use RivieraPro, and I had to explicitly create req in order to use it; it didn’t assign an object just by calling randomize().

examples works well. Constraints from above!.. (angels trumpets heard in distance)

In SV, objects always need to be created before they get used, including when randomizing. That part just isn’t shown (it’s part of the ‘//…’ block in the code sample).

I literally just ran into this in my sim, fixed it, and then came back to your example to see if you had written something. Of course you had.

So this is meant to be used with a transaction that is created during the new function, and then randomized over and over?
Versus created in the new function, and then also created over and over during the loop.

If by “this” you mean “constraints from above”, you shouldn’t think of it in terms of when the items are created. I’d use this approach to allow for constraint tweaking where this isn’t possible using the factory. For example, for the communication case from above you can’t set a type override on some_item to another class that only generates SHORT_TX or SHORT_RX, because that would cause constraint violations with the CONFIG and SHUTDOWN inline constraints.

An instance override might be possible if you make sure to name the items differently so they have different contexts. At the same time it would also be possible to create separate classes for CONFIG items and SHUTDOWN items and create those, leaving the possibility to set a type override. Back when I wrote this post I didn’t think much about alternatives. Now that I’ve got more experience I can see that there are many ways to achieve the same effect and it’s nice to know all the tools at your disposal.

Hi Tudor,

Your blogs are really good and informative.

In this current example, why the below constraint is not affecting the CONFIG / SHUTDOWN?

constraint only_comms_c {
req.mode inside { TX_SHORT, TX_LONG, RX_SHORT, RX_LONG };
};

For CONFIG/SHUTDOWN, we’re calling 'reg.randomize() with …". This means it’s randomizing the “reg” object and it only considers constraints defined inside its class. The scope getting randomized is the transaction.

For the other cases notice that we’re calling “this.randomize(req)”. This means that we’re randomizing the sequence (this), but only the “req” field. The scope that’s getting randomized is the sequence, so all constraints here there get considered as well.

Have a look at sections 18.11 In-line random variable control and 18.5.9 Global constraints of the IEEE 1800-2012 standard.