Skip to content

Commit 525c2ef

Browse files
committed
Sta::endpointSlack
Signed-off-by: James Cherry <[email protected]>
1 parent 6e29fcb commit 525c2ef

File tree

7 files changed

+160
-16
lines changed

7 files changed

+160
-16
lines changed

include/sta/PathGroup.hh

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ protected:
107107
class PathGroups : public StaState
108108
{
109109
public:
110+
PathGroups(const StaState *sta);
110111
PathGroups(int group_path_count,
111112
int endpoint_path_count,
112113
bool unique_pins,
@@ -134,8 +135,10 @@ public:
134135
PathGroup *findPathGroup(const Clock *clock,
135136
const MinMax *min_max) const;
136137
PathGroup *pathGroup(const PathEnd *path_end) const;
137-
static bool isGroupPathName(const char *group_name);
138138
static const char *asyncPathGroupName() { return async_group_name_; }
139+
static const char *pathDelayGroupName() { return path_delay_group_name_; }
140+
static const char *gatedClkGroupName() { return gated_clk_group_name_; }
141+
static const char *unconstrainedGroupName() { return unconstrained_group_name_; }
139142

140143
protected:
141144
void makeGroupPathEnds(ExceptionTo *to,

include/sta/Sta.hh

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ typedef InstanceSeq::Iterator SlowDrvrIterator;
7373
typedef Vector<const char*> CheckError;
7474
typedef Vector<CheckError*> CheckErrorSeq;
7575
typedef Vector<Corner*> CornerSeq;
76+
typedef std::vector<std::string> StdStringSeq;
7677

7778
enum class CmdNamespace { sta, sdc };
7879

@@ -516,7 +517,10 @@ public:
516517
ExceptionThruSeq *thrus,
517518
ExceptionTo *to,
518519
const char *comment);
519-
bool isGroupPathName(const char *group_name);
520+
// Deprecated 10/24/2025
521+
bool isGroupPathName(const char *group_name) __attribute__ ((deprecated));
522+
bool isPathGroupName(const char *group_name) const;
523+
StdStringSeq pathGroupNames() const;
520524
void resetPath(ExceptionFrom *from,
521525
ExceptionThruSeq *thrus,
522526
ExceptionTo *to,
@@ -1002,6 +1006,10 @@ public:
10021006
const MinMax *min_max);
10031007
Slack pinSlack(const Pin *pin,
10041008
const MinMax *min_max);
1009+
// Worst slack for an endpoint in a path group.
1010+
Slack endpointSlack(const Pin *pin,
1011+
const std::string &path_group_name,
1012+
const MinMax *min_max);
10051013
Slack vertexSlack(Vertex *vertex,
10061014
const MinMax *min_max);
10071015
Slack vertexSlack(Vertex *vertex,

sdc/Sdc.i

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -734,7 +734,7 @@ make_group_path(const char *name,
734734
bool
735735
is_path_group_name(const char *name)
736736
{
737-
return Sta::sta()->isGroupPathName(name);
737+
return Sta::sta()->isPathGroupName(name);
738738
}
739739

740740
ExceptionFrom *
@@ -863,7 +863,7 @@ set_clock_sense_cmd(PinSet *pins,
863863
else if (stop_propagation)
864864
sta->setClockSense(pins, clks, ClockSense::stop);
865865
else
866-
sta->report()->critical(1577, "unknown clock sense");
866+
sta->report()->critical(2123, "unknown clock sense");
867867
}
868868

869869
void
@@ -1328,7 +1328,7 @@ filter_timing_arcs(const char *property,
13281328
////////////////////////////////////////////////////////////////
13291329

13301330
StringSeq
1331-
path_group_names()
1331+
group_path_names()
13321332
{
13331333
StringSeq pg_names;
13341334
for (auto const& [name, group] : Sta::sta()->sdc()->groupPaths())

search/PathGroup.cc

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -248,13 +248,14 @@ const char *PathGroups::gated_clk_group_name_ = "gated clock";
248248
const char *PathGroups::async_group_name_ = "asynchronous";
249249
const char *PathGroups::unconstrained_group_name_ = "unconstrained";
250250

251-
bool
252-
PathGroups::isGroupPathName(const char *group_name)
251+
PathGroups::PathGroups(const StaState *sta) :
252+
StaState(sta),
253+
group_path_count_(0),
254+
endpoint_path_count_(0),
255+
unique_pins_(false),
256+
slack_min_(-INF),
257+
slack_max_(INF)
253258
{
254-
return stringEq(group_name, path_delay_group_name_)
255-
|| stringEq(group_name, gated_clk_group_name_)
256-
|| stringEq(group_name, async_group_name_)
257-
|| stringEq(group_name, unconstrained_group_name_);
258259
}
259260

260261
PathGroups::PathGroups(int group_path_count,

search/Search.i

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,31 @@ vertex_worst_slack_path(Vertex *vertex,
251251
return sta->vertexWorstSlackPath(vertex, min_max);
252252
}
253253

254+
Slack
255+
endpoint_slack(const Pin *pin,
256+
const char *path_group_name,
257+
const MinMax *min_max)
258+
{
259+
Sta *sta = Sta::sta();
260+
sta->ensureLibLinked();
261+
if (sta->isGroupPathName(path_group_name)) {
262+
Slack slack = sta->endpointSlack(pin, std::string(path_group_name), min_max);
263+
return sta->units()->timeUnit()->staToUser(slack);
264+
}
265+
else {
266+
sta->report()->error(1577, "%s is not a known path group name.",
267+
path_group_name);
268+
return INF;
269+
}
270+
}
271+
272+
StdStringSeq
273+
path_group_names()
274+
{
275+
Sta *sta = Sta::sta();
276+
return sta->pathGroupNames();
277+
}
278+
254279
int
255280
tag_group_count()
256281
{

search/Sta.cc

Lines changed: 102 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1990,9 +1990,35 @@ Sta::makeGroupPath(const char *name,
19901990
bool
19911991
Sta::isGroupPathName(const char *group_name)
19921992
{
1993-
return PathGroups::isGroupPathName(group_name)
1994-
|| sdc_->findClock(group_name)
1995-
|| sdc_->isGroupPathName(group_name);
1993+
return isPathGroupName(group_name);
1994+
}
1995+
1996+
bool
1997+
Sta::isPathGroupName(const char *group_name) const
1998+
{
1999+
return sdc_->findClock(group_name)
2000+
|| sdc_->isGroupPathName(group_name)
2001+
|| stringEq(group_name, PathGroups::asyncPathGroupName())
2002+
|| stringEq(group_name, PathGroups::pathDelayGroupName())
2003+
|| stringEq(group_name, PathGroups::gatedClkGroupName())
2004+
|| stringEq(group_name, PathGroups::asyncPathGroupName());
2005+
}
2006+
2007+
StdStringSeq
2008+
Sta::pathGroupNames() const
2009+
{
2010+
StdStringSeq names;
2011+
for (const Clock *clk : *sdc_->clocks())
2012+
names.push_back(clk->name());
2013+
2014+
for (auto const &[name, group] : sdc_->groupPaths())
2015+
names.push_back(name);
2016+
2017+
names.push_back(PathGroups::asyncPathGroupName());
2018+
names.push_back(PathGroups::pathDelayGroupName());
2019+
names.push_back(PathGroups::gatedClkGroupName());
2020+
names.push_back(PathGroups::unconstrainedGroupName());
2021+
return names;
19962022
}
19972023

19982024
ExceptionFrom *
@@ -3004,13 +3030,84 @@ Sta::pinSlack(const Pin *pin,
30043030
return slack;
30053031
}
30063032

3033+
////////////////////////////////////////////////////////////////
3034+
3035+
class EndpointPathEndVisitor : public PathEndVisitor
3036+
{
3037+
public:
3038+
EndpointPathEndVisitor(const std::string &path_group_name,
3039+
const PathGroups &path_groups,
3040+
const MinMax *min_max,
3041+
const StaState *sta);
3042+
PathEndVisitor *copy() const;
3043+
void visit(PathEnd *path_end);
3044+
Slack slack() const { return slack_; }
3045+
3046+
private:
3047+
const std::string &path_group_name_;
3048+
const PathGroups &path_groups_;
3049+
const MinMax *min_max_;
3050+
Slack slack_;
3051+
const StaState *sta_;
3052+
};
3053+
3054+
EndpointPathEndVisitor::EndpointPathEndVisitor(const std::string &path_group_name,
3055+
const PathGroups &path_groups,
3056+
const MinMax *min_max,
3057+
const StaState *sta) :
3058+
path_group_name_(path_group_name),
3059+
path_groups_(path_groups),
3060+
min_max_(min_max),
3061+
slack_(MinMax::min()->initValue()),
3062+
sta_(sta)
3063+
{
3064+
}
3065+
3066+
PathEndVisitor *
3067+
EndpointPathEndVisitor::copy() const
3068+
{
3069+
return new EndpointPathEndVisitor(path_group_name_, path_groups_, min_max_, sta_);
3070+
}
3071+
3072+
void
3073+
EndpointPathEndVisitor::visit(PathEnd *path_end)
3074+
{
3075+
if (path_end->minMax(sta_) == min_max_
3076+
&& path_groups_.pathGroup(path_end)->name() == path_group_name_) {
3077+
Slack end_slack = path_end->slack(sta_);
3078+
if (delayLess(end_slack, slack_, sta_))
3079+
slack_ = end_slack;
3080+
}
3081+
}
3082+
3083+
Slack
3084+
Sta::endpointSlack(const Pin *pin,
3085+
const std::string &path_group_name,
3086+
const MinMax *min_max)
3087+
{
3088+
ensureGraph();
3089+
Vertex *vertex = graph_->pinLoadVertex(pin);
3090+
if (vertex) {
3091+
findRequired(vertex);
3092+
// Make path groups to use PathGroups::pathGroup(PathEnd).
3093+
PathGroups path_groups(this);
3094+
VisitPathEnds visit_ends(this);
3095+
EndpointPathEndVisitor path_end_visitor(path_group_name, path_groups, min_max, this);
3096+
visit_ends.visitPathEnds(vertex, &path_end_visitor);
3097+
return path_end_visitor.slack();
3098+
}
3099+
else
3100+
return INF;
3101+
}
3102+
3103+
////////////////////////////////////////////////////////////////
3104+
30073105
Slack
30083106
Sta::vertexSlack(Vertex *vertex,
30093107
const MinMax *min_max)
30103108
{
30113109
findRequired(vertex);
3012-
const MinMax *min = MinMax::min();
3013-
Slack slack = min->initValue();
3110+
Slack slack = MinMax::min()->initValue();
30143111
VertexPathIterator path_iter(vertex, this);
30153112
while (path_iter.hasNext()) {
30163113
Path *path = path_iter.next();

tcl/StaTclTypes.i

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,16 @@ using namespace sta;
322322
Tcl_SetObjResult(interp, list);
323323
}
324324

325+
%typemap(out) StdStringSeq {
326+
StdStringSeq &strs = $1;
327+
Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
328+
for (const std::string &str : strs) {
329+
Tcl_Obj *obj = Tcl_NewStringObj(str.c_str(), str.size());
330+
Tcl_ListObjAppendElement(interp, list, obj);
331+
}
332+
Tcl_SetObjResult(interp, list);
333+
}
334+
325335
%typemap(out) Library* {
326336
Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
327337
Tcl_SetObjResult(interp, obj);

0 commit comments

Comments
 (0)