Home > Community > Blogs > Digital Implementation > encounter puzzler 2 solution finding registers beneath a hierarchy
 
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 Digital Implementation blog (individual posts).
 

Email

* 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: *

Encounter Puzzler #2 Solution: Finding Registers Beneath a Hierarchy

Comments(0)Filed under: Digital Implementation, dbGet, encounter, TCL, puzzler

Thanks to everyone who participated in this week's Encounter Puzzer.  If you didn't catch it earlier, have a look now before reading the solution discussion below.

I thought this puzzler was great because it's such a small and simple example, yet it leads to so many useful fundamental components of database access.  The first two comments were especially appreciated because it pointed out two of the primary ways to access data in Encounter: with dbGet and with Advanced Timing TCL commands (let's call them CTE-TCL commands for "Common Timing Engine-Tool Command Language" shall we?).

Coincidentally, I had a chance to visit was the original requestor of this challenge just yesterday.  I sent him the solution via E-mail and it wasn't working!  More on why in the discussion below...

@Edwin suggests a solution that was very nearly what I proposed to the customer:

deselectAll
foreach inst [dbGet -p2 [dbGetHInstByName i_a].allTreeInsts.cell.name DFF*] {
  dbSelectObj $inst
}

What I like about this solution is that it discovers the instances beneath the hierarchical instance i_a programatically rather than relying on instance name.  The \i_a/i0 instance I added at the top-level of the design is a bit contrived, but it does point out a risk in assuming hierarchy from instance name.  In the spirit of writing generic code that can work across a number of designs it is good practice to find the instances that are explicity stored beneath the hierarchical instance and using dbGet to traverse from hierarchical instance to "allTreeInsts" is a great way to do that.  But it raises a complication...

Another point to mention in this example is keying off a cell name of "DFF*".  If the timing libraries are loaded, the script could key off the ".isSequential" cell marking as follows:

foreach inst [dbGet -p2 [dbGetHInstByName i_a].allTreeInsts.cell.isSequential 1] {
  dbSelectObj $inst
}

Remember how I said the script I sent the customer wasn't working?  It turns out timing libraries weren't loaded so the isSequential marking was populated.  Turns out selecting by a sequential cell master name like Edwin suggested was a better approach for the situation.

Another point to mention is that as of 9.1.USR1 dbSelectObj works on a list so the code could be compacted further into:

dbSelectObj [dbGet -p2 [dbGetHInstByName i_a].allTreeInsts.cell.isSequential 1]

Further reading on selecting objects by pointer with dbGet in this blog entry.

By the way, it's worth mentioning that a Google search for "dbSelectObj cadence encounter" would retrieve this blog entry as would a search on support.cadence.com for "dbSelectObj".

One other thing to mention relative to the dbGet solution.  When I run the suggested code I get the following message:

**WARN: (ENCDBTCL-204): 'cell' is not a recognized object/attribute for object type 'hInst'. For help use 'dbGet <object>.?h' to get list of all supported (settable/unsettable) objects and attributes.

What's happening there?  Well, the warning can be ignored but .allTreeInsts returns what we call a "heterogeneous" list which includes all of the instances -and- hierarchical instances beneath i_a.  This list includes the hierarchical instance i_a/i_a_sub and when we try to traverse from i_a/i_a_sub to its "cell" we get the warning message because "cell" is not a valid object for hierarchical instances.  We could filter out the objects that aren't instances with the following addition in bold:

dbSelectObj [dbGet -p2 [dbGet -p [dbGetHInstByName i_a].allTreeInsts.objType inst].cell.isSequential 1]

Note: We're considering exposing heterogeneous and non-heterogeneous lists in a number of areas to make this simpler in a future release.

@Vishnu used CTE-TCL:

set x [get_cells -hier -filter "hierarchical_name =~ i_a/* && is_sequential == true"]
foreach_in_collection y $x {
   selectInst [get_object_name $y]

}

There's a lot of extremely useful functionality demonstrated in this example.  The complex filtering capabilities of get_cells, keying off the "is_sequential" attribute, using foreach_in_collection to iterate through the objects... Great stuff.  One tiny tiny nuance that was problematic with the example was filtering out the top-level \i_a/i0 instance.

By default, Encounter hides leading backslashes from instance names, so the instance that's called \i_a/i0 in the Verilog netlist is identified within Encounter as simply "i_a/i0".  Consequently, the script would still catch that instance undesireably as being beneath i_a.  We can overcome this however with a call to:

encounter 1> set dbgIsBackslashInNamesHidden 0

Once this variable is set, the leading backslash is no longer hidden and the code would work as desired: \i_a/i0 would be filtered out because it contains a leading backslash and therefore doesn't match the "i_a/*" filter expression.  Normally, variables like this are visible from Options->Set Global Variable...  However, this one isn't public yet.  I'm working with our developers on that now.  Kind of a wacky side-issue but I hope it illustrates some risks associated with keying off names vs. keying off the hierarchical structure directly.

Laurent proposed an interesting area-based solution.  I hadn't thought of that myself but it could certainly be useful in this and other scenarios when seeking to find objects by type in a specific area of the design:

set area [list 600 600 1200 1200]
foreach i [dbGet [dbQueryInstInBox \
  [dbMicronsToDBU [dbBoxLLX $area]] \
  [dbMicronsToDBU [dbBoxLLY $area]] \
  [dbMicronsToDBU [dbBoxURX $area]] \

  [dbMicronsToDBU [dbBoxURY $area]]].cell.isSequential 1 -p2] {
  dbSelectObj $i
}

An even easier way to go about this is with the dbQuery command.  I haven't talked about it yet since it's not fully documented until 9.1.USR3 but check back in a month or so for an update on that.  It can be really powerful and simple to use.

Another way to solve this puzzler is by using what JasonG referred to as "old school" commands.  Here we're talking about commands like "dbForEachCellInst" and old school is actually a good characterization of them since they've been around since Encounter's inception.  I sometimes refer to these as "FE-TCL" commands.  They're sometimes criticized as being cryptical and confusing, but they can often be fast and powerful:

proc selectHierRegisters {hinstName} {
  dbForEachCellVInst [dbHInstCell $hinstName] viPtr {
    if {[dbIsCellHier [dbVInstCell $viPtr]]} {
      selectHierRegisters $hinstName/[dbVInstName $viPtr]
    } elseif {[dbIsCellSequential [dbVInstCell $viPtr]]} {
      selectInst $hinstName/[dbVInstName $viPtr]
    }
  }
}

Ideally, we can do everything you can do with FE-TCL with dbGet but there are some cases where I find it more comfortable to fall back on FE-TCL commands.  This just might be one of those cases.  Here's why...

FE-TCL provides one very useful command for this scenario: dbForEachHInstTreeInst.  It's an object-type specific iterator that goes through each instance beneath a given hierarchical instance.  Perfect!  There's also a "dbForEachHInstTreeHinst" command that iterates throughall of the hierarchical instances beneath a hierarchical instance.  Here's an example:

proc userSelectHierRegisters {hinstName} {
  dbForEachHInstTreeInst [dbGetHInstByName $hinstName] inst {
    if {[dbIsCellSequential [dbInstCell $inst]]} {
      dbSelectObj $inst
    }
  }
}

An interesting side-note: We've been discussing the idea of splitting out more homogeneous lists in dbGet to make code more compact.  In this case, that would mean a list of just the instances beneath the hierarchical instance.  Stay tuned for more on that in a future release.

As you can see there's more than one way to solve this solution for sure.  I'm pleased we covered it from so many angles -- the general techniques described here can be applied to other scripting tasks in the tool.  Thanks again for the participation and discussion.  If you have any thoughts you'd like to add we'd love to hear from you.  Check back soon for more puzzlers and updates.  You'd be my Best Friend Forever if you subscribed to E-mail updates to our Digital Implementation blogs.  Never more than one E-mail a day and hopefully useful and interesting content.

Bob Dwyer

Comments(0)

Leave a Comment


Name
E-mail (will not be published)
Comment
 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.