Merge remote-tracking branch 'parallax/master'

Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
This commit is contained in:
Matt Liberty 2025-05-16 04:12:02 +00:00
commit 65c2943191
20 changed files with 179 additions and 73 deletions

View File

@ -16,8 +16,7 @@ RUN apt-get update && \
bison \
flex \
automake \
autotools-dev \
valgrind
autotools-dev
# Download CUDD
RUN wget https://raw.githubusercontent.com/davidkebo/cudd/main/cudd_versions/cudd-3.0.0.tar.gz && \

View File

@ -194,7 +194,7 @@ following command builds a Docker image.
```
cd OpenSTA
docker build --file Dockerfile.ubuntu22.04 --tag OpenSTA .
docker build --file Dockerfile.ubuntu22.04 --tag opensta .
```
To run a docker container using the OpenSTA image, use the -v option
@ -202,7 +202,7 @@ to docker to mount direcories with data to use and -i to run
interactively.
```
docker run -i -v $HOME:/data OpenSTA
docker run -i -v $HOME:/data opensta
```
## Build on Macos/Darwin

View File

@ -209,14 +209,14 @@ public:
virtual VertexVisitor *copy() const;
protected:
GraphDelayCalc *graph_delay_calc1_;
GraphDelayCalc *graph_delay_calc_;
ArcDelayCalc *arc_delay_calc_;
};
FindVertexDelays::FindVertexDelays(GraphDelayCalc *graph_delay_calc1) :
FindVertexDelays::FindVertexDelays(GraphDelayCalc *graph_delay_calc) :
VertexVisitor(),
graph_delay_calc1_(graph_delay_calc1),
arc_delay_calc_(graph_delay_calc1_->arc_delay_calc_->copy())
graph_delay_calc_(graph_delay_calc),
arc_delay_calc_(graph_delay_calc_->arc_delay_calc_->copy())
{
}
@ -230,13 +230,13 @@ FindVertexDelays::copy() const
{
// Copy StaState::arc_delay_calc_ because it needs separate state
// for each thread.
return new FindVertexDelays(graph_delay_calc1_);
return new FindVertexDelays(graph_delay_calc_);
}
void
FindVertexDelays::visit(Vertex *vertex)
{
graph_delay_calc1_->findVertexDelay(vertex, arc_delay_calc_, true);
graph_delay_calc_->findVertexDelay(vertex, arc_delay_calc_, true);
}
// The logical structure of incremental delay calculation closely

View File

@ -6,6 +6,10 @@ This file summarizes user visible changes for each release.
Realase 2.6.1 2025/03/30
-------------------------
The -list_annotated and -list_not_annotated arguments to the
report_annotated_delay and report_annotated_check commands have been renamed to
-report_annotated and -report_unannotated.
The Tcl "source" command is no longer redefined to support "-echo" and
"-verbose" arguments and redirecton. Use the "include" command instead.

Binary file not shown.

Binary file not shown.

View File

@ -359,6 +359,7 @@ public:
void reportArrivals(Vertex *vertex) const;
Slack wnsSlack(Vertex *vertex,
PathAPIndex path_ap_index);
void levelsChangedBefore();
void levelChangedBefore(Vertex *vertex);
void seedInputArrival(const Pin *pin,
Vertex *vertex,

View File

@ -42,7 +42,11 @@ proc_redirect report_instance {
sta_warn 234 "report_instance -verbose is deprecated."
}
set instance_path [lindex $args 0]
set instance [find_instance $instance_path]
if { [is_object $instance_path] } {
set instance $instance_path
} else {
set instance [find_instance $instance_path]
}
if { $instance != "NULL" } {
report_instance1 $instance
} else {

View File

@ -3530,7 +3530,7 @@ proc set_wire_load_selection_group { args } {
################################################################
define_cmd_args "set_voltage" \
{[-min min_case_value] [-object_list list_of_power_nets] max_case_voltage}
{[-min min_case_value] [-object_list power_nets] max_case_voltage}
proc set_voltage { args } {
parse_key_args "set_voltage" args keys {-min -object_list} flags {}

View File

@ -65,12 +65,13 @@ proc_redirect read_sdf {
define_cmd_args "report_annotated_delay" \
{[-cell] [-net] [-from_in_ports] [-to_out_ports] [-max_lines lines]\
[-list_annotated] [-list_not_annotated] [-constant_arcs]}
[-report_annotated] [-report_unannotated] [-constant_arcs]}
proc_redirect report_annotated_delay {
parse_key_args "report_annotated_delay" args keys {-max_lines} \
flags {-cell -net -from_in_ports -to_out_ports -list_annotated \
-list_not_annotated -constant_arcs}
flags {-cell -net -from_in_ports -to_out_ports \
-report_annotated -report_unannotated -constant_arcs \
-list_not_annotated -list_annotated}
if { [info exists flags(-cell)] || [info exists flags(-net)] \
|| [info exists flags(-from_in_ports)] \
|| [info exists flags(-to_out_ports)] } {
@ -91,22 +92,35 @@ proc_redirect report_annotated_delay {
check_positive_integer "-max_lines" $max_lines
}
set report_annotated [info exists flags(-report_annotated)]
if { [info exists flags(-list_annotated)] } {
# Deprecated 05/26/2025
sta_warn 624 "-list_annotated is deprecated. Use -report_annotated."
set report_annotated 1
}
set report_unannotated [info exists flags(-report_unannotated)]
if { [info exists flags(-list_not_annotated)] } {
# Deprecated 05/26/2025
sta_warn 625 "-list_not_annotated is deprecated. Use -report_unannotated."
set report_unannotated 1
}
report_annotated_delay_cmd $report_cells $report_nets \
$report_in_nets $report_out_nets \
$max_lines [info exists flags(-list_annotated)] \
[info exists flags(-list_not_annotated)] \
$max_lines $report_annotated $report_unannotated \
[info exists flags(-constant_arcs)]
}
define_cmd_args "report_annotated_check" \
{[-setup] [-hold] [-recovery] [-removal] [-nochange] [-width] [-period]\
[-max_skew] [-max_lines lines] [-list_annotated] [-list_not_annotated]\
[-max_skew] [-max_lines lines] [-report_annotated] [-report_unannotated]\
[-constant_arcs]}
proc_redirect report_annotated_check {
parse_key_args "report_annotated_check" args keys {-max_lines} \
flags {-setup -hold -recovery -removal -nochange -width -period \
-max_skew -list_annotated -list_not_annotated -constant_arcs}
-max_skew -report_annotated -report_unannotated -constant_arcs \
-list_annotated -list_not_annotated}
if { [info exists flags(-setup)] || [info exists flags(-hold)] \
|| [info exists flags(-recovery)] || [info exists flags(-removal)] \
|| [info exists flags(-nochange)] || [info exists flags(-width)] \
@ -136,11 +150,23 @@ proc_redirect report_annotated_check {
check_positive_integer "-max_lines" $max_lines
}
set report_annotated [info exists flags(-report_annotated)]
if { [info exists flags(-list_annotated)] } {
# Deprecated 05/26/2025
sta_warn 626 "-list_annotated is deprecated. Use -report_annotated."
set report_annotated 1
}
set report_unannotated [info exists flags(-report_unannotated)]
if { [info exists flags(-list_not_annotated)] } {
# Deprecated 05/26/2025
sta_warn 627 "-list_not_annotated is deprecated. Use -report_unannotated."
set report_unannotated 1
}
report_annotated_check_cmd $report_setup $report_hold \
$report_recovery $report_removal $report_nochange \
$report_width $report_period $report_max_skew \
$max_lines [info exists flags(-list_annotated)] \
[info exists flags(-list_not_annotated)] \
$max_lines $report_annotated $report_unannotated \
[info exists flags(-constant_arcs)]
}

View File

@ -34,15 +34,6 @@
namespace sta {
static bool
clkInfoEqual(const ClkInfo *clk_info1,
const ClkInfo *clk_info2,
const StaState *sta);
static int
clkInfoCmp(const ClkInfo *clk_info1,
const ClkInfo *clk_info2,
const StaState *sta);
ClkInfo::ClkInfo(const ClockEdge *clk_edge,
const Pin *clk_src,
bool is_propagated,
@ -210,7 +201,7 @@ ClkInfoEqual::operator()(const ClkInfo *clk_info1,
return clkInfoEqual(clk_info1, clk_info2, sta_);
}
static bool
bool
clkInfoEqual(const ClkInfo *clk_info1,
const ClkInfo *clk_info2,
const StaState *sta)
@ -253,7 +244,7 @@ ClkInfoLess::operator()(const ClkInfo *clk_info1,
return clkInfoCmp(clk_info1, clk_info2, sta_) < 0;
}
static int
int
clkInfoCmp(const ClkInfo *clk_info1,
const ClkInfo *clk_info2,
const StaState *sta)

View File

@ -93,6 +93,15 @@ private:
unsigned int path_ap_index_:path_ap_index_bit_count;
};
int
clkInfoCmp(const ClkInfo *clk_info1,
const ClkInfo *clk_info2,
const StaState *sta);
bool
clkInfoEqual(const ClkInfo *clk_info1,
const ClkInfo *clk_info2,
const StaState *sta);
class ClkInfoLess
{
public:

View File

@ -122,6 +122,8 @@ Levelize::levelize()
Stats stats(debug_, report_);
debugPrint(debug_, "levelize", 1, "levelize");
clear();
if (observer_)
observer_->levelsChangedBefore();
VertexIterator vertex_iter(graph_);
while (vertex_iter.hasNext()) {
@ -135,7 +137,7 @@ Levelize::levelize()
findRoots();
findBackEdges();
VertexSeq topo_sorted = findToplologicalOrder();
VertexSeq topo_sorted = findTopologicalOrder();
assignLevels(topo_sorted);
ensureLatchLevels();
@ -345,7 +347,7 @@ Levelize::findUnvisitedVertices()
////////////////////////////////////////////////////////////////
VertexSeq
Levelize::findToplologicalOrder()
Levelize::findTopologicalOrder()
{
Stats stats(debug_, report_);
std::map<Vertex*, int> in_degree;
@ -545,6 +547,19 @@ Levelize::ensureLatchLevels()
latch_d_to_q_edges_.clear();
}
void
Levelize::setLevel(Vertex *vertex,
Level level)
{
debugPrint(debug_, "levelize", 2, "set level %s %d",
vertex->to_string(this).c_str(),
level);
vertex->setLevel(level);
max_level_ = max(level, max_level_);
if (level >= Graph::vertex_level_max)
criticalError(616, "maximum logic level exceeded");
}
void
Levelize::invalid()
{
@ -597,6 +612,8 @@ Levelize::deleteEdgeBefore(Edge *edge)
{
if (levelized_
&& loop_edges_.hasKey(edge)) {
debugPrint(debug_, "levelize", 2, "delete loop edge %s",
edge->to_string(this).c_str());
disabled_loop_edges_.erase(edge);
// Relevelize if a loop edge is removed. Incremental levelization
// fails because the DFS path will be missing.
@ -621,7 +638,7 @@ Levelize::relevelize()
vertex->to_string(this).c_str());
if (search_pred_.searchFrom(vertex)) {
if (isRoot(vertex)) {
setLevel(vertex, 0);
setLevelIncr(vertex, 0);
roots_->insert(vertex);
}
VertexSet visited(graph_);
@ -645,7 +662,7 @@ Levelize::visit(Vertex *vertex,
EdgeSeq &path)
{
Pin *from_pin = vertex->pin();
setLevel(vertex, level);
setLevelIncr(vertex, level);
level += level_space;
visited.insert(vertex);
path_vertices.insert(vertex);
@ -691,8 +708,8 @@ Levelize::isDisabledLoop(Edge *edge) const
}
void
Levelize::setLevel(Vertex *vertex,
Level level)
Levelize::setLevelIncr(Vertex *vertex,
Level level)
{
debugPrint(debug_, "levelize", 2, "set level %s %d",
vertex->to_string(this).c_str(),
@ -704,7 +721,7 @@ Levelize::setLevel(Vertex *vertex,
}
max_level_ = max(level, max_level_);
if (level >= Graph::vertex_level_max)
criticalError(616, "maximum logic level exceeded");
criticalError(617, "maximum logic level exceeded");
}
////////////////////////////////////////////////////////////////

View File

@ -74,7 +74,7 @@ protected:
void levelize();
void findRoots();
VertexSeq sortedRootsWithFanout();
VertexSeq findToplologicalOrder();
VertexSeq findTopologicalOrder();
void assignLevels(VertexSeq &topo_sorted);
void recordLoop(Edge *edge,
EdgeSeq &path);
@ -96,6 +96,8 @@ protected:
EdgeSeq &path);
void setLevel(Vertex *vertex,
Level level);
void setLevelIncr(Vertex *vertex,
Level level);
void clearLoopEdges();
void deleteLoops();
void reportPath(EdgeSeq &path) const;
@ -135,6 +137,7 @@ class LevelizeObserver
public:
LevelizeObserver() {}
virtual ~LevelizeObserver() {}
virtual void levelsChangedBefore() = 0;
virtual void levelChangedBefore(Vertex *vertex) = 0;
};

View File

@ -384,8 +384,8 @@ PathEnumFaninVisitor::visitFromToPath(const Pin *,
Vertex *to_vertex,
const RiseFall *to_rf,
Tag *to_tag,
Arrival &to_arrival,
const MinMax *min_max,
Arrival & /* to_arrival */,
const MinMax * /* min_max */,
const PathAnalysisPt *path_ap)
{
// These paths fanin to before_div_ so we know to_vertex matches.
@ -406,19 +406,9 @@ PathEnumFaninVisitor::visitFromToPath(const Pin *,
// Make the diverted path end to check slack with from_path crpr.
makeDivertedPathEnd(from_path, edge, arc, div_end, after_div_copy);
if (div_end) {
// Only enumerate paths with greater slack.
// fuzz for difference in updatePathHeadDelays and accumulated arrivals.
float fuzz = .001;
float slack_limit = path_end_slack_ > 0
? path_end_slack_ * (1.0 - fuzz)
: path_end_slack_ * (1.0 + fuzz);
if (delayGreaterEqual(div_end->slack(this), slack_limit, this)) {
reportDiversion(edge, arc, from_path);
path_enum_->makeDiversion(div_end, after_div_copy);
visited_fanins_.emplace(from_vertex, arc);
}
else
delete div_end;
reportDiversion(edge, arc, from_path);
path_enum_->makeDiversion(div_end, after_div_copy);
visited_fanins_.emplace(from_vertex, arc);
}
}
else
@ -426,8 +416,7 @@ PathEnumFaninVisitor::visitFromToPath(const Pin *,
edge->to_string(this).c_str(),
arc->to_string().c_str());
}
// Only enumerate slower/faster paths.
else if (delayLessEqual(to_arrival, before_div_arrival_, min_max, this)) {
else {
PathEnd *div_end;
Path *after_div_copy;
makeDivertedPathEnd(from_path, edge, arc, div_end, after_div_copy);

View File

@ -795,14 +795,30 @@ Search::arrivalInvalid(Vertex *vertex)
}
}
// Move any pending arrival/requireds to invalid before relevelization.
void
Search::levelsChangedBefore()
{
if (arrivals_exist_) {
while (arrival_iter_->hasNext()) {
Vertex *vertex = arrival_iter_->next();
arrivalInvalid(vertex);
}
while (required_iter_->hasNext()) {
Vertex *vertex = required_iter_->next();
requiredInvalid(vertex);
}
}
}
void
Search::levelChangedBefore(Vertex *vertex)
{
if (arrivals_exist_) {
arrival_iter_->remove(vertex);
required_iter_->remove(vertex);
search_->arrivalInvalid(vertex);
search_->requiredInvalid(vertex);
arrivalInvalid(vertex);
requiredInvalid(vertex);
}
}
@ -2760,6 +2776,30 @@ Search::setVertexArrivals(Vertex *vertex,
}
}
class ReportPathLess
{
public:
ReportPathLess(const StaState *sta);
bool operator()(const Path *path1,
const Path *path2) const;
private:
const StaState *sta_;
};
ReportPathLess::ReportPathLess(const StaState *sta) :
sta_(sta)
{
}
bool
ReportPathLess::operator()(const Path *path1,
const Path *path2) const
{
return tagCmp(path1->tag(sta_), path2->tag(sta_), sta_) < 0;
}
void
Search::reportArrivals(Vertex *vertex) const
{
@ -2767,9 +2807,14 @@ Search::reportArrivals(Vertex *vertex) const
TagGroup *tag_group = tagGroup(vertex);
if (tag_group) {
report_->reportLine("Group %u", tag_group->index());
std::vector<const Path*> paths;
VertexPathIterator path_iter(vertex, this);
while (path_iter.hasNext()) {
const Path *path = path_iter.next();
paths.push_back(path);
}
sort(paths.begin(), paths.end(), ReportPathLess(this));
for (const Path *path : paths) {
const Tag *tag = path->tag(this);
const PathAnalysisPt *path_ap = tag->pathAnalysisPt(this);
const RiseFall *rf = tag->transition();

View File

@ -210,7 +210,8 @@ class StaLevelizeObserver : public LevelizeObserver
{
public:
StaLevelizeObserver(Search *search);
virtual void levelChangedBefore(Vertex *vertex);
void levelsChangedBefore() override;
void levelChangedBefore(Vertex *vertex) override;
private:
Search *search_;
@ -221,6 +222,12 @@ StaLevelizeObserver::StaLevelizeObserver(Search *search) :
{
}
void
StaLevelizeObserver::levelsChangedBefore()
{
search_->levelsChangedBefore();
}
void
StaLevelizeObserver::levelChangedBefore(Vertex *vertex)
{

View File

@ -289,26 +289,31 @@ Tag::matchHash(bool match_crpr_clk_pin,
////////////////////////////////////////////////////////////////
TagLess::TagLess(const StaState *sta) :
sta_(sta)
{
}
bool
TagLess::operator()(const Tag *tag1,
const Tag *tag2) const
{
return tagCmp(tag1, tag2) < 0;
return tagCmp(tag1, tag2, sta_) < 0;
}
int
tagCmp(const Tag *tag1,
const Tag *tag2)
const Tag *tag2,
const StaState *sta)
{
if (tag1 == tag2)
return 0;
int rf_index1 = tag1->rfIndex();
int rf_index2 = tag2->rfIndex();
if (rf_index1 < rf_index2)
return -1;
if (rf_index1 > rf_index2)
return 1;
ClkInfo *clk_info1 = tag1->clkInfo();
ClkInfo *clk_info2 = tag2->clkInfo();
int clk_cmp = clkInfoCmp(clk_info1, clk_info2, sta);
if (clk_cmp != 0)
return clk_cmp;
PathAPIndex path_ap_index1 = tag1->pathAPIndex();
PathAPIndex path_ap_index2 = tag2->pathAPIndex();
@ -317,11 +322,11 @@ tagCmp(const Tag *tag1,
if (path_ap_index1 > path_ap_index2)
return 1;
size_t clk_info1 = tag1->clkInfo()->hash();
size_t clk_info2 = tag2->clkInfo()->hash();
if (clk_info1 < clk_info2)
int rf_index1 = tag1->rfIndex();
int rf_index2 = tag2->rfIndex();
if (rf_index1 < rf_index2)
return -1;
if (clk_info1 > clk_info2)
if (rf_index1 > rf_index2)
return 1;
bool is_clk1 = tag1->isClock();

View File

@ -112,8 +112,12 @@ private:
class TagLess
{
public:
TagLess(const StaState *sta);
bool operator()(const Tag *tag1,
const Tag *tag2) const;
private:
const StaState *sta_;
};
class TagIndexLess
@ -138,7 +142,8 @@ public:
int
tagCmp(const Tag *tag1,
const Tag *tag2);
const Tag *tag2,
const StaState *sta);
// Match tag clock edge, clock driver and exception states but not clk info.
bool

View File

@ -304,6 +304,7 @@ Report::critical(int /* id */,
printToBufferAppend(fmt, args);
printBufferLine();
va_end(args);
exit(1);
}
void