Home > Community > Blogs > Functional Verification > generation action constraints from above
Login with a Cadence account.
Not a member yet?
Create a permanent login account to make interactions with Cadence more conveniennt.

Register | Membership benefits
Get email delivery of the Functional Verification blog (individual posts).


* Required Fields

Recipients email * (separate multiple addresses with commas)

Your name *

Your email *

Message *

Contact Us

* Required Fields
First Name *

Last Name *

Email *

Company / Institution *

Comments: *

Generation Action: Constraints From Above

Comments(0)Filed under: Functional Verification, IES, Incisive Enterprise Simulator (IES), e, Specman, IEEE 1647, Aspect Oriented Programming, AOP, IntelliGen, IES-XL

[Welcome guest blogger Reuven Naveh of Specman R&D]

What is the “constraints from above” problem, and how is it solved by Specman today?

The answer: “constraints from above” are stimulus generation constraints which have the following properties:

  • They constrain a do-not-generate field or its descendants.
  • The constraint is declared not in the type in which the field is declared, but at a higher level.
  • The field is later generated on-the-fly.

The following short example illustrates such a constraint:


struct packet {



      pre_generate() is also {

            gen id;




extend sys {



      run() is also {

            for i from 1 to 100 {

                  gen p keeping {

                        it.id == i;






While this syntax looks very similar to any other constraint, I regret to report that such constraints were simply ignored in Specman’s legacy “PGEN” stimulus generation engine (which I must admit is a behavior that has been recognized as one of PGEN’s most significant limitations).  However, starting with Specman version 8.2 (released last December), “constraints from above” are fully supported by “IntelliGen”, the new Specman generator.

The area in which such constraints are most often applied is in a sequences test scenario, where the user might want to constrain not just the current sequence’s item or sequence, but an item deeper in the sequence tree. Since the item is a do-not-generate field, this creates a constraint “from above”. The following example demonstrates this scenario:



struct packet like any_sequence_item {

    length : uint;

    keep soft length == 0xbad;



sequence packet_sequence using item = packet, created_driver = packet_driver;


extend SIMPLE packet_sequence {


    !packet : packet;


    body() @driver.clock is only {

        for i from 1 to 5 {

            do packet;





extend MAIN packet_sequence {


    !short_seq : SIMPLE packet_sequence;

    !long_seq: SIMPLE packet_sequence;


    body() @driver.clock is only {

        do short_seq keeping {

            legal => it.packet.length in [4, 8, 16];



        do long_seq keeping {

            legal => it.packet.length in [1024, 2048, 4096];






Before Specman 8.2 and IntelliGen, to bypass this problem, users had to adopt different sorts of workarounds, from rewriting the constraints and moving them to the “item” level, to generating the whole sequence tree in one gen action, thus hurting the freshness of the generated items.  In many cases, users wrote such constraints, naturally expecting them to enforced, only to find (or not to find…) that they were silently ignored.

Clearly it’s never a good thing when a user’s intent is ignored, and over time this naughty Specman behavior came to be known as the ‘The Conceptual Bug’ (who’s solution grew to become an inspiration for creating IntelliGen, but that’s another story …)  The name comes from the fact that (despite their innocent look) constraints from above present some unique conceptual problems which differentiate them from any other kind of constraint.  Specifically, there are two main issues involved here:

1 – Instance-based generation
The question whether to enforce or not to enforce a constraint in a gen action is typically not dependant of the specific instance under which the gen action is performed.  The instance is of course relevant when we sample or allocate data, but if we are generating a packet, then we can assume all constraints defined under this type will be relevant for the problem.  The same goes with constraints in the “keeping” block of the gen action: every time the gen action is performed, they will be relevant to it.

Constraints from above are different: it might be that the same gen action will be subject to different constraints, since each instance has been generated in a different scope. Therefore, to be able to handle constraints from above, the generator need to retrieve from the specific instance, the relevant constraints passing through it on the currently generated field.

2 - The Question of timing
An even more intriguing issue is in regard to timing, and the fact that constraints from above are actually enforced in separate generation contexts.  This is especially true when the constraints contain inputs, which might be inaccessible when the last gen action takes place. Take for example the constraint in the first code example given above – with "it.id == i", the local 'i ' is relevant only to the scope of the sys.run() method, while the 'id' is generated within a different method (and possibly long after the original method has finished).  Correct treatment of the constraint should therefore be in two phases: at the scope of the original generation, the inputs which participate in the constraint need to be sampled, and the sampling results need to be stored.  Later on, when the deeper gen action takes place, the sampled values should be retrieved and used in generation.

Again, starting in Specman 8.2 and later, when using IntelliGen the user need not worry about any of the issues above, and one can simply use constraints from above almost like any other constraint, and have them enforced to his or her satisfaction.  I say “almost” in the previous sentence since there are some guidelines which need to be followed (but fear not: IntelliGen does report warnings to catch deviations from the guidelines).

  • Remember that constraints from above apply to do-not-generate fields only. Trying to constraint a generatable field from above, and then re-generate it in another gen action will not succeed!
  • When using constraint from above, it is highly important to explicitly mark it as such. For example, in the constraint keep my_gen_field == my_item.dng_field it is not obvious who is the real parameter of the constraint, and which is considered an input. To make the constraint behave like a constraint from above, the proper way to write it is keep read_only(my_gen_field) == my_item.dng_field. This is the better coding style anyway.
  • Sometimes a constraint uses inputs which simply cannot be sampled. Suppose the constraint is keep seq.item.length == seq.item.f(me.g()). The method f() can be sampled only after the generation of the item, but the method g() cannot be sampled at that timing!

As long as these guidelines are followed, you will enjoy the benefits of assigning  constraints from above in your verification environment.

Happy generating!

Reuven Naveh
Specman R&D


Leave a Comment

E-mail (will not be published)
 I have read and agree to the Terms of use and Community Guidelines.
Community Guidelines
The Cadence Design Communities support Cadence users and technologists interacting to exchange ideas, news, technical information, and best practices to solve problems and get the most from Cadence technology. The community is open to everyone, and to provide the most value, we require participants to follow our Community Guidelines that facilitate a quality exchange of ideas and information. By accessing, contributing, using or downloading any materials from the site, you agree to be bound by the full Community Guidelines.