Graph.i
Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
parent
5e855dd989
commit
1baa0dc907
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
%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; }
|
||||
}
|
||||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
%module network
|
||||
|
||||
%{
|
||||
#include "Network.hh"
|
||||
%}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Empty class definitions to make swig happy.
|
||||
// Private constructor/destructor so swig doesn't emit them.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
%inline %{
|
||||
|
||||
%} // inline
|
||||
403
tcl/StaTcl.i
403
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(); }
|
||||
|
|
|
|||
Loading…
Reference in New Issue