• Skip to main content
  • Skip to search
  • Skip to footer
Cadence Home
  • This search text may be transcribed, used, stored, or accessed by our third-party service providers per our Cookie Policy and Privacy Policy.

  1. Blogs
  2. Verification
  3. Using Constraints to Pass Configuration Options in the Unit…
teamspecman
teamspecman

Community Member

Blog Activity
Options
  • Subscribe by email
  • More
  • Cancel
IEEE 1647
IntelliGen
Specman
Functional Verification
e
team specman
Aspect Oriented Programming
Incisive Enterprise Simulator (IES)
AOP
IES-XL

Using Constraints to Pass Configuration Options in the Unit Hierarchy (Top-Down approach)

26 Jun 2009 • 4 minute read

To allow for increased solvability, some constraints that were previously uni-directional with the old “Pgen” generator are now treated by IntelliGen in a bi-directional manner by default.  This behavior dramatically improves solvability and gives you a lot more freedom in writing and layering very complex constraints. 

However, if you are coding with a Pgen frame of mind there is one case where the results might not be what you expected.  Specifically, the behavior of IntelliGen can differ from Pgen for the case where you want to constrain a child struct’s fields from within the parent (for example, when you want to pass configuration options down the unit hierarchy).  Fortunately, the code needed to address this situation is very simple to apply. Consider the following general example:

 

type size_t: [SMALL, MEDIUM, LARGE];

 

struct config_s {

   sz: size_t;

   valid: bool;

}; // struct config_s...

 

unit agent_u {

   cfg: config_s;

   bfm: bfm_u is instance;

   keep bfm.cfg == cfg;    // constraint [1]

}; // unit agent_u

 

unit bfm_u {

   cfg: config_s;

   keep soft cfg == NULL;        // constraint [2]

}; // unit bfm_u

 

unit env_u {

   agent: agent_u is instance;

}; // unit env_u



Specman users familiar with Pgen will know that Pgen will treat constraint [1] as unidirectional (from agent_u.cfg to agent_u.bfm.cfg), allowing agent_u.cfg to be randomly generated, and then pushing that struct down to agent_u.bfm.cfg.  Additionally, constraint [2] will not be enforced given that it is a soft constraint (and of course with Pgen the user would have to make constraint [2] a hard constraint in order for it to be enforced.)  If we run the above code we would find that agent_u.cfg and agent_u.bfm.cfg both point to the same config_s instance.  Here is the potential gotcha: since constraint [1] is unidirectional, (soft) constraint [2] will be ignored, which might not be the intended behavior – in this example it’s not clear if the user truly desired the cfg struct of the bfm_u to be NULL

Now consider the behavior of this code with IntelliGen: IntelliGen will treat constraint [1] as bi-directional by default.  As a result, constraint [2] will be applied in addition to constraint [1], Users will find that both agent_u.cfg and agent_u.bfm.cfg both point to the same instance of cfg_s which, in this case would be a NULL struct.  IntelliGen will apply all constraints in the above example, which is generally more intuitive and showcases the additional solving capabilities of IntelliGen.

But what if the intention was to pass the value of parent fields down into child structs in a purely top-to-bottom, unidirectional way?  The correct way to implement this in IntelliGen would be to wrap the right hand side of the constraint in a read_only() to enforce top-down unidirectionality (because wrapping constraint variables in read_only() causes them to be generated first), as shown in the following example:

 

type size_t: [SMALL, MEDIUM, LARGE];

 

struct config_s {

   sz: size_t;

   valid: bool;

}; // struct config_s...

 

unit agent_u {

   cfg: config_s;

   bfm: bfm_u is instance;

   keep bfm.cfg == read_only(cfg);     // constraint [1]

}; // unit agent_u

 

unit bfm_u {

   cfg: config_s;

   keep soft cfg == NULL;        // constraint [2]

}; // unit bfm_u

 

unit env_u {

   agent: agent_u is instance;

}; // unit env_u

 

In the above example, constraint [2] would not be enforced as sys.agent.bfm.cfg would point to the same cfg struct as its parent due to constraint [1].  Without the read_only(), constraint [1] would be bidirectional and IntelliGen would also consider constraint [2], hence the NULL cfg struct in bfm_u would be propagated upwards through the hierarchy resulting in sys.agent.cfg == NULL.

Bottom line:
IntelliGen has improved solvability over the previous generation engine (Pgen) given more constraints are now treated as bi-directional by default.  Thus if you would like to push parent fields down into lower level child structs, you will need to wrap the parent field value in a read_only() call.

Corey Goss

© 2025 Cadence Design Systems, Inc. All Rights Reserved.

  • Terms of Use
  • Privacy
  • Cookie Policy
  • US Trademarks
  • Do Not Sell or Share My Personal Information