( ESNUG 451 Item 6 ) -------------------------------------------- [02/08/06]

Subject: ( ESNUG 450 #7 ) Find those Global Net Worst Delays in PrimeTime

> I'm trying to figure out the best way to get the worst delay from one pin
> to another in PrimeTime.  This is to determine the delay of a global net,
> before floorplan blocks are even synthesized.  The path is simple; non-
> inverting, fanouts of one, with zero or more repeater buffers (or pairs
> of inverters):
>                          zero or more repeaters
>                            __________________
>                           /                  \
>                  |\         |\            |\          |\
>          ...-----| >*-------| >----...----| >--------*| >---...
>                  |/pin1     |/            |/      pin2|/
> 
> How can I get the delay from pin1 to pin2?  I can't simply get a timing
> arc, because there are an unknown number of optional repeater buffers
> between the two pins, and a timing arc only goes across one net or cell.
> (Also, I need to traverse the hierarchy of soft macros.)
>
> In my past experience with other tools (IBM Einstimer), it took only one
> command to get the latest arrival times of pin1 and pin2, and then I could
> just subtract them.  (I took the worst of the rise-to-rise or fall-to-fall
> delays.)
>
>     - Tom Arneberg
>       SGI                                        Chippewa Falls, WI


From: Eric Petrich <eric.petrich=user domain=intel spot calm>
To: Tom Arneberg <toma=user domain=sgi spot calm>

Hi Tom,

Like you, I haven't found any built-in method for measuring delay across
multiple gates.  I don't have a Tcl routine handy, but I may be able to shed
some light on some questions you raised.

First, you see only one "arrival" time when you look at a point in a timing
path because there is only one arrival time at that point for that path.
If you want to see the earliest arrival time, you would need to specify
"get_timing_paths -delay_type min".  Remember you're looking at attributes
of a timing path through the pin, and not necessarily the attributes of the
pin itself.

Having said that, the "pin" object has the following attributes
(list_attribute -app -class pin):

  max_fall_arrival
  max_rise_arrival
  min_fall_arrival
  min_rise_arrival

One could simply compare the values of, say, "max_rise_arrival" for the two
pins, and the difference may tell you the delay between the two.

Note that I said "may".  The details are not completely clear to me, but I
have seen cases just within the last few weeks where this comparison is
insufficient.  I was trying to measure clock insertion delay, and I think
that generated clock sources don't always have values that you can use in
this manner.  (They probably make sense in some other context.)

To avoid errors, "get_timing_paths" is the best method I know.  I would
recommend getting a timing path "-through" both pins, because it seems
possible that the worst path through one pin could differ from the worst
path through another pin.  (Though you did say that these are top-level
nets with no fanout or fanin.  That would simplify matters, but why take
chances if you're striving for a general solution?)

Let's see if I can come up with a procedure that will meet this need....

  proc pin2pin_dly {min_max pin1_ref pin2_ref} {
    set wst_dly ""
    # For general cases, I always assume get_timing_paths might return
    # more than one path. Therefore use foreach_in_collection to iterate.
    foreach_in_collection tpath_ref [get_timing_paths -through $pin1_ref \
            -through $pin2_ref -include_hierarchical_pins \
            -delay_type $min_max] {
        foreach_in_collection tpoint_ref [get_attribute $tpath_ref points] {
            set oref [get_attribute $tpoint_ref object]
            # The compare_collections command returns 0 if both collections
            # contain the same elements. (I just found this command myself.)
            if {[compare_collections $oref $pin1_ref] =3D=3D 0} {
                set pin1_arr [get_attribute $tpoint_ref arrival]
            }
            if {[compare_collections $oref $pin2_ref] =3D=3D 0} {
                set pin2_arr [get_attribute $tpoint_ref arrival]
            }
        }
        # This expression should always work because you explicitly
        # specified a path including both pin1_ref and pin2_ref. You could
        # always add error checking to cover pathological cases where PT
        # is returning junk.
        set dly [expr $pin2_arr - $pin1_arr]

        if {$min_max =3D=3D "min"} {
            if {($wst_dly =3D=3D "") || ($wst_dly > $dly)} {
                set wst_dly $dly
            }
        } else { # $min_max =3D=3D "max" or anything else
            if {($wst_dly =3D=3D "") || ($wst_dly < $dly)} {
                set wst_dly $dly
            }
        }
    }
    return $wst_dly
  }

Call this routine as:

            pin2pin_dly max [get_pins foo] [get_pins bar]

and it will return the worst-case max_delay between the pins "foo" and
"bar".  Use "min" instead of "max", and you should get the worst-case
min_delay.  I just tested it on one or two paths in my design, and it
looks like it works.

Possible improvements would allow passing in pin names instead of
references, but I'll leave that as an exercise for the student.  (Hint:
When a variable contains a collection, its value always begins with
"_sel".)

Hope this proves useful.

    - Eric Petrich
      Intel Corp.                                Santa Clara, CA

         ----    ----    ----    ----    ----    ----   ----

From: Tom Arneberg <toma=user domain=sgi spot calm>
To: Eric Petrich <eric.petrich=user domain=intel spot calm>

Thanks for your reply, Eric!

Your use of "compare_collections" answered one of my questions, which is
how to compare two objects without having to get the "full_name" attribute
of each.

After I wrote my original post but before it appeared on ESNUG, I figured
out about getting a timing path "-through" both pins.  D'OH!

As to your suggestion to use attributes like "max_fall_arrival", I noticed
those earlier.  It would be great if they would work, but they're not
defined for me:

  pt_shell> get_attribute [get_pins $pin] max_fall_arrival
  Warning: Attribute 'max_fall_arrival' does not exist on pin
  'core_nl5_n5_phy_lpc_support_U196/Q' (ATTR-3)

I don't know for sure, but I am guessing that those are CONSTRAINTS rather
than RESULTS.  I am learning that PrimeTime has a different philosophy than
Einstimer -- keep less info around (such as earliest and latest arrival time
for each pin), so it can be faster and use less memory.  Not necessarily a
bad design decision, but it does make the user do a bit more work to extract
desired information at times.

    - Tom Arneberg
      SGI                                        Chippewa Falls, WI

         ----    ----    ----    ----    ----    ----   ----

From: Eric Petrich <eric.petrich=user domain=intel spot calm>
To: Tom Arneberg <toma=user domain=sgi spot calm>

Dear Tom,

I'm pretty sure that the "max_rise_arrival" attribute and its cohorts are
results, but it doesn't surprise me that they are sometimes not defined.
I'll not pretend to understand why, I have merely learned to accept it.

I have not worked with Einstimer, but I have heard comments similar to
yours from fellow engineers.  I agree that it's probably a matter of
design philosophy.

One thing I have noticed, and I figure I should pass on to you, is that
PrimeTime is good at telling you stuff about violations, but it's not very
good at telling you about what isn't violating.  I have faced questions
from managers along the lines of, "How many paths are passing?"  Perhaps
this is just a difficult question to answer in any case, but PT seems
particularly bad at it.

There's also the matter of what I call "the hole in the air".  If you have
a custom timing model for an I/O module, and that model neglects to assign
a timing check on an input pin, you will never know unless you review the
.lib.  PrimeTime doesn't say, "This pin doesn't have a check," because it
doesn't know that it *should* have a check.

This is a good thing insofar as it cuts down on false warnings about
"don't-care" pins, but it can cause quite a bit of consternation when
you realize you aren't timing what you think you're timing.

    - Eric Petrich
      Intel Corp.                                Santa Clara, CA

         ----    ----    ----    ----    ----    ----   ----

From: Tom Arneberg <toma=user domain=sgi spot calm>
To: Eric Petrich <eric.petrich=user domain=intel spot calm>

Well, Eric, at least they have the "report_analysis_coverage" command.  That
one gies you the number (and percentage) of untested checks for each type of
check.

    - Tom Arneberg
      SGI                                        Chippewa Falls, WI

         ----    ----    ----    ----    ----    ----   ----

From: Chris Papademetrious <chrispy=user domain=synopsys spot calm>

Hi John,

In PrimeTime, you can query arbitrary pins for their arrival times just
like in Einstimer.  The arrival times for all clock domains are stored in
a pin/port attribute called "arrival_window".  If edges from multiple
clock domains go through the pin, then the arrival_window attribute will
contain the window information for each clock domain.  This attribute
appears to be what you are most interested in.

In PrimeTime-SI, the default behavior is to store this attribute for all
pins since the arrival windows are used to calculate delta delays.  In
normal PrimeTime, the arrival windows are only saved at path endpoints
by default.  However, we can tell PrimeTime to save this information on
all pins by setting the following variable:

        set timing_save_pin_arrival_and_slack true

After an update_timing, you will be able to query the arrival_window
attribute on arbitrary pins:

     {{{wb_clk_i} pos_edge {min_r_f 3.87025 3.68215}
                           {max_r_f 19.6942 19.7574}}
          {{clk2} pos_edge {min_r_f 11.3601 7.84273}
                           {max_r_f 15.3953 10.6178}}}

Your procedure was using timing_paths.  Since the paths you are looking
at are simple buffer/inverter paths, you could actually use either paths
or arrival times to get the information you need.  I have written a Tcl
procedure get_arrival_from_window to make it easy to get these arrival
times.  For example, using the above attribute example, you can do these
in pt_shell>:

   get_arrival_from_window [get_pins wis/U2436/Y] -delay min 3.68215
   get_arrival_from_window [get_pins wis/U2436/Y] -delay max 19.7574
   get_arrival_from_window [get_pins wis/U2436/Y] \
                                    -delay min -clock {clk2} 7.84273
   get_arrival_from_window [get_pins wis/U2436/Y] \
                                    -delay max -clock {clk2} 15.3953

Here's the Tcl procedure:

  # get_arrival_from_window.tcl
  #  parse arrival_window attribute to get arrivals of interest
  #
  # v1.0  02/01/2006 chrispy
  #  initial release

  proc get_arrival_from_window {args} {
   set results(-delay_type) max
   set results(-clock) {}
   set results(-edge) {rise fall}
   parse_proc_arguments -args $args results

   set windows [lindex [get_attribute -quiet $results(object) \
                arrival_window] 0]
   if {$windows eq {}} {
    error "Unable to find arrival windows"
   }

   set arrival {}
   foreach window $windows {
    set clock [lindex $window 0]
    if {$results(-clock) ne {} && $results(-clock) ne $clock} {continue}
    set rf_index(rise) 1
    set rf_index(fall) 2
    foreach rf $results(-edge) {
     switch $results(-delay_type) {
      min {
       set this_arrival [lindex [lindex $window 2] $rf_index($rf)]
       if {[string is double $this_arrival] && ($arrival eq {} || \
           $this_arrival < $arrival)} { set arrival $this_arrival }
      }
      max {
       set this_arrival [lindex [lindex $window 3] $rf_index($rf)]
       if {[string is double $this_arrival] && ($arrival eq {} || \
           $this_arrival > $arrival)} { set arrival $this_arrival }
      }
     }
    }
   }
   return $arrival
  }

  define_proc_attributes get_arrival_from_window \
   -info "Get min/max rise/fall arrival for pin/port" \
   -define_args \
   {
    {object "Pin or port object" {} string required}
    {-delay_type "Type of arrival time to analyze" type one_of_string
    {optional value_help {values {min max}}}}
    {-edge "Specify only rise or fall arrival time" rise_or_fall \
    one_of_string
    {optional value_help {values {rise fall}}}}
    {-clock "Use only arrivals for this clock domain" \
    "clock_domain" string optional}
  }

Here are some answers to Tom's questions:

> Is there a better way to compare two objects, other than to get the
> full_name of each and compare those strings?

Tom can use the compare_collection command to see if two objects are the
same object.  Note that if you are walking through the points list of a
timing_path, you will need to compare the *object* of the point, not the
points themselves.

> Why is there only one "arrival" time, and not one for rise and one
> for fall?  I want to get the worst delay from  pin1 to pin2, so I
> thought I'd have to do one rise and one fall and take the max delay.
> (I thought there'd be two timing paths -- one for rise, one for fall.)

For a timing path, there is only one arrival time because a timing path
is a single sensitized path of propagation.  Along each edge of a
timing_path object, you will only have a rise or fall transition (denoted
by each point's "rise_fall" attribute).  The arrival_window attributes,
since they are global and not per-path, obviously have both rise and fall
values.  This attribute appears to be what Tom is interested in.

  - Chris Papademetrious
    Synopsys PrimeTime CAE                       Allentown, PA
Index    Next->Item








   
 Sign up for the DeepChip newsletter.
Email
 Read what EDA tool users really think.


Feedback About Wiretaps ESNUGs SIGN UP! Downloads Trip Reports Advertise

"Relax. This is a discussion. Anything said here is just one engineer's opinion. Email in your dissenting letter and it'll be published, too."
This Web Site Is Modified Every 2-3 Days
Copyright 1991-2024 John Cooley.  All Rights Reserved.
| Contact John Cooley | Webmaster | Legal | Feedback Form |

   !!!     "It's not a BUG,
  /o o\  /  it's a FEATURE!"
 (  >  )
  \ - / 
  _] [_     (jcooley 1991)