SPP Performance Note

It's probably not surprising that running a Synopsys shell command in the Perl world is slower overall than running it directly in Tcl. The overhead of communicating the command and response back and forth over the pseudo-tty, while it seems insignificant during interactive use, is actually substantial. This is especially true for commands which take very little time to execute in Tcl, like iterating over large collections.

When it comes to running commands like compile or report_timing, this overhead doesn't really matter because command execution time swamps out terminal communication time. However, compare the following two code snippets, both of which find the capacitance on all the output pins in a design.

First, in Tcl:

proc cap_tcl {} { foreach_in_collection pin [get_pins -h -filter "direction == out" *] { set name [get_object_name $pin] puts "$name rise [get_attribute $pin actual_rise_transition_max]" puts "$name fall [get_attribute $pin actual_fall_transition_max]" } }

Now, the Perl:

sub get_cap1 { my $all_out_pins = $shell->get_pins('-h', '-filter "direction == out"', '*'); my $size = $all_out_pins->size; for($i=0; $i<$size; $i++) { my $pin = $all_out_pins->index($i); my $name = $pin->name; $shell->printer(1, "$name rise ", $pin->actual_rise_transition_max, "\n"); $shell->printer(1, "$name fall ", $pin->actual_fall_transition_max, "\n"); } }

So how much slower does the Perl run than the Tcl? How about 10 to 30 times slower! The pseudo-tty communication overhead just kills the Perl. It's really not that surprising I guess. The Perl is basically running the innermost code of a tight loop over a network channel. Nothing good will ever come of that.

So is there anything that can be done about it? Yes, if Synopsys were to get involved, they could make this problem go away. Ok, that's not going to happen in the next week, so is there anything else that could be done. Well, yes. Most solutions rely on either getting the Synopsys shell to spit out a lot more information at one time or writing more code in Tcl.

Getting more out of Synopsys

One of the reasons that the Perl code above is so slow is that it's executing three Tcl transactions every time through the loop. That can add up to a lot of overhead. If we could somehow convince Synopsys to spit all of our information at once and then parse it in Perl all at once, things would be much faster. Although it sounds inefficient, having Synopsys send over megabytes of data and parsing it isn't that slow.

Consider this alternate solution:

sub get_cap2 { my $all_out_pins = $shell->get_pins('-h', '-filter "direction == out"', '*'); $shell->report_attribute('-nosplit', '-application', $all_out_pins); foreach my $line ($shell->output_lines) { if( $line =~ /(\S+)\s+\S+\s+actual_rise_transition_max\s+(\S+)/ ) { print "$1 rise $2\n"; } elsif( $line =~ /(\S+)\s+\S+\s+actual_fall_transition_max\s+(\S+)/ ) { print "$1 fall $2\n"; } } }

get_cap2() runs about 3 to 4 times faster than get_cap1(). Now let's embed the whole command into Tcl:

sub get_cap3 { $shell->run( 'set i 0;' . 'set all_out_pins [get_pins -h -filter "direction == out" *];' . 'puts stderr "Getting info on [sizeof_collection $all_out_pins] pins.";' . 'foreach_in_collection pin $all_out_pins {' . 'set name [get_object_name $pin];' . 'puts "$name rise [get_attribute $pin actual_rise_transition_max]";' . 'puts "$name fall [get_attribute $pin actual_fall_transition_max]";' . '};' . ); }

This one produces the exact same output as the previous two but runs in native time, which shouldn't surprise anyone. Of course, you're back to writing Tcl again, which we were trying to avoid in the first place! This third solution also runs into the problem of line length that I describe here. If you're going to do something like get_cap3(), it's probably a better idea to create a Tcl source file that does what you want and just source that file to execute it.

Have we run out of ideas? Almost, but Synopsys could again help us out. One of the reasons that get_cap2() doesn't go faster is that report_attribute returns information on every attribute for the objects we ask about. get_cap2() spends most of it's time getting the huge file across the pty while parsing it takes relatively little. Since we only care about a fraction of what's sent, getting the whole output is a waste. If Synopsys would add an attribute argument to report_attribute, then it could tell us only about the attributes we want and get_cap2() would run much faster.

The Bottom Line

SPP has some big performance problems for some applications. For other things, I couldn't imagine writing the same thing in Tcl. Take my example script, which uses Perl's ability to quickly create complex data structures. This is something no one would want to try in Tcl. The bottom line is that if SPP actually becomes used, Synopsys may be inclined to make some changes internally to make it run better.