• 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. Digital Design
  3. Encounter Puzzler #3 Solution: Renaming a Net Logically
BobD
BobD

Community Member

Blog Activity
Options
  • Subscribe by email
  • More
  • Cancel
CDNS - RequestDemo

Have a question? Need more information?

Contact Us
conformal
dbGet
net renaming
encounter
Digital Implementation
Encounter Digital Implementation
puzzler
tcl

Encounter Puzzler #3 Solution: Renaming a Net Logically

9 Mar 2011 • 4 minute read

Once again, the Encounter Digital Implementation designer community has stepped up to the challenge. Last week's puzzler -- renaming a net logically in Encounter -- was solved in short order. Let's add J2mh and Sims to the list of Encounter Wizards (along with regular commentator and guest blogger Jason G).

To quickly restate the challenge, we wanted to rename a logical net. We wanted to take this netlist:

module testcase ();
 wire net;
 BUFX1 i0(.Y(net));
 BUFX1 i1(.A(net));
endmodule

...and turn it into this:

module testcase ();
   wire new_net;
   BUFX1 i0 (.Y(new_net));
   BUFX1 i1 (.A(new_net));
endmodule

J2mh's solution was very similar to my own -- but his was more concise. Create a new net, and attach each instance terminal connected to the old net to the new net:

proc changeNetName {oldNetName newNetName} {
  selectNet $oldNetName
  addNet $newNetName
  foreach selTerminals [dbGet selected.allTerms] {
    attachTerm [dbGet $selTerminals.inst.name] [dbGet $selTerminals.cellTerm.name] $newNetName
  }
  deselectAll
}

Notice how we don't need to disconnect the old net from each terminal. Connecting it to the new net overrides the connection since a given instance terminal can only be connected to a single net.

attachTerm takes 3 arguments: <instName> <termName> <netName>

When you're iterating through each instance terminal in "net.allTerms" it returns pointers whose "name" is the instance name plus the pin name. Like "i0/A" for example.

I especially liked how he used dbGet to "walk" from each instance terminal to get the inst.name and cellTerm.name to pass the required arguments to attachTerm.

I used a slightly different approach that's probably more error prone. I used "file" commands to decompose <inst_name>/<pin_name>:

set instTermName [dbGet $term.name]
set instName [file dirname $instTermName]
set termName [file tail $instTermName]
attachTerm $instName $termName $newNetName

I like his approach better because it's not splitting strings -- it's getting the name directly from the appropriate db object.

The extra credit to the challenge was to make sure the script worked when renaming a net that connected through hierarchical terminal -- like "net2" does in this example:

module testcase ();
 wire net2;
 BUFX1 i0(.Y(net2));
 a i_a(.in(net2));
endmodule

module a(in);
 input in;
 BUFX1 i0(.A(in));
endmodule

I thought this was going to be a really complicated case to handle. Sims' approach was what I thought was going to be necessary where we'd need to connect the hierarchical terminal i_a/in to the net at each level of hierarchy. However, I don't think it's that difficult after all. Here's why...

With the netlist above, although there are indeed fractional representations of the net in the db, there is only 1 net in the design in terms of how it is presented to us via dbGet. I've heard this called the "canonical" net name. Therefore, if we connect the input of the buffer within the "a" module to a new net:

encounter 1> addNet new_net2
encounter 2> attachTerm i_a/i0 A new_net2

encounter 3> attachTerm i0 Y new_net2

..."new_net2" is automatically connected through the hierarchical terminal "i_a/in". The netlist would look like this:

module a (
    in);
   input in;

   BUFX1 i0 (.A(in));
endmodule

module testcase ();

   // Internal wires
   wire new_net2;
   wire net2;

   BUFX1 i0 (.Y(new_net2));
   a i_a (.in(new_net2));
endmodule

The final part of the extra credit was to handle the case where the net was connected to a top-level IO port. Like top-level input port "in" in this example:

module testcase (in);
 input in;
 BUFX1 i0(.A(in));
endmodule

This too was a little easier than I expected, but in an interesting way. Rather than having to create a new top-level port and connect it to a newly-created net, when you create a new top-level port a new net is automatically available. Or, if you create the net first and then create a new top-level port the two are automatically associated.

addModulePort takes a moduleName -or- uses the special character "-" to denote addition at the top level:

Usage: addModulePort
    addModulePort <moduleName> | - <portName> {input | output | bidi}

For example:

addModulePort - new_in input

It's worth mentioning why dbGet calls the list of terminals associated with the "net" object "allTerms" instead of "terms" or "instTerms". It's called "all" to indicate the list of objects may contain a mixture of top-level terminals ("terms") and instance terminals ("instTerms").

Stringing this all together, we can check the object type of each terminal in the allTerms list and do something different depending on which it is:

proc userChangeNetName {oldNetName newNetName} {
  set net [dbGetNetByName $oldNetName]
  addNet $newNetName
  foreach term [dbGet $net.allTerms] {
    if {[dbGet $term.objType] == "instTerm"} {
      set instTermName [dbGet $term.name]
      set instName [file dirname $instTermName]
      set termName [file tail $instTermName]
      attachTerm $instName $termName $newNetName
    } else {
      addModulePort - $newNetName [dbGet $term.inOutDir]
      deleteModulePort - $oldNetName
    }
  }
  deleteNet $oldNetName
}

All of this made me realize it would be a good to have native net-renaming functionality in the tool so I filed a reuquest asking for an enhancement. Hopefully this served as a useful example of how db access can help bridge the gap between current capabilities and something we as users need to accomplish.

When performing netlist manipulations like these it's always good to check your work. I'm sure many of you are familiar with the Encounter Conformal Equivilence Checker which provides (among other things) a quick and easy way to make sure two Verilog gate level netlists are functionally equivilent.

Thanks again for participating in these puzzlers. I'll follow-up soon with another (designers have been sharing some great challenges lately!). It would be great if you subscribed to these blogs so we can keep in touch.

Bob Dwyer

 


CDNS - RequestDemo

Try Cadence Software for your next design!

Free Trials

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

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