SPP Example

Perhaps the best way to see how SPP is used in a standalone script is to look at an example. The first script that I wrote was a script to parse the output of the report_transitive_fanout command. That script, clocktree.pl, can be found here.

I'll try to go over some of the more interesting parts of the script on this page.

We start off with this magic:

: # -*- perl -*- eval 'exec perl -w -S $0 ${1+"$@"}' if 0;

While this little snippet really has nothing to with SPP, I thought I'd throw it in there as a portable to start of your Perl scripts. It has the positive qualities that it doesn't depend on a hard-coded path to perl and it allows your script to be started in any of three ways:

unix% script unix% perl script unix% sh script

Moving on, we have at the start:

use strict; use Synopsys; $Synopsys::Verbose = 3;

I always use the -w flag and the use strict; pragma in any worthwhile Perl script I write. Perl is a write-only language only when you want it to be. Next, make sure to use Synopsys; or your script won't now where to find the module. Finally, we can set the class variable Verbose to anything we want before we create an SPP object. When the object is created it's instance value of verbose will be initialized to this value. I set the verbose level 3 to see more output. If I wanted it to run more silently, I would set it to 1.

Ok, enough screwin' around, let's fire off a Synopsys shell process!

my $shell = Synopsys->new($shell_name) or die "Init of $shell_name failed, exiting.\n";

Pretty simple huh? I pass in the shell name I want (pt_shell in this case) and I'm done. In the case of pt_shell, I didn't need to specify -tcl_mode because pt_shell doesn't run any other way. But other shells have a choice, so make sure to specify whichever you want. Also be sure to check the return value of this function everytime.

Now, I'll redefine the error_handler.


If you look at the definition of &my_error_handler, you'll see that it's different from the default error_handler in that it exits on any command error. This makes the script easier on the eyes because an explicit check of the return value of every command is not necessary.

Now, let's set some variables, read in the verilog and set the current design.

$shell->variable('search_path', '.', '$synopsys_root/libraries/syn', '/cad/lsi/lib/synopsys/lcb500k'); $shell->variable('link_library', '"*"', 'lcb500kiov.db', 'sgi500kv.db'); $shell->read_verilog('Magic.v'); $shell->current_design('Magic');

Now, get a Collection object for the top of the clocktree.

my $pin = $shell->get_pins('Pads/PadsClock/Phi1Drive/A');

We're finally to the meat of the script. Once the SPP infrastructure was set, it was fairly straight-forward writing my own method as an extension. The get_transitive_fanout method parses the output of the report_transitive_fanout command. Perl is perfect for this task. Tcl has about as much chance as pulling off a function like this as I do of graduating in the near future.

$pin->get_transitive_fanout( '-callback' => \&callback, '-stop' => [ '^DEL', '^MUX21H' ], '-skip' => [ '^BAL' ], ); sub callback { my @path = @_; return if $path[$#path]->{'pin_out'} =~ /Z$/; return if $path[$#path]->{'pin_in'} =~ /D$/; $i++; print OUTFILE "spice_path path$i "; foreach my $node (@path) { print OUTFILE "/$node->{'pin_in'} "; print OUTFILE "/$node->{'pin_out'} " if $node->{'pin_out'} ne ''; } print OUT ";\n\n"; }

I tried to write get_transitive_fanout in a generic enough way so it would satisfy anyone's needs. I purposely included all the information that the command returns even though I don't use it. For a full description of this method see the manpage.