diff --git a/README b/README
index 1ecd713b..23f679da 100644
--- a/README
+++ b/README
@@ -15,7 +15,7 @@
# along with this program. If not, see .
Parallax Gate Level Static Timing Analyzer
- See INSTALL for build instructions.
+See INSTALL for installation and build instructions.
Standard file formats
Verilog
diff --git a/liberty/Liberty.cc b/liberty/Liberty.cc
index 68dba11c..7c835111 100644
--- a/liberty/Liberty.cc
+++ b/liberty/Liberty.cc
@@ -135,6 +135,14 @@ LibertyLibrary::~LibertyLibrary()
deleteEquivCellMap(equiv_cell_map_);
delete units_;
ocv_derate_map_.deleteContents();
+
+ SupplyVoltageMap::Iterator supply_iter(supply_voltage_map_);
+ while (supply_iter.hasNext()) {
+ const char *supply_name;
+ float voltage;
+ supply_iter.next(supply_name, voltage);
+ stringDelete(supply_name);
+ }
}
LibertyCell *
@@ -762,6 +770,19 @@ LibertyLibrary::addOcvDerate(OcvDerate *derate)
ocv_derate_map_[derate->name()] = derate;
}
+void
+LibertyLibrary::addSupplyVoltage(const char *supply_name,
+ float voltage)
+{
+ supply_voltage_map_[stringCopy(supply_name)] = voltage;
+}
+
+float
+LibertyLibrary::supplyVoltage(const char *supply_name)
+{
+ return supply_voltage_map_[supply_name];
+}
+
////////////////////////////////////////////////////////////////
LibertyCellIterator::LibertyCellIterator(const LibertyLibrary *
diff --git a/liberty/Liberty.hh b/liberty/Liberty.hh
index d8cb89a6..de013de5 100644
--- a/liberty/Liberty.hh
+++ b/liberty/Liberty.hh
@@ -68,6 +68,7 @@ typedef Map LatchEnableMap;
typedef Map OcvDerateMap;
typedef Vector TimingArcAttrsSeq;
typedef Vector InternalPowerAttrsSeq;
+typedef Map SupplyVoltageMap;
typedef enum {
clock_gate_none,
@@ -263,6 +264,9 @@ public:
void setDefaultOcvDerate(OcvDerate *derate);
OcvDerate *findOcvDerate(const char *derate_name);
void addOcvDerate(OcvDerate *derate);
+ void addSupplyVoltage(const char *suppy_name,
+ float voltage);
+ float supplyVoltage(const char *suppy_name);
// Make scaled cell. Call LibertyCell::addScaledCell after it is complete.
LibertyCell *makeScaledCell(const char *name,
@@ -323,6 +327,7 @@ protected:
float ocv_arc_depth_;
OcvDerate *default_ocv_derate_;
OcvDerateMap ocv_derate_map_;
+ SupplyVoltageMap supply_voltage_map_;
// Set if any library has rise/fall capacitances.
static bool found_rise_fall_caps_;
diff --git a/liberty/LibertyReader.cc b/liberty/LibertyReader.cc
index 05dfed82..75e185ca 100644
--- a/liberty/LibertyReader.cc
+++ b/liberty/LibertyReader.cc
@@ -178,6 +178,7 @@ LibertyReader::defineVisitors()
defineAttrVisitor("leakage_power_unit", &LibertyReader::visitPowerUnit);
defineAttrVisitor("delay_model", &LibertyReader::visitDelayModel);
defineAttrVisitor("bus_naming_style", &LibertyReader::visitBusStyle);
+ defineAttrVisitor("voltage_map", &LibertyReader::visitVoltageMap);
defineAttrVisitor("nom_temperature", &LibertyReader::visitNomTemp);
defineAttrVisitor("nom_voltage", &LibertyReader::visitNomVolt);
defineAttrVisitor("nom_process", &LibertyReader::visitNomProc);
@@ -832,6 +833,39 @@ LibertyReader::visitBusStyle(LibertyAttr *attr)
}
}
+void
+LibertyReader::visitVoltageMap(LibertyAttr *attr)
+{
+ if (library_) {
+ if (attr->isComplex()) {
+ LibertyAttrValueIterator value_iter(attr->values());
+ if (value_iter.hasNext()) {
+ LibertyAttrValue *value = value_iter.next();
+ if (value->isString()) {
+ const char *supply_name = value->stringValue();
+ if (value_iter.hasNext()) {
+ value = value_iter.next();
+ if (value->isFloat()) {
+ float voltage = value->floatValue();
+ library_->addSupplyVoltage(supply_name, voltage);
+ }
+ else
+ libWarn(attr, "voltage_map voltage is not a float.\n");
+ }
+ else
+ libWarn(attr, "voltage_map missing voltage.\n");
+ }
+ else
+ libWarn(attr, "voltage_map supply name is not a string.\n");
+ }
+ else
+ libWarn(attr, "voltage_map missing supply name and voltage.\n");
+ }
+ else
+ libWarn(attr, "voltage_map missing values suffix.\n");
+ }
+}
+
void
LibertyReader::visitNomTemp(LibertyAttr *attr)
{
diff --git a/liberty/LibertyReaderPvt.hh b/liberty/LibertyReaderPvt.hh
index 9ec1d655..f3efb63a 100644
--- a/liberty/LibertyReaderPvt.hh
+++ b/liberty/LibertyReaderPvt.hh
@@ -88,6 +88,7 @@ public:
float &scale_var,
Unit *unit_suffix);
virtual void visitDelayModel(LibertyAttr *attr);
+ virtual void visitVoltageMap(LibertyAttr *attr);
virtual void visitBusStyle(LibertyAttr *attr);
virtual void visitNomTemp(LibertyAttr *attr);
virtual void visitNomVolt(LibertyAttr *attr);
diff --git a/search/Path.cc b/search/Path.cc
index 299c4809..a63a1b44 100644
--- a/search/Path.cc
+++ b/search/Path.cc
@@ -21,6 +21,7 @@
#include "Clock.hh"
#include "Tag.hh"
#include "Corner.hh"
+#include "DcalcAnalysisPt.hh"
#include "PathAnalysisPt.hh"
#include "PathRef.hh"
#include "Path.hh"
@@ -97,6 +98,19 @@ Path::pathAnalysisPtIndex(const StaState *sta) const
return pathAnalysisPt(sta)->index();
}
+DcalcAnalysisPt *
+Path::dcalcAnalysisPt(const StaState *sta) const
+{
+ return pathAnalysisPt(sta)->dcalcAnalysisPt();
+}
+
+Slew
+Path::slew(const StaState *sta) const
+{
+ return sta->graph()->slew(vertex(sta), transition(sta),
+ dcalcAnalysisPt(sta)->index());
+}
+
int
Path::trIndex(const StaState *sta) const
{
diff --git a/search/Path.hh b/search/Path.hh
index fed5b34f..8442f52d 100644
--- a/search/Path.hh
+++ b/search/Path.hh
@@ -29,6 +29,8 @@
namespace sta {
+class DcalcAnalysisPt;
+
// Abstract base class for Path API.
class Path
{
@@ -55,6 +57,7 @@ public:
virtual const MinMax *minMax(const StaState *sta) const;
virtual PathAnalysisPt *pathAnalysisPt(const StaState *sta) const = 0;
virtual PathAPIndex pathAnalysisPtIndex(const StaState *sta) const;
+ virtual DcalcAnalysisPt *dcalcAnalysisPt(const StaState *sta) const;
virtual Arrival arrival(const StaState *sta) const = 0;
virtual void setArrival(Arrival arrival,
const StaState *sta) = 0;
@@ -66,6 +69,7 @@ public:
virtual void initRequired(const StaState *sta);
virtual bool requiredIsInitValue(const StaState *sta) const;
virtual Slack slack(const StaState *sta) const;
+ virtual Slew slew(const StaState *sta) const;
// This takes the same time as prevPath and prevArc combined.
virtual void prevPath(const StaState *sta,
// Return values.
diff --git a/search/ReportPath.cc b/search/ReportPath.cc
index 1a7e73d9..42dad7fe 100644
--- a/search/ReportPath.cc
+++ b/search/ReportPath.cc
@@ -256,10 +256,63 @@ ReportPath::setDigits(int digits)
////////////////////////////////////////////////////////////////
+void
+ReportPath::reportPathEndHeader()
+{
+ string header;
+ switch (format_) {
+ case report_path_full:
+ case report_path_full_clock:
+ case report_path_full_clock_expanded:
+ case report_path_short:
+ case report_path_endpoint:
+ break;
+ case report_path_summary:
+ reportSummaryHeader(header);
+ report_->print(header);
+ break;
+ case report_path_slack_only:
+ reportSlackOnlyHeader(header);
+ report_->print(header);
+ break;
+ default:
+ internalError("unsupported path type");
+ break;
+ }
+}
+
+void
+ReportPath::reportPathEndFooter()
+{
+ string header;
+ switch (format_) {
+ case report_path_full:
+ case report_path_full_clock:
+ case report_path_full_clock_expanded:
+ case report_path_short:
+ break;
+ case report_path_endpoint:
+ case report_path_summary:
+ case report_path_slack_only:
+ report_->print("\n");
+ break;
+ default:
+ internalError("unsupported path type");
+ break;
+ }
+}
+
void
ReportPath::reportPathEnd(PathEnd *end)
{
- string header, result;
+ reportPathEnd(end, NULL);
+}
+
+void
+ReportPath::reportPathEnd(PathEnd *end,
+ PathEnd *prev_end)
+{
+ string result;
switch (format_) {
case report_path_full:
case report_path_full_clock:
@@ -273,24 +326,18 @@ ReportPath::reportPathEnd(PathEnd *end)
report_->print(result);
report_->print("\n\n");
break;
- case report_path_end:
- reportEndHeader(header);
- report_->print(header);
+ case report_path_endpoint:
+ reportEndpointHeader(end, prev_end);
reportEndLine(end, result);
report_->print(result);
break;
case report_path_summary:
- reportSummaryHeader(header);
- report_->print(header);
reportSummaryLine(end, result);
report_->print(result);
break;
case report_path_slack_only:
- reportSlackOnlyHeader(header);
- report_->print(header);
reportSlackOnly(end, result);
report_->print(result);
- report_->print("\n");
break;
default:
internalError("unsupported path type");
@@ -301,89 +348,42 @@ ReportPath::reportPathEnd(PathEnd *end)
void
ReportPath::reportPathEnds(PathEndSeq *ends)
{
- if (!ends->empty()) {
- string header;
- PathEndSeq::Iterator end_iter(ends);
- switch (format_) {
- case report_path_full:
- case report_path_full_clock:
- case report_path_full_clock_expanded:
- while (end_iter.hasNext()) {
- PathEnd *end = end_iter.next();
- string result;
- end->reportFull(this, result);
- report_->print(result);
- report_->print("\n\n");
- }
- break;
- case report_path_short:
- while (end_iter.hasNext()) {
- PathEnd *end = end_iter.next();
- string result;
- end->reportShort(this, result);
- report_->print(result);
- report_->print("\n\n");
- }
- break;
- case report_path_end:
- reportPathEndsEnd(ends);
- break;
- case report_path_summary:
- reportSummaryHeader(header);
- report_->print(header);
- while (end_iter.hasNext()) {
- PathEnd *end = end_iter.next();
- string result;
- reportSummaryLine(end, result);
- report_->print(result);
- }
- report_->print("\n");
- break;
- case report_path_slack_only:
- reportSlackOnlyHeader(header);
- report_->print(header);
- while (end_iter.hasNext()) {
- PathEnd *end = end_iter.next();
- string result;
- reportSlackOnly(end, result);
- report_->print(result);
- }
- report_->print("\n");
- break;
- default:
- internalError("unsupported path type");
- break;
- }
+ reportPathEndHeader();
+ PathEndSeq::Iterator end_iter(ends);
+ PathEnd *prev_end = NULL;
+ while (end_iter.hasNext()) {
+ PathEnd *end = end_iter.next();
+ reportEndpointHeader(end, prev_end);
+ string result;
+ end->reportFull(this, result);
+ report_->print(result);
+ report_->print("\n\n");
+ prev_end = end;
}
+ reportPathEndFooter();
}
void
-ReportPath::reportPathEndsEnd(PathEndSeq *ends)
+ReportPath::reportEndpointHeader(PathEnd *end,
+ PathEnd *prev_end)
{
PathGroup *prev_group = NULL;
- PathEndSeq::Iterator end_iter(ends);
- while (end_iter.hasNext()) {
- PathEnd *end = end_iter.next();
- PathGroup *group = search_->pathGroup(end);
- if (group != prev_group) {
- if (prev_group)
- report_->print("\n");
- const char *setup_hold = (end->minMax(this) == MinMax::min())
- ? "min_delay/hold"
- : "max_delay/setup";
- report_->print("%s ('%s' group)\n\n",
- setup_hold,
- group->name());
- string header;
- reportEndHeader(header);
- report_->print(header);
- }
- string result;
- reportEndLine(end, result);
- report_->print(result);
- prev_group = group;
+ if (prev_end)
+ prev_group = search_->pathGroup(prev_end);
+ PathGroup *group = search_->pathGroup(end);
+ if (group != prev_group) {
+ if (prev_group)
+ report_->print("\n");
+ const char *setup_hold = (end->minMax(this) == MinMax::min())
+ ? "min_delay/hold"
+ : "max_delay/setup";
+ report_->print("%s ('%s' group)\n\n",
+ setup_hold,
+ group->name());
+ string header;
+ reportEndHeader(header);
+ report_->print(header);
}
- report_->print("\n");
}
void
diff --git a/search/ReportPath.hh b/search/ReportPath.hh
index ac878772..92cec57e 100644
--- a/search/ReportPath.hh
+++ b/search/ReportPath.hh
@@ -81,7 +81,16 @@ public:
void setNoSplit(bool no_split);
ReportField *findField(const char *name);
+ // Header above reportPathEnd results.
+ void reportPathEndHeader();
+ // Footer below reportPathEnd results.
+ void reportPathEndFooter();
void reportPathEnd(PathEnd *end);
+ // Format report_path_endpoint only:
+ // Previous path end is used to detect path group changes
+ // so headers are reported by group.
+ void reportPathEnd(PathEnd *end,
+ PathEnd *prev_end);
void reportPathEnds(PathEndSeq *ends);
void reportPath(const Path *path);
@@ -194,7 +203,8 @@ protected:
bool left_justify,
Unit *unit,
bool enabled);
- void reportPathEndsEnd(PathEndSeq *ends);
+ void reportEndpointHeader(PathEnd *end,
+ PathEnd *prev_end);
void reportShort(const PathEndUnconstrained *end,
PathExpanded &expanded,
string &result);
diff --git a/search/SearchClass.hh b/search/SearchClass.hh
index 96bfd47e..e02cb561 100644
--- a/search/SearchClass.hh
+++ b/search/SearchClass.hh
@@ -118,7 +118,7 @@ typedef enum {
report_path_full_clock,
report_path_full_clock_expanded,
report_path_short,
- report_path_end,
+ report_path_endpoint,
report_path_summary,
report_path_slack_only
} ReportPathFormat;
diff --git a/search/Sta.cc b/search/Sta.cc
index 7fd8cb50..5a01145a 100644
--- a/search/Sta.cc
+++ b/search/Sta.cc
@@ -2465,6 +2465,31 @@ Sta::reportPathEnds(PathEndSeq *ends)
report_path_->reportPathEnds(ends);
}
+void
+Sta::reportPathEndHeader()
+{
+ report_path_->reportPathEndHeader();
+}
+
+void
+Sta::reportPathEndFooter()
+{
+ report_path_->reportPathEndFooter();
+}
+
+void
+Sta::reportPathEnd(PathEnd *end)
+{
+ report_path_->reportPathEnd(end);
+}
+
+void
+Sta::reportPathEnd(PathEnd *end,
+ PathEnd *prev_end)
+{
+ report_path_->reportPathEnd(end, prev_end);
+}
+
void
Sta::reportPath(Path *path)
{
diff --git a/search/Sta.hh b/search/Sta.hh
index fdb0b232..9eedb773 100644
--- a/search/Sta.hh
+++ b/search/Sta.hh
@@ -870,6 +870,16 @@ public:
const Corner *corner,
const SetupHold *setup_hold,
int digits);
+ // Header above reportPathEnd results.
+ void reportPathEndHeader();
+ // Footer below reportPathEnd results.
+ void reportPathEndFooter();
+ // Format report_path_endpoint only:
+ // Previous path end is used to detect path group changes
+ // so headers are reported by group.
+ void reportPathEnd(PathEnd *end,
+ PathEnd *prev_end);
+ void reportPathEnd(PathEnd *end);
void reportPathEnds(PathEndSeq *ends);
ReportPath *reportPath() { return report_path_; }
void reportPath(Path *path);
diff --git a/tcl/Cmds.tcl b/tcl/Cmds.tcl
index c46c2e3e..63b2551d 100644
--- a/tcl/Cmds.tcl
+++ b/tcl/Cmds.tcl
@@ -1793,6 +1793,8 @@ proc get_property_cmd { cmd type_key cmd_args } {
return [liberty_library_property $object $attr]
} elseif { $object_type == "Edge" } {
return [edge_property $object $attr]
+ } elseif { $object_type == "PathEnd" } {
+ return [path_end_property $object $attr]
} else {
sta_error "$cmd unsupported object type $object_type."
}
@@ -1835,6 +1837,24 @@ proc edge_property { edge property } {
}
}
+proc path_end_property { path_end property } {
+ if { $property == "startpoint" } {
+ return [$path_end startpoint]
+ } elseif { $property == "startpoint_clock" } {
+ return [$path_end startpoint_clock]
+ } elseif { $property == "endpoint" } {
+ return [$path_end endpoint]
+ } elseif { $property == "endpoint_clock" } {
+ return [$path_end endpoint_clock]
+ } elseif { $property == "endpoint_clock_pin" } {
+ return [$path_end endpoint_clock_pin]
+ } elseif { $property == "slack" } {
+ return [time_sta_ui [$path_end slack]]
+ } else {
+ return ""
+ }
+}
+
proc get_object_type { obj } {
set object_type [object_type $obj]
if { $object_type == "Clock" } {
diff --git a/tcl/Search.tcl b/tcl/Search.tcl
index 8c84c454..4b3fceee 100644
--- a/tcl/Search.tcl
+++ b/tcl/Search.tcl
@@ -383,5 +383,15 @@ proc report_slew_limits { corner min_max all_violators verbose nosplit } {
}
}
+proc report_path_ends { path_ends } {
+ report_path_end_header
+ set prev_end "NULL"
+ foreach path_end $path_ends {
+ report_path_end2 $path_end $prev_end
+ set prev_end $path_end
+ }
+ report_path_end_footer
+}
+
# sta namespace end.
}
diff --git a/tcl/Sta.tcl b/tcl/Sta.tcl
index d3b90942..8450fc1e 100644
--- a/tcl/Sta.tcl
+++ b/tcl/Sta.tcl
@@ -138,7 +138,7 @@ proc_redirect report_clock_skew {
################################################################
-define_sta_cmd_args "report_checks" \
+define_sta_cmd_args "find_timing_paths" \
{[-from from_list|-rise_from from_list|-fall_from from_list]\
[-through through_list|-rise_through through_list|-fall_through through_list]\
[-to to_list|-rise_to to_list|-fall_to to_list]\
@@ -150,27 +150,22 @@ define_sta_cmd_args "report_checks" \
[-slack_max slack_max]\
[-slack_min slack_min]\
[-sort_by_slack]\
- [-path_group group_name]\
- [-format full|full_clock|full_clock_expanded|short|end|summary]\
- [-fields [capacitance|transition_time|input_pin|net]]\
- [-digits digits]\
- [-no_line_splits]\
- [> filename] [>> filename]}
+ [-path_group group_name]}
-proc_redirect report_checks {
- global sta_report_unconstrained_paths
- variable path_options
+proc find_timing_paths { args } {
+ set path_ends [find_timing_paths_cmd "find_timing_paths" args]
+ return $path_ends
+}
- parse_key_args "report_checks" args \
+proc find_timing_paths_cmd { cmd args_var } {
+ upvar 1 $args_var args
+
+ parse_key_args "find_timing_paths" args \
keys {-from -rise_from -fall_from -to -rise_to -fall_to \
-path_delay -corner -group_count -endpoint_count \
-slack_max -slack_min -path_group} \
flags {-sort_by_slack -unique_paths_to_endpoint} 0
- parse_report_path_options "report_checks" args "full" 0
-
- set cmd "report_checks"
-
set min_max "max"
set end_tr "rise_fall"
if [info exists keys(-path_delay)] {
@@ -261,7 +256,36 @@ proc_redirect report_checks {
$slack_min $slack_max \
$sort_by_slack $groups \
1 1 1 1 1 1]
- if { [$path_ends empty] } {
+ return $path_ends
+}
+
+################################################################
+
+define_sta_cmd_args "report_checks" \
+ {[-from from_list|-rise_from from_list|-fall_from from_list]\
+ [-through through_list|-rise_through through_list|-fall_through through_list]\
+ [-to to_list|-rise_to to_list|-fall_to to_list]\
+ [-path_delay min|min_rise|min_fall|max|max_rise|max_fall|min_max]\
+ [-corner corner_name]\
+ [-group_count path_count] \
+ [-endpoint_count path_count]\
+ [-unique_paths_to_endpoint]\
+ [-slack_max slack_max]\
+ [-slack_min slack_min]\
+ [-sort_by_slack]\
+ [-path_group group_name]\
+ [-format full|full_clock|full_clock_expanded|short|end|summary]\
+ [-fields [capacitance|transition_time|input_pin|net]]\
+ [-digits digits]\
+ [-no_line_splits]\
+ [> filename] [>> filename]}
+
+proc_redirect report_checks {
+ global sta_report_unconstrained_paths
+
+ parse_report_path_options "report_checks" args "full" 0
+ set path_ends [find_timing_paths_cmd "report_checks" args]
+ if { $path_ends == {} } {
if { $sta_report_unconstrained_paths } {
puts "No paths."
} else {
@@ -270,7 +294,6 @@ proc_redirect report_checks {
} else {
report_path_ends $path_ends
}
- delete_path_ends $path_ends
}
################################################################
@@ -398,7 +421,6 @@ proc_redirect report_check_types {
$recovery $removal \
$clk_gating_setup $clk_gating_hold]
report_path_ends $path_ends
- delete_path_ends $path_ends
}
if { $max_transition } {
diff --git a/tcl/StaTcl.i b/tcl/StaTcl.i
index bda897a7..b21b2534 100644
--- a/tcl/StaTcl.i
+++ b/tcl/StaTcl.i
@@ -65,6 +65,7 @@
#include "Tag.hh"
#include "PathVertex.hh"
#include "PathRef.hh"
+#include "PathExpanded.hh"
#include "PathEnd.hh"
#include "PathGroup.hh"
#include "CheckTiming.hh"
@@ -96,7 +97,6 @@ typedef PinSet TmpPinSet;
typedef PinSeq TmpPinSeq;
typedef InstanceSeq TmpInstanceSeq;
typedef InstanceSet TmpInstanceSet;
-typedef PathEndSeq::Iterator PathEndSeqIterator;
typedef MinPulseWidthCheckSeq::Iterator MinPulseWidthCheckSeqIterator;
typedef FloatSeq TmpFloatSeq;
typedef string TmpString;
@@ -1596,7 +1596,7 @@ using namespace sta;
else if (stringEq(arg, "short"))
$1 = report_path_short;
else if (stringEq(arg, "end"))
- $1 = report_path_end;
+ $1 = report_path_endpoint;
else if (stringEq(arg, "summary"))
$1 = report_path_summary;
else if (stringEq(arg, "slack_only"))
@@ -1779,11 +1779,17 @@ using namespace sta;
%typemap(out) PathEndSeq* {
Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj);
-}
-%typemap(out) PathEndSeqIterator* {
- Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
- Tcl_SetObjResult(interp, obj);
+ Tcl_Obj *list = Tcl_NewListObj(0, NULL);
+ const PathEndSeq *path_ends = $1;
+ PathEndSeq::ConstIterator end_iter(path_ends);
+ while (end_iter.hasNext()) {
+ PathEnd *path_end = end_iter.next();
+ Tcl_Obj *obj = SWIG_NewInstanceObj(path_end, SWIGTYPE_p_PathEnd, false);
+ Tcl_ListObjAppendElement(interp, list, obj);
+ }
+ delete path_ends;
+ Tcl_SetObjResult(interp, list);
}
%typemap(out) MinPulseWidthCheckSeqIterator* {
@@ -2196,20 +2202,6 @@ private:
~PathEnd();
};
-class PathEndSeq
-{
-private:
- PathEnd();
- ~PathEnd();
-};
-
-class PathEndSeqIterator
-{
-private:
- PathEndSeqIterator();
- ~PathEndSeqIterator();
-};
-
class MinPulseWidthCheck
{
private:
@@ -4412,6 +4404,31 @@ find_path_ends(ExceptionFrom *from,
return ends;
}
+void
+report_path_end_header()
+{
+ Sta::sta()->reportPathEndHeader();
+}
+
+void
+report_path_end_footer()
+{
+ Sta::sta()->reportPathEndFooter();
+}
+
+void
+report_path_end(PathEnd *end)
+{
+ Sta::sta()->reportPathEnd(end);
+}
+
+void
+report_path_end2(PathEnd *end,
+ PathEnd *prev_end)
+{
+ Sta::sta()->reportPathEnd(end, prev_end);
+}
+
void
set_report_path_format(ReportPathFormat format)
{
@@ -4463,18 +4480,6 @@ set_report_path_no_split(bool no_split)
Sta::sta()->setReportPathNoSplit(no_split);
}
-void
-report_path_ends(PathEndSeq *ends)
-{
- Sta::sta()->reportPathEnds(ends);
-}
-
-void
-delete_path_ends(PathEndSeq *ends)
-{
- delete ends;
-}
-
void
delete_path_ref(PathRef *path)
{
@@ -4504,12 +4509,6 @@ report_clk_skew(ClockSet *clks,
delete clks;
}
-PathEndSeqIterator *
-path_end_seq_iterator(PathEndSeq *ends)
-{
- return new PathEndSeqIterator(ends);
-}
-
TmpPinSet *
startpoints()
{
@@ -6254,17 +6253,43 @@ Crpr common_clk_pessimism() { return self->commonClkPessimism(Sta::sta()); }
TransRiseFall *target_clk_end_trans()
{ return const_cast(self->targetClkEndTrans(Sta::sta())); }
+Pin *
+startpoint()
+{
+ Sta *sta = Sta::sta();
+ PathExpanded expanded(self->path(), sta);
+ return expanded.startPath()->pin(sta);
}
-%extend PathEndSeq {
-bool empty() { return self->empty(); }
-} // PathEndSeq methods
+Clock *
+startpoint_clock()
+{
+ Sta *sta = Sta::sta();
+ return self->path()->clock(sta);
+}
-%extend PathEndSeqIterator {
-bool has_next() { return self->hasNext(); }
-PathEnd *next() { return self->next(); }
-void finish() { delete self; }
-} // PathEndSeqIterator methods
+Pin *
+endpoint()
+{
+ Sta *sta = Sta::sta();
+ return self->path()->pin(sta);
+}
+
+Clock *
+endpoint_clock()
+{
+ Sta *sta = Sta::sta();
+ return self->targetClk(sta);
+}
+
+Pin *
+endpoint_clock_pin()
+{
+ Sta *sta = Sta::sta();
+ return self->targetClkPath()->pin(sta);
+}
+
+}
%extend MinPulseWidthCheckSeqIterator {
bool has_next() { return self->hasNext(); }