diff --git a/CMakeLists.txt b/CMakeLists.txt index 834fd6f4..d3adc13b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -420,20 +420,24 @@ set_property(SOURCE ${STA_SWIG_FILE} PROPERTY SWIG_FLAGS -module sta -namespace -prefix sta - -I${STA_HOME}/tcl + -I${STA_HOME}/dcalc + -I${STA_HOME}/graph + -I${STA_HOME}/liberty + -I${STA_HOME}/network -I${STA_HOME}/sdc -I${STA_HOME}/sdf - -I${STA_HOME}/dcalc - -I${STA_HOME}/liberty -I${STA_HOME}/parasitics -I${STA_HOME}/power -I${STA_HOME}/spice + -I${STA_HOME}/tcl -I${STA_HOME}/verilog ) set(SWIG_FILES ${STA_HOME}/dcalc/DelayCalc.i + ${STA_HOME}/graph/Graph.i ${STA_HOME}/liberty/Liberty.i + ${STA_HOME}/network/Network.i ${STA_HOME}/parasitics/Parasitics.i ${STA_HOME}/power/Power.i ${STA_HOME}/sdc/Sdc.i diff --git a/app/StaApp.i b/app/StaApp.i index 3e192658..e4adf39d 100644 --- a/app/StaApp.i +++ b/app/StaApp.i @@ -18,9 +18,11 @@ %include "Exception.i" %include "StaTclTypes.i" +%include "Graph.i" %include "StaTcl.i" %include "Liberty.i" %include "Verilog.i" +%include "Network.i" %include "NetworkEdit.i" %include "Sdf.i" %include "Sdc.i" diff --git a/graph/Graph.i b/graph/Graph.i new file mode 100644 index 00000000..5ac3d417 --- /dev/null +++ b/graph/Graph.i @@ -0,0 +1,435 @@ +// OpenSTA, Static Timing Analyzer +// Copyright (c) 2024, Parallax Software, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +%module graph + +%{ +#include "Graph.hh" +#include "FuncExpr.hh" +#include "TimingRole.hh" +#include "Liberty.hh" +#include "Network.hh" +#include "Clock.hh" +#include "Corner.hh" +#include "Search.hh" +#include "Sta.hh" + +namespace sta { + +Graph * +cmdGraph(); + +} // namespace + +using namespace sta; + +%} + +//////////////////////////////////////////////////////////////// +// +// Empty class definitions to make swig happy. +// Private constructor/destructor so swig doesn't emit them. +// +//////////////////////////////////////////////////////////////// + +class Vertex +{ +private: + Vertex(); + ~Vertex(); +}; + +class Edge +{ +private: + Edge(); + ~Edge(); +}; + +class VertexIterator +{ +private: + VertexIterator(); + ~VertexIterator(); +}; + +class VertexInEdgeIterator +{ +private: + VertexInEdgeIterator(); + ~VertexInEdgeIterator(); +}; + +class VertexOutEdgeIterator +{ +private: + VertexOutEdgeIterator(); + ~VertexOutEdgeIterator(); +}; + +%inline %{ + +VertexIterator * +vertex_iterator() +{ + return new VertexIterator(cmdGraph()); +} + +void +set_arc_delay(Edge *edge, + TimingArc *arc, + const Corner *corner, + const MinMaxAll *min_max, + float delay) +{ + cmdGraph(); + Sta::sta()->setArcDelay(edge, arc, corner, min_max, delay); +} + +void +set_annotated_slew(Vertex *vertex, + const Corner *corner, + const MinMaxAll *min_max, + const RiseFallBoth *rf, + float slew) +{ + cmdGraph(); + Sta::sta()->setAnnotatedSlew(vertex, corner, min_max, rf, slew); +} + +// Remove all delay and slew annotations. +void +remove_delay_slew_annotations() +{ + cmdGraph(); + Sta::sta()->removeDelaySlewAnnotations(); +} + +%} // inline + +%extend Vertex { +Pin *pin() { return self->pin(); } +bool is_bidirect_driver() { return self->isBidirectDriver(); } +int level() { return Sta::sta()->vertexLevel(self); } +int tag_group_index() { return self->tagGroupIndex(); } + +Slew +slew(const RiseFall *rf, + const MinMax *min_max) +{ + Sta *sta = Sta::sta(); + return sta->vertexSlew(self, rf, min_max); +} + +Slew +slew_corner(const RiseFall *rf, + const Corner *corner, + const MinMax *min_max) +{ + Sta *sta = Sta::sta(); + return sta->vertexSlew(self, rf, corner, min_max); +} + +VertexOutEdgeIterator * +out_edge_iterator() +{ + return new VertexOutEdgeIterator(self, Sta::sta()->graph()); +} + +VertexInEdgeIterator * +in_edge_iterator() +{ + return new VertexInEdgeIterator(self, Sta::sta()->graph()); +} + +FloatSeq +arrivals_clk(const RiseFall *rf, + Clock *clk, + const RiseFall *clk_rf) +{ + Sta *sta = Sta::sta(); + FloatSeq arrivals; + const ClockEdge *clk_edge = nullptr; + if (clk) + clk_edge = clk->edge(clk_rf); + for (auto path_ap : sta->corners()->pathAnalysisPts()) { + arrivals.push_back(delayAsFloat(sta->vertexArrival(self, rf, clk_edge, + path_ap, nullptr))); + } + return arrivals; +} + +StringSeq +arrivals_clk_delays(const RiseFall *rf, + Clock *clk, + const RiseFall *clk_rf, + int digits) +{ + Sta *sta = Sta::sta(); + StringSeq arrivals; + const ClockEdge *clk_edge = nullptr; + if (clk) + clk_edge = clk->edge(clk_rf); + for (auto path_ap : sta->corners()->pathAnalysisPts()) { + arrivals.push_back(delayAsString(sta->vertexArrival(self, rf, clk_edge, + path_ap, nullptr), + sta, digits)); + } + return arrivals; +} + +FloatSeq +requireds_clk(const RiseFall *rf, + Clock *clk, + const RiseFall *clk_rf) +{ + Sta *sta = Sta::sta(); + FloatSeq reqs; + const ClockEdge *clk_edge = nullptr; + if (clk) + clk_edge = clk->edge(clk_rf); + for (auto path_ap : sta->corners()->pathAnalysisPts()) { + reqs.push_back(delayAsFloat(sta->vertexRequired(self, rf, clk_edge, + path_ap))); + } + return reqs; +} + +StringSeq +requireds_clk_delays(const RiseFall *rf, + Clock *clk, + const RiseFall *clk_rf, + int digits) +{ + Sta *sta = Sta::sta(); + StringSeq reqs; + const ClockEdge *clk_edge = nullptr; + if (clk) + clk_edge = clk->edge(clk_rf); + for (auto path_ap : sta->corners()->pathAnalysisPts()) { + reqs.push_back(delayAsString(sta->vertexRequired(self, rf, clk_edge, path_ap), + sta, digits)); + } + return reqs; +} + +Slack +slack(MinMax *min_max) +{ + Sta *sta = Sta::sta(); + return sta->vertexSlack(self, min_max); +} + +FloatSeq +slacks(RiseFall *rf) +{ + Sta *sta = Sta::sta(); + FloatSeq slacks; + for (auto path_ap : sta->corners()->pathAnalysisPts()) { + slacks.push_back(delayAsFloat(sta->vertexSlack(self, rf, path_ap))); + } + return slacks; +} + +// Slack with respect to a clock rise/fall edge. +FloatSeq +slacks_clk(const RiseFall *rf, + Clock *clk, + const RiseFall *clk_rf) +{ + Sta *sta = Sta::sta(); + FloatSeq slacks; + const ClockEdge *clk_edge = nullptr; + if (clk) + clk_edge = clk->edge(clk_rf); + for (auto path_ap : sta->corners()->pathAnalysisPts()) { + slacks.push_back(delayAsFloat(sta->vertexSlack(self, rf, clk_edge, + path_ap))); + } + return slacks; +} + +StringSeq +slacks_clk_delays(const RiseFall *rf, + Clock *clk, + const RiseFall *clk_rf, + int digits) +{ + Sta *sta = Sta::sta(); + StringSeq slacks; + const ClockEdge *clk_edge = nullptr; + if (clk) + clk_edge = clk->edge(clk_rf); + for (auto path_ap : sta->corners()->pathAnalysisPts()) { + slacks.push_back(delayAsString(sta->vertexSlack(self, rf, clk_edge, + path_ap), + sta, digits)); + } + return slacks; +} + +VertexPathIterator * +path_iterator(const RiseFall *rf, + const MinMax *min_max) +{ + return Sta::sta()->vertexPathIterator(self, rf, min_max); +} + +bool +has_downstream_clk_pin() +{ + return self->hasDownstreamClkPin(); +} + +bool +is_clock() +{ + Sta *sta = Sta::sta(); + Search *search = sta->search(); + return search->isClock(self); +} + +bool is_disabled_constraint() { return self->isDisabledConstraint(); } + +} // Vertex methods + +%extend Edge { +Vertex *from() { return self->from(Sta::sta()->graph()); } +Vertex *to() { return self->to(Sta::sta()->graph()); } +Pin *from_pin() { return self->from(Sta::sta()->graph())->pin(); } +Pin *to_pin() { return self->to(Sta::sta()->graph())->pin(); } +TimingRole *role() { return self->role(); } +const char *sense() { return timingSenseString(self->sense()); } +TimingArcSeq & +timing_arcs() { return self->timingArcSet()->arcs(); } +bool is_disabled_loop() { return Sta::sta()->isDisabledLoop(self); } +bool is_disabled_constraint() { return Sta::sta()->isDisabledConstraint(self);} +bool is_disabled_constant() { return Sta::sta()->isDisabledConstant(self); } +bool is_disabled_cond_default() +{ return Sta::sta()->isDisabledCondDefault(self); } +PinSet +disabled_constant_pins() { return Sta::sta()->disabledConstantPins(self); } +bool is_disabled_bidirect_inst_path() +{ return Sta::sta()->isDisabledBidirectInstPath(self); } +bool is_disabled_bidirect_net_path() +{ return Sta::sta()->isDisabledBidirectNetPath(self); } +bool is_disabled_preset_clear() +{ return Sta::sta()->isDisabledPresetClr(self); } +const char * +sim_timing_sense(){return timingSenseString(Sta::sta()->simTimingSense(self));} + +FloatSeq +arc_delays(TimingArc *arc) +{ + Sta *sta = Sta::sta(); + FloatSeq delays; + for (auto dcalc_ap : sta->corners()->dcalcAnalysisPts()) + delays.push_back(delayAsFloat(sta->arcDelay(self, arc, dcalc_ap))); + return delays; +} + +StringSeq +arc_delay_strings(TimingArc *arc, + int digits) +{ + Sta *sta = Sta::sta(); + StringSeq delays; + for (auto dcalc_ap : sta->corners()->dcalcAnalysisPts()) + delays.push_back(delayAsString(sta->arcDelay(self, arc, dcalc_ap), + sta, digits)); + return delays; +} + +bool +delay_annotated(TimingArc *arc, + const Corner *corner, + const MinMax *min_max) +{ + DcalcAnalysisPt *dcalc_ap = corner->findDcalcAnalysisPt(min_max); + return Sta::sta()->arcDelayAnnotated(self, arc, dcalc_ap); +} + +float +arc_delay(TimingArc *arc, + const Corner *corner, + const MinMax *min_max) +{ + DcalcAnalysisPt *dcalc_ap = corner->findDcalcAnalysisPt(min_max); + return delayAsFloat(Sta::sta()->arcDelay(self, arc, dcalc_ap)); +} + +const char * +cond() +{ + FuncExpr *cond = self->timingArcSet()->cond(); + if (cond) + return cond->asString(); + else + return nullptr; +} + +const char * +mode_name() +{ + return self->timingArcSet()->modeName(); +} + +const char * +mode_value() +{ + return self->timingArcSet()->modeValue(); +} + +const char * +latch_d_to_q_en() +{ + if (self->role() == TimingRole::latchDtoQ()) { + Sta *sta = Sta::sta(); + const Network *network = sta->cmdNetwork(); + const Graph *graph = sta->graph(); + Pin *from_pin = self->from(graph)->pin(); + Instance *inst = network->instance(from_pin); + LibertyCell *lib_cell = network->libertyCell(inst); + TimingArcSet *d_q_set = self->timingArcSet(); + const LibertyPort *enable_port; + const FuncExpr *enable_func; + const RiseFall *enable_rf; + lib_cell->latchEnable(d_q_set, enable_port, enable_func, enable_rf); + if (enable_port) + return stringPrintTmp("%s %s", enable_port->name(), enable_rf->asString()); + } + return ""; +} + +} // Edge methods + +%extend VertexIterator { +bool has_next() { return self->hasNext(); } +Vertex *next() { return self->next(); } +void finish() { delete self; } +} + +%extend VertexInEdgeIterator { +bool has_next() { return self->hasNext(); } +Edge *next() { return self->next(); } +void finish() { delete self; } +} + +%extend VertexOutEdgeIterator { +bool has_next() { return self->hasNext(); } +Edge *next() { return self->next(); } +void finish() { delete self; } +} diff --git a/liberty/Liberty.i b/liberty/Liberty.i index 0b570efb..5aefae7d 100644 --- a/liberty/Liberty.i +++ b/liberty/Liberty.i @@ -178,6 +178,24 @@ liberty_supply_exists(const char *supply_name) return lib && lib->supplyExists(supply_name); } +LibertyLibraryIterator * +liberty_library_iterator() +{ + return cmdNetwork()->libertyLibraryIterator(); +} + +LibertyLibrary * +find_liberty(const char *name) +{ + return cmdNetwork()->findLiberty(name); +} + +LibertyCell * +find_liberty_cell(const char *name) +{ + return cmdNetwork()->findLibertyCell(name); +} + %} // inline %extend LibertyLibrary { diff --git a/network/Network.i b/network/Network.i new file mode 100644 index 00000000..37719c3f --- /dev/null +++ b/network/Network.i @@ -0,0 +1,32 @@ +// OpenSTA, Static Timing Analyzer +// Copyright (c) 2024, Parallax Software, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +%module network + +%{ +#include "Network.hh" +%} + +//////////////////////////////////////////////////////////////// +// +// Empty class definitions to make swig happy. +// Private constructor/destructor so swig doesn't emit them. +// +//////////////////////////////////////////////////////////////// + +%inline %{ + +%} // inline diff --git a/tcl/StaTcl.i b/tcl/StaTcl.i index ed5a9dfd..20ecca6f 100644 --- a/tcl/StaTcl.i +++ b/tcl/StaTcl.i @@ -274,41 +274,6 @@ private: ~PinConnectedPinIterator(); }; -class Vertex -{ -private: - Vertex(); - ~Vertex(); -}; - -class Edge -{ -private: - Edge(); - ~Edge(); -}; - -class VertexIterator -{ -private: - VertexIterator(); - ~VertexIterator(); -}; - -class VertexInEdgeIterator -{ -private: - VertexInEdgeIterator(); - ~VertexInEdgeIterator(); -}; - -class VertexOutEdgeIterator -{ -private: - VertexOutEdgeIterator(); - ~VertexOutEdgeIterator(); -}; - class PathRef { private: @@ -572,24 +537,6 @@ library_iterator() return cmdNetwork()->libraryIterator(); } -LibertyLibrary * -find_liberty(const char *name) -{ - return cmdNetwork()->findLiberty(name); -} - -LibertyLibraryIterator * -liberty_library_iterator() -{ - return cmdNetwork()->libertyLibraryIterator(); -} - -LibertyCell * -find_liberty_cell(const char *name) -{ - return cmdNetwork()->findLibertyCell(name); -} - CellSeq find_cells_matching(const char *pattern, bool regexp, @@ -1396,42 +1343,6 @@ unit_scaled_suffix(const char *unit_name) //////////////////////////////////////////////////////////////// -VertexIterator * -vertex_iterator() -{ - return new VertexIterator(cmdGraph()); -} - -void -set_arc_delay(Edge *edge, - TimingArc *arc, - const Corner *corner, - const MinMaxAll *min_max, - float delay) -{ - cmdGraph(); - Sta::sta()->setArcDelay(edge, arc, corner, min_max, delay); -} - -void -set_annotated_slew(Vertex *vertex, - const Corner *corner, - const MinMaxAll *min_max, - const RiseFallBoth *rf, - float slew) -{ - cmdGraph(); - Sta::sta()->setAnnotatedSlew(vertex, corner, min_max, rf, slew); -} - -// Remove all delay and slew annotations. -void -remove_delay_slew_annotations() -{ - cmdGraph(); - Sta::sta()->removeDelaySlewAnnotations(); -} - CheckErrorSeq & check_timing_cmd(bool no_input_delay, bool no_output_delay, @@ -2976,320 +2887,6 @@ const Pin *next() { return self->next(); } void finish() { delete self; } } // NetConnectedPinIterator methods -%extend Vertex { -Pin *pin() { return self->pin(); } -bool is_bidirect_driver() { return self->isBidirectDriver(); } -int level() { return Sta::sta()->vertexLevel(self); } -int tag_group_index() { return self->tagGroupIndex(); } - -Slew -slew(const RiseFall *rf, - const MinMax *min_max) -{ - Sta *sta = Sta::sta(); - return sta->vertexSlew(self, rf, min_max); -} - -Slew -slew_corner(const RiseFall *rf, - const Corner *corner, - const MinMax *min_max) -{ - Sta *sta = Sta::sta(); - return sta->vertexSlew(self, rf, corner, min_max); -} - -VertexOutEdgeIterator * -out_edge_iterator() -{ - return new VertexOutEdgeIterator(self, Sta::sta()->graph()); -} - -VertexInEdgeIterator * -in_edge_iterator() -{ - return new VertexInEdgeIterator(self, Sta::sta()->graph()); -} - -FloatSeq -arrivals_clk(const RiseFall *rf, - Clock *clk, - const RiseFall *clk_rf) -{ - Sta *sta = Sta::sta(); - FloatSeq arrivals; - const ClockEdge *clk_edge = nullptr; - if (clk) - clk_edge = clk->edge(clk_rf); - for (auto path_ap : sta->corners()->pathAnalysisPts()) { - arrivals.push_back(delayAsFloat(sta->vertexArrival(self, rf, clk_edge, - path_ap, nullptr))); - } - return arrivals; -} - -StringSeq -arrivals_clk_delays(const RiseFall *rf, - Clock *clk, - const RiseFall *clk_rf, - int digits) -{ - Sta *sta = Sta::sta(); - StringSeq arrivals; - const ClockEdge *clk_edge = nullptr; - if (clk) - clk_edge = clk->edge(clk_rf); - for (auto path_ap : sta->corners()->pathAnalysisPts()) { - arrivals.push_back(delayAsString(sta->vertexArrival(self, rf, clk_edge, - path_ap, nullptr), - sta, digits)); - } - return arrivals; -} - -FloatSeq -requireds_clk(const RiseFall *rf, - Clock *clk, - const RiseFall *clk_rf) -{ - Sta *sta = Sta::sta(); - FloatSeq reqs; - const ClockEdge *clk_edge = nullptr; - if (clk) - clk_edge = clk->edge(clk_rf); - for (auto path_ap : sta->corners()->pathAnalysisPts()) { - reqs.push_back(delayAsFloat(sta->vertexRequired(self, rf, clk_edge, - path_ap))); - } - return reqs; -} - -StringSeq -requireds_clk_delays(const RiseFall *rf, - Clock *clk, - const RiseFall *clk_rf, - int digits) -{ - Sta *sta = Sta::sta(); - StringSeq reqs; - const ClockEdge *clk_edge = nullptr; - if (clk) - clk_edge = clk->edge(clk_rf); - for (auto path_ap : sta->corners()->pathAnalysisPts()) { - reqs.push_back(delayAsString(sta->vertexRequired(self, rf, clk_edge, path_ap), - sta, digits)); - } - return reqs; -} - -Slack -slack(MinMax *min_max) -{ - Sta *sta = Sta::sta(); - return sta->vertexSlack(self, min_max); -} - -FloatSeq -slacks(RiseFall *rf) -{ - Sta *sta = Sta::sta(); - FloatSeq slacks; - for (auto path_ap : sta->corners()->pathAnalysisPts()) { - slacks.push_back(delayAsFloat(sta->vertexSlack(self, rf, path_ap))); - } - return slacks; -} - -// Slack with respect to a clock rise/fall edge. -FloatSeq -slacks_clk(const RiseFall *rf, - Clock *clk, - const RiseFall *clk_rf) -{ - Sta *sta = Sta::sta(); - FloatSeq slacks; - const ClockEdge *clk_edge = nullptr; - if (clk) - clk_edge = clk->edge(clk_rf); - for (auto path_ap : sta->corners()->pathAnalysisPts()) { - slacks.push_back(delayAsFloat(sta->vertexSlack(self, rf, clk_edge, - path_ap))); - } - return slacks; -} - -StringSeq -slacks_clk_delays(const RiseFall *rf, - Clock *clk, - const RiseFall *clk_rf, - int digits) -{ - Sta *sta = Sta::sta(); - StringSeq slacks; - const ClockEdge *clk_edge = nullptr; - if (clk) - clk_edge = clk->edge(clk_rf); - for (auto path_ap : sta->corners()->pathAnalysisPts()) { - slacks.push_back(delayAsString(sta->vertexSlack(self, rf, clk_edge, - path_ap), - sta, digits)); - } - return slacks; -} - -VertexPathIterator * -path_iterator(const RiseFall *rf, - const MinMax *min_max) -{ - return Sta::sta()->vertexPathIterator(self, rf, min_max); -} - -bool -has_downstream_clk_pin() -{ - return self->hasDownstreamClkPin(); -} - -bool -is_clock() -{ - Sta *sta = Sta::sta(); - Search *search = sta->search(); - return search->isClock(self); -} - -bool is_disabled_constraint() { return self->isDisabledConstraint(); } - -} // Vertex methods - -%extend Edge { -Vertex *from() { return self->from(Sta::sta()->graph()); } -Vertex *to() { return self->to(Sta::sta()->graph()); } -Pin *from_pin() { return self->from(Sta::sta()->graph())->pin(); } -Pin *to_pin() { return self->to(Sta::sta()->graph())->pin(); } -TimingRole *role() { return self->role(); } -const char *sense() { return timingSenseString(self->sense()); } -TimingArcSeq & -timing_arcs() { return self->timingArcSet()->arcs(); } -bool is_disabled_loop() { return Sta::sta()->isDisabledLoop(self); } -bool is_disabled_constraint() { return Sta::sta()->isDisabledConstraint(self);} -bool is_disabled_constant() { return Sta::sta()->isDisabledConstant(self); } -bool is_disabled_cond_default() -{ return Sta::sta()->isDisabledCondDefault(self); } -PinSet -disabled_constant_pins() { return Sta::sta()->disabledConstantPins(self); } -bool is_disabled_bidirect_inst_path() -{ return Sta::sta()->isDisabledBidirectInstPath(self); } -bool is_disabled_bidirect_net_path() -{ return Sta::sta()->isDisabledBidirectNetPath(self); } -bool is_disabled_preset_clear() -{ return Sta::sta()->isDisabledPresetClr(self); } -const char * -sim_timing_sense(){return timingSenseString(Sta::sta()->simTimingSense(self));} - -FloatSeq -arc_delays(TimingArc *arc) -{ - Sta *sta = Sta::sta(); - FloatSeq delays; - for (auto dcalc_ap : sta->corners()->dcalcAnalysisPts()) - delays.push_back(delayAsFloat(sta->arcDelay(self, arc, dcalc_ap))); - return delays; -} - -StringSeq -arc_delay_strings(TimingArc *arc, - int digits) -{ - Sta *sta = Sta::sta(); - StringSeq delays; - for (auto dcalc_ap : sta->corners()->dcalcAnalysisPts()) - delays.push_back(delayAsString(sta->arcDelay(self, arc, dcalc_ap), - sta, digits)); - return delays; -} - -bool -delay_annotated(TimingArc *arc, - const Corner *corner, - const MinMax *min_max) -{ - DcalcAnalysisPt *dcalc_ap = corner->findDcalcAnalysisPt(min_max); - return Sta::sta()->arcDelayAnnotated(self, arc, dcalc_ap); -} - -float -arc_delay(TimingArc *arc, - const Corner *corner, - const MinMax *min_max) -{ - DcalcAnalysisPt *dcalc_ap = corner->findDcalcAnalysisPt(min_max); - return delayAsFloat(Sta::sta()->arcDelay(self, arc, dcalc_ap)); -} - -const char * -cond() -{ - FuncExpr *cond = self->timingArcSet()->cond(); - if (cond) - return cond->asString(); - else - return nullptr; -} - -const char * -mode_name() -{ - return self->timingArcSet()->modeName(); -} - -const char * -mode_value() -{ - return self->timingArcSet()->modeValue(); -} - -const char * -latch_d_to_q_en() -{ - if (self->role() == TimingRole::latchDtoQ()) { - Sta *sta = Sta::sta(); - const Network *network = sta->cmdNetwork(); - const Graph *graph = sta->graph(); - Pin *from_pin = self->from(graph)->pin(); - Instance *inst = network->instance(from_pin); - LibertyCell *lib_cell = network->libertyCell(inst); - TimingArcSet *d_q_set = self->timingArcSet(); - const LibertyPort *enable_port; - const FuncExpr *enable_func; - const RiseFall *enable_rf; - lib_cell->latchEnable(d_q_set, enable_port, enable_func, enable_rf); - if (enable_port) - return stringPrintTmp("%s %s", enable_port->name(), enable_rf->asString()); - } - return ""; -} - -} // Edge methods - -%extend VertexIterator { -bool has_next() { return self->hasNext(); } -Vertex *next() { return self->next(); } -void finish() { delete self; } -} - -%extend VertexInEdgeIterator { -bool has_next() { return self->hasNext(); } -Edge *next() { return self->next(); } -void finish() { delete self; } -} - -%extend VertexOutEdgeIterator { -bool has_next() { return self->hasNext(); } -Edge *next() { return self->next(); } -void finish() { delete self; } -} - %extend PathEnd { bool is_unconstrained() { return self->isUnconstrained(); } bool is_check() { return self->isCheck(); }