( ESNUG 226 Item 1 ) ---------------------------------------------- [8/31/95]
Subject: (ESNUG 225 #1) Synopsys Point-To-Point Timing Exceptions
>If you have a design with point-to-point timing exceptions (i.e. multicycle
>paths, false paths), these exceptions become invisible to the timing
>analyzer when the design is incorporated into the next higher level of
>hierarchy. ... I have a design in which several lower level modules contain
>literally hundreds of point to point exceptions. After I carefully set
>these up & compile the block until I get a clean timing report, I set
>dont_touch on the module and then work on the next level up. But the timing
>analyzer does not take the subdesign's exceptions into account!!!
>Hence, I get ridiculous compile times & a lot of bogus timing violations.
From: myhui@thlayli.newport-beach.ca.us (Michael M.Y. Hui)
John,
I always apply my multicycle path commands at the top level only, using the
full hierarchical instance name. I do this because when I use "characterize",
I do it also at the top level, and obviously "characterize" *requires* that
the multicycle paths be visible to it. This is the only way it can set
sensible timing constraints for the block you're characterizing for,
especially for those ports that are fed by slow paths that have been
"corrected" by the multicycle path command.
After you characterize (from the top level), and before you do a re-compile
or incremental compile, try displaying the timing constraints, and look for
the pins that should belong to a multicycle path. Check to make sure that
those pins have sensible timing constraints (i.e. the limit should be more
than one clock period.)
Generally, as a safety check, I always check the timing constraints before
a compile anyways just to minimize wasting time on a badly set up compile.
- Michael M.Y. Hui
---- ---- ---- ---- ---- ----
From: Karl.Pfalzer@Eng.Sun.COM (Karl Pfalzer)
John, There are 2 "clever" ways of dealing with this issue.
There is a reason why constraints would not automatically propagate up a
design hierarchy: exceptions are design attributes, visible at the current
top-level design. However, when this design is instantiated (now a "cell" in
Synopsys jargon), it may not be the designer's intent to have every instance
(cell) of this design have these exceptions --- as would occur if (previous)
design constraints automatically propagated up a hierarchy and took affect
in every instance (cell/reference) in this design. (The user implies this
"pitfall" in his message, too.)
Anyway, one way of dealing w/ propagating constraints:
1) In the constraint file of the leaf/lowest level module/design where the
exceptions are required write them such that they propagate based upon
whether the current level design is this module or contains a reference
to it (cell).
For example, suppose the lowest level design is called "SyncFF" and you
wanted to specify an exception (false-path) through porrt "D" to a
register QInt_reg. A dc_shell script would be written:
foreach(ThisDesign,find(design,current_design)) {}
if (ThisDesign == "SyncFF") {
set_false_path -from find(port,D) -to find(cell,QInt_reg);}
else { /**2**/
/** cells/instances which reference SyncFF and set exception
** through their top-level port (determined dynamically below) **/
filter(find(cell,-hier),"@ref_name == SyncFF") > /dev/null; /**1**/
foreach(i,dc_shell_status) {
j = find(net,all_connected(find(pin,i + "/D")));
while (1) {
find(port,j) > /dev/null;
if (dc_shell_status != {}) {
break;
}
j = find(net,all_connected(find(pin,j)));
}
set_false_path -from find(port,j) -to find(cell,i +"/QInt_reg");
}
}
Obviously, when compiling SyncFF, the above script is included. However,
when derived/enclosing modules are also compiled, be sure to include the
above script too. By always including lower level include scripts in
derived/enclosing design scripts this is easily accomplished.
The above works fine for primary input to register paths. However, it
also applies to ALL instances/cells of SyncFF (which may not be desired).
Of course, this could be modified by "subtracting" cells from /**1**/
above.
In cases where you have a register to register path, life becomes a little
more difficult. Why ?? Because as you propagate up the hierarchy, until
the path exception is fully enclosed, the path source will be a port.
Once at levels which fully enclose the path, the source is a cell/reg.
The method above in 1) can still be used, however you will need to add an
additional "else if/else" clause at /**2**/.
2) The 2nd method which is the most general is using "path segmentation" (try
SolvIt for details). The method uses set_input/output_delay constraints
on PINS at various levels of the design hierarchy. This also enforces
& eases time budgeting along multicycle paths. By segmenting a path, you
create new startpoint and endpoints and effectively break the normal
[port, reg, clock] <--> [port, reg, clock ] timing paths. However, the
advantage is "significant" when propagating exceptions up a deep design
hierarchy, so you only need to prepend cell names on the pins as you move
up the hierarchy (to move the constraints). The budget delays (arguments
to set_input/output_delays) would likely change to. (report_design will
report on such path segmentation).
- Karl Pfalzer
Sun Microsystems
|
|