This set of scripts will fix hold times on scan
chain inputs using Design Comapiler, by inserting delays.
Hold time problems in scan chain shift timing can
be fixed by a recompile, of course, but in such
case care must be taken to keep Design Comapiler
from doing anything to create problems with functional
logic, which usually requires multiple compile scripts
with "case" statements, repeated timing analysis runs
to monitor DC's effect on the netlist, etc.  With
these scripts we can avoid all that, at least in those
cases where we have a library with scan FFs which have a
dedicated scan shift data pin.  (Reordering the scan chain
in order of clock delays is another (and possibly better
overall) solution to fixing scan shift hold time problems,
but is somewhat more complicated to automate).

There is a main script which does some setup and
then calls the "add_delays" routine, which then
will fix hold times in the design specified by the
"TARGET_DESIGN" variable.

In this implementation, the "add_delays" procedure looks
for all FF "TI" input pins.  Those inputs are normally
used only for scan chain shift connections, so if you're
using them for something else anywhere, be aware that
the script does not discriminate and will also fix hold times
on TI pins used for functional logic.  In general, the
"get_scan_hold_violators" procedure could be replaced
with something that loads the "TI_PIN_LIST" variable
using a different selection criterion (i.e. something
other than "[get_pins -hier */TI]"), in order to
get an arbitrary list of violating endpoints.  Or,
the violating endpoint pins could be extracted from some
other utility (PrimeTime, or whatever) - "the exercise
is left to the reader".

The main script calls "add_delays" twice, rereading SDF
annotation in between calls, since we've observed that hold
time violations aren't always worst-case with min SDF
annotation.  The "PASS_CYCLE" variable is incremented between
runs to make sure the netlist doesn't end up with
duplicate instance names being added.

The "DELAY_CELL_TYPES" variable needs to be loaded with a
list of the buffers to be used for delays, preferably in order
of ascending delay (choice of delay cells is another topic
which could be discussed at length).  The "add_delays" routine
then cyclically inserts a cell from the list on the violating
inputs, rechecks to see if it fixed the hold-time problem,
iterating in the delay cell list and retrying as necessary.
If the maximum-size delay cell won't fix the hold-time
violation, it starts the cycle over, adding another
delay cell in series.  Delay cell instance names are tagged
with the "pass cycle" (corresponding in this case to
successive SDF annotations), the "delay cycle"
(corresponding to the current target delay cell),
and a date code.  The date code prevents identical instance
names from being generated in the unlikely event
that the script finds the same error twice on the same
design, in successive ECO cycles.  The user might want to
change the naming convention to suit themselves (the
current protocol tends to generate some rather stupendous
net names).  The scripts assume that all buffers or delay
cells use the "pin A input/pin Z output" format for inserted
cells; the pin names in the scripts will have to be modified
for libraries which don't conform to this regime.

In addition to being applied to the netlist, the commands
to add delays are also written to the file named by the
MOD_COMMAND_FILE variable.  Since typically the scripts
will be run on a post-layout netlist and then used to
generate an ECO for layout, it may be necessary to do
the delay cell insertion on a pre-layout netlist for the
ECO, so they are preserved in this file for future use.

AFA known bugs goes, I think there are problems if
"TARGET_DESIGN" is not set to the top level design (which
is not an issue unless someone wants to insert delays
only on a submodule) but that's all I know of at the
moment.  One thing to keep in mind, though, is that when
inserting cells in a post-layout, SDF-annotated netlist,
new nodes are created for which SDF annotation will not
exist, and which will be timed using whatever other timing
parameters Design Time can find (typically wire loads).
So as the script repeatedly runs its analysis looking
for hold time violations, it may inaccurately assess the
remaining hold-time violations as a result of now-inaccurate
timing due to missing SDF annotation.  Worst case, of course,
this simply results in another ECO cycle, and of course this
problem will be fixed some time in 2073, when the EDA industry
has finally succeeded in interactively coupling layout
with synthesis.

A note on the TCL code...  I'm not a professional programmer
("Make Silicon, Not Software").  So in the code there
are probably numerous prime targets for objection by
those who are such.  For instance, I didn't like the
global variables, but I couldn't find a way out of using
them without making the code even more complex by using
TCL's "namespaces" and "uplevel" commands and other
byzantine constructs.

In any case, if anyone has any complaints (other than
programming "style") or suggestions or finds any bugs
(or wants to throw money!!), email me at "icnerd@ieee.org".  

Credit and appreciation is due Dave Unterseher and Anil
Moolchandani of Synopsys, who both contributed solutions
to extracting data from DC when it wasn't at all obvious
how to get at it...
