Repository navigation
Sta upstream 10/05 - #422
dsengupta0628 wants to merge 18 commits into
Conversation
Signed-off-by: James Cherry <34749589+jjcherry56@users.noreply.github.com>
Signed-off-by: James Cherry <34749589+jjcherry56@users.noreply.github.com>
Signed-off-by: James Cherry <34749589+jjcherry56@users.noreply.github.com>
Signed-off-by: James Cherry <34749589+jjcherry56@users.noreply.github.com>
Signed-off-by: James Cherry <34749589+jjcherry56@users.noreply.github.com>
Signed-off-by: James Cherry <34749589+jjcherry56@users.noreply.github.com>
Signed-off-by: James Cherry <34749589+jjcherry56@users.noreply.github.com>
Signed-off-by: James Cherry <34749589+jjcherry56@users.noreply.github.com>
Signed-off-by: James Cherry <34749589+jjcherry56@users.noreply.github.com>
…(#521) * fix for issue 389 Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com> * use libs from test/ dir not examples/ Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com> * Remove port_direction_reinit test initSta() is intended to be called once per process; the test exercised unsupported re-initialization. * Remove PortDirection::init/destroy Singletons are static objects; nothing to allocate or free. --------- Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com>
* Report the tcl traceback for an error while reading a file include_file reads a file one complete command at a time and evaluates each with catch, so the errorInfo tcl builds for a command that fails is only reachable there. It is discarded, and the error is reported as a single line naming the file and line but not the procs that raised it. sta_error_traceback, 0 by default, keeps it. catch is given its options dict and -errorinfo is used in place of the bare result; since errorInfo begins with the error message, the existing check that prepends the file and line only once is unaffected, and both the sta_continue_on_error report and the raise at the end of the file pick it up. The uplevel frames include_file itself adds are trimmed from the end so the traceback ends at the command read from the file. With the variable at 0 the reported text is unchanged. Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com> * Report the start line of an incomplete command Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com> * Report the start line of a multi-line command that failed include_line counts lines as they are read, so by the time a command spanning several lines runs it names the command's last line. An error inside an if that opens on line 3 and closes on line 7 was reported as line 7, and a warning from a command continued across lines 14 to 18 as line 18. cmd_start_line holds the first line of the command being accumulated. include_file reports it, and sdc_file_line returns it so the messages raised with a msg id while reading a file use it as well. Single line commands are unaffected. write_path_spice_arc_sense.ok is the one golden whose warning moves, from the last line of the command to the line the command starts on. Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com> * Report a multi-line command error at its first line When reading stops at the first error, include_file built the message with include_line, the last line of the failing command. Use cmd_start_line, as the continue-on-error message and sdc_file_line do. Remove the sta_error_traceback docs and test, superseded by the $errorInfo traceback in 1b066c3. Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com> * Clear include_error_info at the start of include_file include_file saves the failing command's traceback in include_error_info, but only include clears it. read_sdc calls include_file directly, so after a failed read_sdc the traceback was left behind and reused by a later include error with no traceback of its own (e.g. cannot open the file). Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com> --------- Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com>
Signed-off-by: James Cherry <34749589+jjcherry56@users.noreply.github.com>
PortDirection::init/destroy were removed in f3cd9b1 (#521); the directions are now static objects that need no initialization. Drop the stale init() calls and the null-check guards around them. Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com>
MultiDrvrNet::dcalcDrvr/setDcalcDrvr were removed in bdd66c5 ("dcalc multi-drvr do not use levels") and replaced by loadSlewsInited/setLoadSlewsInited. Retarget the accessor tests to the new API. Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com>
Sta::findDelays() now passes Graph::vertex_level_max instead of levelize_->maxLevel() (e3326b0), so the delay_calc debug message reports level 16777215. Timing results are unchanged. Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com>
There was a problem hiding this comment.
Code Review
This pull request refactors several core components of the timing analysis engine, including replacing dynamic PortDirection singletons with static constexpr instances, optimizing levelization with lazy initialization, adding port limit calculations to timing models, and improving Tcl error tracebacks. However, several critical issues were identified in the review: a performance bottleneck in findCrpr due to heap allocations and O(N log N) complexity from std::map, a typo in Levelize::findBackEdges that iterates over roots_ instead of the sorted roots sequence (introducing non-determinism), a bug in zeroSlewAndWireDelays where passing true for merge prevents proper zeroing, and variable shadowing of pin in setPortLimits.
| std::map<const Pin*, const Path*> src_pin_map; | ||
| const Path *src = src_clk_path1; | ||
| while (src && !src->isNull()) { | ||
| src_pin_map[src->pin(this)] = src; | ||
| src = src->prevPath(); | ||
| } | ||
|
|
||
| const Path *tgt = tgt_clk_path1; | ||
| src = nullptr; | ||
| Pin *tgt_pin = nullptr; | ||
| while (tgt && !tgt->isNull()) { | ||
| tgt_pin = tgt->pin(this); | ||
| auto src_itr = src_pin_map.find(tgt_pin); | ||
| if (src_itr != src_pin_map.end()) { | ||
| src = src_itr->second; | ||
| break; | ||
| } | ||
| tgt = tgt->prevPath(); | ||
| } |
There was a problem hiding this comment.
Using std::map here introduces findCrpr is called frequently during timing analysis, this can be a significant performance bottleneck.\n\nSince the clock path is a tree and prevPath() acts as a parent pointer, finding the common pin is equivalent to finding the Lowest Common Ancestor (LCA) of two nodes in a tree. We can achieve this in
int src_len = 0;
const Path *src_curr = src_clk_path1;
while (src_curr && !src_curr->isNull()) {
src_len++;
src_curr = src_curr->prevPath();
}
int tgt_len = 0;
const Path *tgt_curr = tgt_clk_path1;
while (tgt_curr && !tgt_curr->isNull()) {
tgt_len++;
tgt_curr = tgt_curr->prevPath();
}
const Path *src = src_clk_path1;
const Path *tgt = tgt_clk_path1;
if (src_len > tgt_len) {
for (int i = 0; i < src_len - tgt_len; ++i) {
src = src->prevPath();
}
} else if (tgt_len > src_len) {
for (int i = 0; i < tgt_len - src_len; ++i) {
tgt = tgt->prevPath();
}
}
Pin *tgt_pin = nullptr;
while (src && !src->isNull() && tgt && !tgt->isNull()) {
if (src->pin(this) == tgt->pin(this)) {
tgt_pin = tgt->pin(this);
break;
}
src = src->prevPath();
tgt = tgt->prevPath();
}| VertexSeq roots = sortedRootsWithFanout(); | ||
| for (Vertex *vertex : roots_) { |
There was a problem hiding this comment.
There is a typo here: the code initializes a local roots sequence sorted by fanout to ensure deterministic traversal, but then iterates over the member variable roots_ instead. Since roots_ is a VertexSet (which may be ordered by pointer addresses or unordered), iterating over it directly can introduce non-determinism in the DFS traversal and loop-breaking order.
VertexSeq roots = sortedRootsWithFanout();
for (Vertex *vertex : roots) {There was a problem hiding this comment.
likely typo upstream- needs fixing
| annotateLoadDelaySlew(drvr_vertex, wire_edge, delay_zero, | ||
| load_vertex, delay_zero, | ||
| true, rf, min_max, ap_index); |
There was a problem hiding this comment.
In zeroSlewAndWireDelays, passing true for the merge parameter to annotateLoadDelaySlew is a bug. The purpose of this function is to unconditionally reset/zero the downstream wire delays and slews (as done in the original code). If merge is true, the values will only be updated if they satisfy the delayGreater condition, which prevents them from being reset to 0.0 if they already have non-zero values. This should be false to match the original unconditional zeroing behavior.
annotateLoadDelaySlew(drvr_vertex, wire_edge, delay_zero,
load_vertex, delay_zero,
false, rf, min_max, ap_index);| const Pin *pin = pin_iter->next(); | ||
| const LibertyPort *port = network_->libertyPort(pin); |
|
Have you checked for QoR impact? |
not yet- there seems to be a correctness issue that I have raised with upstream. will wait for that before overloading CI with runs |
Latest STA from 10/05 morning upstream