( ESNUG 348 Item 17 ) -------------------------------------------- [3/30/00]
Subject: ( ESNUG 343 #12 ) Synopsys Response To "Translating DC To TCL"
> As I just ported most of my dc scripts from dc_shell to dc_shell -tcl, I
> thought I would share my experiences and ask my unanswered questions...
>
> Overall dc-transcript did an awful job of converting my dc-shell scripts
> to tcl. Very few of them worked first time, but it at least put me in
> the right ballpark. I was pretty frustrated for the first few files, but
> once I started to understand the dumb things it repeatedly did (thanks
> Gzim), it became relatively simple to fix its output.
>
> - Mark Andrews
> Electronics For Imaging, Inc. Foster City, CA
From: [ Tickle Me Elmo ]
Hi John,
I'd like to comment on Mark's post (ESNUG 343 #12) regarding DC-Tcl and
hopefully answer his questions. I work at Synopsys, but please sign me as
[ Tickle Me Elmo ] in this letter, OK?
I think Mark hit on a very important point regarding dc-transcript. It's a
good place to start, but it will by no means create a perfect translation of
your DC compile scripts.
I also wanted to reinforce a point I made during the "Tickle Me Elmo" SNUG
presentation last year. Once you become familiar with Tcl, you will write
much better scripts than what you would get out of a translator. This isn't
a problem that's specific to dc_shell and Tcl, but if you look at dc_shell
as a language you can easily see why translation is difficult.
> HELPFUL HINT 1
> --------------
>
> Say you have this in dc_shell, i.e. you are using a variable to test
> something in a filter command:
>
> test="true"
> filter( find( design, "*" ), "@is_mapped == test" )
>
> dc-transcript will convert it to:
>
> set test {true}
> filter [find design {*}] {@is_mapped == test}
>
> This always returns an empty collection, it should have been:
>
> set test {true}
> filter [find design {*}] "@is_mapped == $test"
I'd like to give you some insight into why this is difficult to translate.
In dc_shell, the syntax for variables and constants is identical. These
are identical in dc_shell:
test="true"
filter( find( design, "*" ), "@is_mapped == test" )
and
filter( find( design, "*" ), "@is_mapped == true" )
To translate this you have to know that the variable "test" was created to
be included in the subsequent statement. This requires you to keep track of
the "state" of all variable assignments, then make the appropriate
substitution. This looks simple enough to translate, but when "we" do it
visually, we're using clues from the command. The fact that "test" is
defined, the fact that "is_mapped" takes a true/false value, and the fact
that "test" is assigned "true" which is what "is_mapped" is looking for.
dc-transcript doesn't try to "understand" your script. It works to
translate dc_shell constructs into DC-Tcl constructs. So to add to the
hint, these sorts of transformations are not performed by dc-transcript.
I highly recommend reviewing the output of dc-transcript and make sure your
script still makes sense. As an aside, for the straightforward translation
of constraint files dc-transcript has a much higher success rate.
> QUESTION 1
> ----------
>
> Do we need the tcl equivalent of this in dc_shell -tcl?
>
> foreach(design_name,dc_shell_status){}
With DC-Tcl, "dc_shell_status" has gone away. It has been replaced by
'real' return values from commands. If you're using Tcl, you don't need
"dc_shell_status".
Example:
find(design, "*")
my_designs = dc_shell_status
should be rewritten (in Tcl)
set my_designs [find design {*}]
dc-transcript will attempt to do this for you but it can't always bind the
command and the dc_shell_status it belongs to in which case it doesn't
translate it. Note that dc-transcript will create a Tcl variable called
"dc_shell_status" where it finds it in your dc_shell scripts. However this
variable in Tcl is no different than any other Tcl variable. It does not
automatically get set to the return value of the previous command.
So in fact dc-transcript would turn the above dc_shell code into:
set dc_shell_status [ find design {*} ]
set my_designs $dc_shell_status
> QUESTION 2
> ----------
>
> Do we need these anymore?
>
> list_name = {}
> int_name = 0
> str_name = ""
>
> Dc-transcript dutifully converts them to tcl, but tcl doesn't know the
> difference between and integer and a string. And we don't really want a
> list in tcl, we need a collection. I wasn't really sure what the correct
> thing to do was, so I just deleted them all, (everything still seems to
> work...).
In most cases, you don't need to initialize variables in Tcl, but there's no
harm in doing so.
Technically, "list_name = {}" can either be a null string or a null list.
Actually, in Tcl lists are just strings with a special format. This is one
of the reasons that they're horribly inefficient for storing large amounts
of things. And this is the reason we invented "collections".
You touched on this in HELPFUL HINT 1, but you need to keep straight the
meaning of "" vs {} in Tcl. They're both used for quoting strings. ""
allows you to perform variable substitution inside while {} keeps the stuff
inside intact:
dc_shell-t> set test "true"
dc_shell-t> puts "$test"
Prints:
true
while
dc_shell-t> puts {$test}
Prints:
$test
This is a very common thing to mess up when learning Tcl and I will admit
that I still screw this up sometimes.
> QUESTION 3
> ----------
>
> How do I create an empty collection?
The answer is, you don't need to. I know this may not be obvious and it
wasn't to me when I first starting using DC-Tcl. When you want to have a
collection of things, you grab objects using one of the "get_" functions.
If you REALLY want to create something that has null value to initialize a
variable, you can simply assign it a null string, for example:
dc_shell-t> set my_collection ""
...
dc_shell-t> set my_collection [get_designs]
I think the answer to the next question my help clear things up:
> QUESTION 4
> ----------
>
> Is a collection a regular tcl variable with a hidden Synopsys type? Or is
> it a tcl list with one entry and a hidden Synopsys type? By type I mean
> design, net, port etc.
Really, there's only one type of variable in Tcl: The string. All other
variables are just special types of strings. Numbers are strings that can
be evaluated by certain functions (hence why there's no operators in Tcl!)
and lists are strings with rules about delimiting. In DC-Tcl (and other
Synopsys shells that are Tcl-based) collections are fundamentally strings.
Things that are expecting "collections" know how to take the collection
handle string and turn it into an object.
Try this: (with a design in memory)
dc_shell-t> set foo [get_designs]
now
dc_shell-t> puts "$foo"
You get the string:
_sel123 (or whatever name DC creates it as)
But if you say
dc_shell-t> report_attribute $foo
You get an attribute report for all your designs. This is because
"report_attribute" was looking for an "object_list" as an argument. (To
verify this, type "report_attribute -help".) To see what I mean, try:
dc_shell-t> set goo "_sel666"
dc_shell-t> report_attribute $goo
You get:
Warning: Can't find object '_sel666' in design 'DESIGN'. (UID-95)
Warning: Nothing implicitly matched '_sel666' (SEL-003)
Error: Nothing matched for collection (SEL-005)
(assuming you had design "DESIGN" loaded into memory.)
DC actually tried to find the collection "_sel666" which is something that
you just made up. But Tcl didn't know that, it just thinks that "_sel666"
is a string. It wasn't until "report_attribute" tried to actually look up
"_sel666" that things got funny.
Back to the "empty collection" question, if you try to be clever and do:
dc_shell-t> set foo [get_designs ""]
you will get nothing, null string, NOT an empty collection
dc_shell-t> echo $foo
dc_shell-t>
I hope I have shed some light on DC-Tcl and Tcl in general. I want to thank
Mark for posting his message to ESNUG and sharing his experiences. As
always, we welcome feedback about our products (yes both good and bad). If
you encounter a problem or something doesn't work as you expect, please let
us know. We really DO listen to your feedback!
- [ Tickle Me Elmo ]
|
|