Home > Community > Blogs > Digital Implementation > encounter puzzler solution renaming a net logically
 
Login with a Cadence account.
Not a member yet?
Create a permanent login account to make interactions with Cadence more convenient.

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 #3 Solution: Renaming a Net Logically

Comments(6)Filed under: Digital Implementation, dbGet, encounter, Encounter Digital Implementation, TCL, puzzler, Conformal, net renaming

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

 

Comments(6)

By Simi on March 10, 2011
Hi Bob, connection through hierarchical terminal i_a/in seems to work only when there is one instance to be connected in the hierarchy i_a. Otherwise encounter creates a new module port  when the script loops through the first instance term under the hierarchy, and after all the instance terms are reconnected, the old module port is left open. Logically this is still correct, but it creates new hierarchical ports, and leaves old ones dangling.

By BobD on April 13, 2011
Hi Simi,
I was working on a similar issue with a user yesterday and I was reminded of this conversation. I went back and tested with more than one instance and I still don't see new hterms created.
I think the key thing is to connect the instances beneath the hierarchical instance by doing an attachTerm while the original net still connects to the hterm. If you detach term first then try to connect it through the original hterm it gets tricky.
Let me know if you see otherwise - this is definitely an interesting topic I think.
Thanks,
Bob

By Simi on April 27, 2011
Hi Bob, I use the same testcase as in this blog, except that I have one more instance inside module "a", which I  named  "i1".
Here is the transcript, you can see "new_net2" hterm is getting created. I cant see where I'm making a mistake.
velocity 1> get_pins i_a/*
i_a/in
velocity 2> get_cells i_a/*
i_a/i0 i_a/i1
velocity 3> addNet new_net2
velocity 4> attachTerm i_a/i0 A new_net2
velocity 5> get_pins i_a/*
i_a/in i_a/new_net2
velocity 6> attachTerm i_a/i1 A new_net2
velocity 7> get_pins i_a/*
i_a/in i_a/new_net2
velocity 8> attachTerm i0 X new_net2
velocity 9> get_pins i_a/*
i_a/in i_a/new_net2
velocity 10> dbGet [dbGetHTermByInstTermName i_a/new_net2].net.allTerms.name
i0/X i_a/i1/A i_a/i0/A
velocity 11> dbGet [dbGetHTermByInstTermName i_a/in].net.allTerms.name
0x0

By BobD on April 29, 2011
Hi Simi,
I did some more testing on this and I see what you're saying now. I previously added a 2nd instance within i_a but it was not connected through the same hterm. When they're both connected to the same hterm I indeed see what you're talking about - that a new port is created because you can't call attachTerm on a list of terms and it doesn't accept wildcards.
I thought there might be a way to get there with the -moduleBased -port or -noNewPort options but I don't think it's possible. Your solution using attachModulePort looks like the way to go - and as you show fracturing up the net and looking at hnets is probably the most efficient way to get the hterms connected to the net for connection.
Nice scripting! And thanks for participating here. I appreciate it.
-Bob

By Mohan Kumar ch on May 21, 2011
Hi i need to change the Hierarchy of the net for example
I have net1 which should be renamed as U1/net1 , how to do this ??
currently i am managing by writing an eco file and load it by loadeco file .
any alternative way for best practice ??
-mk

By shiva on April 22, 2012
For I/o module port of bus type how can I delete the old module ports

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.