Compare commits

...

9 Commits

Author SHA1 Message Date
Mike-debug 8280929182
Merge 7c540b9b5f into 254d090582 2025-10-27 19:52:26 +05:30
Matt Liberty 254d090582 Replace deprecated isGroupPathName with isPathGroupName
Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
2025-10-27 00:14:56 +00:00
Matt Liberty 8df87e07a1 Merge remote-tracking branch 'upstream/master' 2025-10-26 22:50:15 +00:00
James Cherry de0f5440a6 Sta::isPathGroupName
Signed-off-by: James Cherry <cherry@parallaxsw.com>
2025-10-26 09:23:16 -07:00
James Cherry 8fb0cc305d Sta::endpointSlack
Signed-off-by: James Cherry <cherry@parallaxsw.com>
2025-10-25 11:44:23 -07:00
James Cherry 79ddebf153 Sta::endpointSlack
Signed-off-by: James Cherry <cherry@parallaxsw.com>
2025-10-25 11:27:01 -07:00
James Cherry 525c2efb3d Sta::endpointSlack
Signed-off-by: James Cherry <cherry@parallaxsw.com>
2025-10-25 10:02:34 -07:00
James Cherry 6e29fcb3f0 findRequired(vertex) rm crpr disable
Signed-off-by: James Cherry <cherry@parallaxsw.com>
2025-10-24 08:47:07 -07:00
mike_debug 7c540b9b5f debug_DispatchQueue_ThreadPool_DeadLock 2025-05-30 09:57:19 +08:00
12 changed files with 209 additions and 85 deletions

View File

@ -594,7 +594,6 @@ Graph::deletePaths(Vertex *vertex)
{
vertex->setPaths(nullptr);
vertex->tag_group_index_ = tag_group_index_max;
vertex->crpr_path_pruning_disabled_ = false;
}
////////////////////////////////////////////////////////////////
@ -998,7 +997,6 @@ Vertex::init(Pin *pin,
visited1_ = false;
visited2_ = false;
bfs_in_queue_ = 0;
crpr_path_pruning_disabled_ = false;
}
Vertex::~Vertex()
@ -1120,12 +1118,6 @@ Vertex::removeSlewAnnotated()
slew_annotated_ = 0;
}
void
Vertex::setCrprPathPruningDisabled(bool disabled)
{
crpr_path_pruning_disabled_ = disabled;
}
TagGroupIndex
Vertex::tagGroupIndex() const
{

View File

@ -304,8 +304,6 @@ public:
bool bfsInQueue(BfsIndex index) const;
void setBfsInQueue(BfsIndex index, bool value);
bool isRegClk() const { return is_reg_clk_; }
bool crprPathPruningDisabled() const { return crpr_path_pruning_disabled_;}
void setCrprPathPruningDisabled(bool disabled);
// ObjectTable interface.
ObjectIdx objectIdx() const { return object_idx_; }
@ -353,7 +351,6 @@ protected:
bool is_check_clk_:1;
bool is_constrained_:1;
bool has_downstream_clk_pin_:1;
bool crpr_path_pruning_disabled_:1;
bool visited1_:1;
bool visited2_:1;

View File

@ -134,8 +134,12 @@ public:
PathGroup *findPathGroup(const Clock *clock,
const MinMax *min_max) const;
PathGroup *pathGroup(const PathEnd *path_end) const;
static bool isGroupPathName(const char *group_name);
static std::string pathGroupName(const PathEnd *path_end,
const StaState *sta);
static const char *asyncPathGroupName() { return async_group_name_; }
static const char *pathDelayGroupName() { return path_delay_group_name_; }
static const char *gatedClkGroupName() { return gated_clk_group_name_; }
static const char *unconstrainedGroupName() { return unconstrained_group_name_; }
protected:
void makeGroupPathEnds(ExceptionTo *to,
@ -175,7 +179,8 @@ protected:
const MinMax *min_max);
bool reportGroup(const char *group_name,
PathGroupNameSet *group_names) const;
GroupPath *groupPathTo(const PathEnd *path_end) const;
static GroupPath *groupPathTo(const PathEnd *path_end,
const StaState *sta);
int group_path_count_;
int endpoint_path_count_;

View File

@ -73,6 +73,7 @@ typedef InstanceSeq::Iterator SlowDrvrIterator;
typedef Vector<const char*> CheckError;
typedef Vector<CheckError*> CheckErrorSeq;
typedef Vector<Corner*> CornerSeq;
typedef std::vector<std::string> StdStringSeq;
enum class CmdNamespace { sta, sdc };
@ -516,7 +517,10 @@ public:
ExceptionThruSeq *thrus,
ExceptionTo *to,
const char *comment);
bool isGroupPathName(const char *group_name);
// Deprecated 10/24/2025
bool isGroupPathName(const char *group_name) __attribute__ ((deprecated));
bool isPathGroupName(const char *group_name) const;
StdStringSeq pathGroupNames() const;
void resetPath(ExceptionFrom *from,
ExceptionThruSeq *thrus,
ExceptionTo *to,
@ -1002,6 +1006,10 @@ public:
const MinMax *min_max);
Slack pinSlack(const Pin *pin,
const MinMax *min_max);
// Worst slack for an endpoint in a path group.
Slack endpointSlack(const Pin *pin,
const std::string &path_group_name,
const MinMax *min_max);
Slack vertexSlack(Vertex *vertex,
const MinMax *min_max);
Slack vertexSlack(Vertex *vertex,
@ -1437,8 +1445,6 @@ protected:
Corner *corner,
const MinMax *min_max);
void powerPreamble();
void disableFanoutCrprPruning(Vertex *vertex,
int &fanou);
virtual void replaceCell(Instance *inst,
Cell *to_cell,
LibertyCell *to_lib_cell);

View File

@ -734,7 +734,7 @@ make_group_path(const char *name,
bool
is_path_group_name(const char *name)
{
return Sta::sta()->isGroupPathName(name);
return Sta::sta()->isPathGroupName(name);
}
ExceptionFrom *
@ -863,7 +863,7 @@ set_clock_sense_cmd(PinSet *pins,
else if (stop_propagation)
sta->setClockSense(pins, clks, ClockSense::stop);
else
sta->report()->critical(1577, "unknown clock sense");
sta->report()->critical(2123, "unknown clock sense");
}
void
@ -1328,7 +1328,7 @@ filter_timing_arcs(const char *property,
////////////////////////////////////////////////////////////////
StringSeq
path_group_names()
group_path_names()
{
StringSeq pg_names;
for (auto const& [name, group] : Sta::sta()->sdc()->groupPaths())

View File

@ -248,15 +248,6 @@ const char *PathGroups::gated_clk_group_name_ = "gated clock";
const char *PathGroups::async_group_name_ = "asynchronous";
const char *PathGroups::unconstrained_group_name_ = "unconstrained";
bool
PathGroups::isGroupPathName(const char *group_name)
{
return stringEq(group_name, path_delay_group_name_)
|| stringEq(group_name, gated_clk_group_name_)
|| stringEq(group_name, async_group_name_)
|| stringEq(group_name, unconstrained_group_name_);
}
PathGroups::PathGroups(int group_path_count,
int endpoint_path_count,
bool unique_pins,
@ -412,7 +403,7 @@ PathGroups::pathGroup(const PathEnd *path_end) const
{
const MinMax *min_max = path_end->minMax(this);
int mm_index = min_max->index();
GroupPath *group_path = groupPathTo(path_end);
GroupPath *group_path = groupPathTo(path_end, this);
if (path_end->isUnconstrained())
return unconstrained_[mm_index];
// GroupPaths have precedence.
@ -455,16 +446,63 @@ PathGroups::pathGroup(const PathEnd *path_end) const
}
}
// Mirrors PathGroups::pathGroup.
std::string
PathGroups::pathGroupName(const PathEnd *path_end,
const StaState *sta)
{
GroupPath *group_path = groupPathTo(path_end, sta);
if (path_end->isUnconstrained())
return unconstrained_group_name_;
// GroupPaths have precedence.
else if (group_path) {
if (group_path->isDefault())
return path_delay_group_name_;
else
return group_path->name();
}
else if (path_end->isCheck() || path_end->isLatchCheck()) {
const TimingRole *check_role = path_end->checkRole(sta);
const Clock *tgt_clk = path_end->targetClk(sta);
if (check_role == TimingRole::removal()
|| check_role == TimingRole::recovery())
return async_group_name_;
else
return tgt_clk->name();
}
else if (path_end->isOutputDelay()
|| path_end->isDataCheck())
return path_end->targetClk(sta)->name();
else if (path_end->isGatedClock())
return gated_clk_group_name_;
else if (path_end->isPathDelay()) {
// Path delays that end at timing checks are part of the target clk group
// unless -ignore_clock_latency is true.
PathDelay *path_delay = path_end->pathDelay();
const Clock *tgt_clk = path_end->targetClk(sta);
if (tgt_clk
&& !path_delay->ignoreClkLatency())
return tgt_clk->name();
else
return path_delay_group_name_;
}
else {
sta->report()->critical(1391, "unknown path end type");
return nullptr;
}
}
GroupPath *
PathGroups::groupPathTo(const PathEnd *path_end) const
PathGroups::groupPathTo(const PathEnd *path_end,
const StaState *sta)
{
const Path *path = path_end->path();
const Pin *pin = path->pin(this);
const Pin *pin = path->pin(sta);
ExceptionPath *exception =
search_->exceptionTo(ExceptionPathType::group_path, path,
pin, path->transition(this),
path_end->targetClkEdge(this),
path->minMax(this), false, false);
sta->search()->exceptionTo(ExceptionPathType::group_path, path,
pin, path->transition(sta),
path_end->targetClkEdge(sta),
path->minMax(sta), false, false);
return dynamic_cast<GroupPath*>(exception);
}

View File

@ -1182,7 +1182,6 @@ ArrivalVisitor::visit(Vertex *vertex)
visitFaninPaths(vertex);
if (crpr_active_
&& search_->crprPathPruningEnabled()
&& !vertex->crprPathPruningDisabled()
// No crpr for ideal clocks.
&& tag_bldr_->hasPropagatedClk()
&& !has_fanin_one_)

View File

@ -251,6 +251,31 @@ vertex_worst_slack_path(Vertex *vertex,
return sta->vertexWorstSlackPath(vertex, min_max);
}
Slack
endpoint_slack(const Pin *pin,
const char *path_group_name,
const MinMax *min_max)
{
Sta *sta = Sta::sta();
sta->ensureLibLinked();
if (sta->isPathGroupName(path_group_name)) {
Slack slack = sta->endpointSlack(pin, std::string(path_group_name), min_max);
return sta->units()->timeUnit()->staToUser(slack);
}
else {
sta->report()->error(1577, "%s is not a known path group name.",
path_group_name);
return INF;
}
}
StdStringSeq
path_group_names()
{
Sta *sta = Sta::sta();
return sta->pathGroupNames();
}
int
tag_group_count()
{

View File

@ -1990,9 +1990,35 @@ Sta::makeGroupPath(const char *name,
bool
Sta::isGroupPathName(const char *group_name)
{
return PathGroups::isGroupPathName(group_name)
|| sdc_->findClock(group_name)
|| sdc_->isGroupPathName(group_name);
return isPathGroupName(group_name);
}
bool
Sta::isPathGroupName(const char *group_name) const
{
return sdc_->findClock(group_name)
|| sdc_->isGroupPathName(group_name)
|| stringEq(group_name, PathGroups::asyncPathGroupName())
|| stringEq(group_name, PathGroups::pathDelayGroupName())
|| stringEq(group_name, PathGroups::gatedClkGroupName())
|| stringEq(group_name, PathGroups::unconstrainedGroupName());
}
StdStringSeq
Sta::pathGroupNames() const
{
StdStringSeq names;
for (const Clock *clk : *sdc_->clocks())
names.push_back(clk->name());
for (auto const &[name, group] : sdc_->groupPaths())
names.push_back(name);
names.push_back(PathGroups::asyncPathGroupName());
names.push_back(PathGroups::pathDelayGroupName());
names.push_back(PathGroups::gatedClkGroupName());
names.push_back(PathGroups::unconstrainedGroupName());
return names;
}
ExceptionFrom *
@ -3004,13 +3030,78 @@ Sta::pinSlack(const Pin *pin,
return slack;
}
////////////////////////////////////////////////////////////////
class EndpointPathEndVisitor : public PathEndVisitor
{
public:
EndpointPathEndVisitor(const std::string &path_group_name,
const MinMax *min_max,
const StaState *sta);
PathEndVisitor *copy() const;
void visit(PathEnd *path_end);
Slack slack() const { return slack_; }
private:
const std::string &path_group_name_;
const MinMax *min_max_;
Slack slack_;
const StaState *sta_;
};
EndpointPathEndVisitor::EndpointPathEndVisitor(const std::string &path_group_name,
const MinMax *min_max,
const StaState *sta) :
path_group_name_(path_group_name),
min_max_(min_max),
slack_(MinMax::min()->initValue()),
sta_(sta)
{
}
PathEndVisitor *
EndpointPathEndVisitor::copy() const
{
return new EndpointPathEndVisitor(path_group_name_, min_max_, sta_);
}
void
EndpointPathEndVisitor::visit(PathEnd *path_end)
{
if (path_end->minMax(sta_) == min_max_
&& PathGroups::pathGroupName(path_end, sta_) == path_group_name_) {
Slack end_slack = path_end->slack(sta_);
if (delayLess(end_slack, slack_, sta_))
slack_ = end_slack;
}
}
Slack
Sta::endpointSlack(const Pin *pin,
const std::string &path_group_name,
const MinMax *min_max)
{
ensureGraph();
Vertex *vertex = graph_->pinLoadVertex(pin);
if (vertex) {
findRequired(vertex);
VisitPathEnds visit_ends(this);
EndpointPathEndVisitor path_end_visitor(path_group_name, min_max, this);
visit_ends.visitPathEnds(vertex, &path_end_visitor);
return path_end_visitor.slack();
}
else
return INF;
}
////////////////////////////////////////////////////////////////
Slack
Sta::vertexSlack(Vertex *vertex,
const MinMax *min_max)
{
findRequired(vertex);
const MinMax *min = MinMax::min();
Slack slack = min->initValue();
Slack slack = MinMax::min()->initValue();
VertexPathIterator path_iter(vertex, this);
while (path_iter.hasNext()) {
Path *path = path_iter.next();
@ -3200,48 +3291,8 @@ Sta::findRequired(Vertex *vertex)
// Need to include downstream required times if there is fanout.
&& !hasFanout(vertex, search_->searchAdj(), graph_))
search_->seedRequired(vertex);
else {
else
search_->findRequireds(vertex->level());
if (variables_->crprEnabled()
&& search_->crprPathPruningEnabled()
&& !search_->crprApproxMissingRequireds()
// Clocks invariably have requireds that are pruned but it isn't
// worth finding arrivals and requireds all over again for
// the entire fanout of the clock.
&& !search_->isClock(vertex)) {
// Invalidate arrivals and requireds and disable
// path pruning on fanout vertices with DFS.
int fanout = 0;
disableFanoutCrprPruning(vertex, fanout);
debugPrint(debug_, "search", 1, "resurrect pruned required %s fanout %d",
vertex->to_string(this).c_str(),
fanout);
// Find fanout arrivals and requireds with pruning disabled.
search_->findArrivals();
search_->findRequireds(vertex->level());
}
}
}
void
Sta::disableFanoutCrprPruning(Vertex *vertex,
int &fanout)
{
if (!vertex->crprPathPruningDisabled()) {
search_->arrivalInvalid(vertex);
search_->requiredInvalid(vertex);
vertex->setCrprPathPruningDisabled(true);
fanout++;
SearchPred *pred = search_->searchAdj();
VertexOutEdgeIterator edge_iter(vertex, graph_);
while (edge_iter.hasNext()) {
Edge *edge = edge_iter.next();
Vertex *to_vertex = edge->to(graph_);
if (pred->searchThru(edge)
&& pred->searchTo(to_vertex))
disableFanoutCrprPruning(to_vertex, fanout);
}
}
}
Slack

View File

@ -322,6 +322,16 @@ using namespace sta;
Tcl_SetObjResult(interp, list);
}
%typemap(out) StdStringSeq {
StdStringSeq &strs = $1;
Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
for (const std::string &str : strs) {
Tcl_Obj *obj = Tcl_NewStringObj(str.c_str(), str.size());
Tcl_ListObjAppendElement(interp, list, obj);
}
Tcl_SetObjResult(interp, list);
}
%typemap(out) Library* {
Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj);

View File

@ -1,2 +1,2 @@
Initial path groups:
Final path groups: In2Out In2Reg Reg2Out Reg2Reg
Initial path groups: clk asynchronous {path delay} {gated clock} unconstrained
Final path groups: clk In2Out In2Reg Reg2Out Reg2Reg asynchronous {path delay} {gated clock} unconstrained

View File

@ -42,11 +42,12 @@ void
DispatchQueue::setThreadCount(size_t thread_count)
{
terminateThreads();
std::unique_lock<std::mutex> lock(lock_);
threads_.resize(thread_count);
for(size_t i = 0; i < thread_count; i++) {
threads_[i] = std::thread(&DispatchQueue::dispatch_thread_handler, this, i);
}
quit_ = false;
}
void