OpenSTA/search/Search.i

644 lines
13 KiB
OpenEdge ABL
Raw Normal View History

// 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 search
%{
#include "Sta.hh"
#include "PathGroup.hh"
#include "Search.hh"
#include "search/Levelize.hh"
#include "search/ReportPath.hh"
using namespace sta;
%}
////////////////////////////////////////////////////////////////
//
// Empty class definitions to make swig happy.
// Private constructor/destructor so swig doesn't emit them.
//
////////////////////////////////////////////////////////////////
class VertexPathIterator
{
private:
VertexPathIterator();
~VertexPathIterator();
};
class PathRef
{
private:
PathRef();
~PathRef();
};
class PathEnd
{
private:
PathEnd();
~PathEnd();
};
class MinPulseWidthCheck
{
private:
MinPulseWidthCheck();
~MinPulseWidthCheck();
};
class MinPulseWidthCheckSeq
{
private:
MinPulseWidthCheckSeq();
~MinPulseWidthCheckSeq();
};
class MinPulseWidthCheckSeqIterator
{
private:
MinPulseWidthCheckSeqIterator();
~MinPulseWidthCheckSeqIterator();
};
class Corner
{
private:
Corner();
~Corner();
};
%inline %{
int group_count_max = PathGroup::group_count_max;
void
find_timing_cmd(bool full)
{
cmdLinkedNetwork();
Sta::sta()->updateTiming(full);
}
void
arrivals_invalid()
{
Sta *sta = Sta::sta();
sta->arrivalsInvalid();
}
PinSet
startpoints()
{
return Sta::sta()->startpointPins();
}
PinSet
endpoints()
{
return Sta::sta()->endpointPins();
}
size_t
endpoint_count()
{
return Sta::sta()->endpointPins().size();
}
void
find_requireds()
{
cmdLinkedNetwork();
Sta::sta()->findRequireds();
}
Slack
total_negative_slack_cmd(const MinMax *min_max)
{
cmdLinkedNetwork();
Sta *sta = Sta::sta();
return sta->totalNegativeSlack(min_max);
}
Slack
total_negative_slack_corner_cmd(const Corner *corner,
const MinMax *min_max)
{
cmdLinkedNetwork();
Sta *sta = Sta::sta();
return sta->totalNegativeSlack(corner, min_max);
}
Slack
worst_slack_cmd(const MinMax *min_max)
{
cmdLinkedNetwork();
Sta *sta = Sta::sta();
Slack worst_slack;
Vertex *worst_vertex;
sta->worstSlack(min_max, worst_slack, worst_vertex);
return worst_slack;
}
Vertex *
worst_slack_vertex(const MinMax *min_max)
{
cmdLinkedNetwork();
Sta *sta = Sta::sta();
Slack worst_slack;
Vertex *worst_vertex;
sta->worstSlack(min_max, worst_slack, worst_vertex);
return worst_vertex;;
}
Slack
worst_slack_corner(const Corner *corner,
const MinMax *min_max)
{
cmdLinkedNetwork();
Sta *sta = Sta::sta();
Slack worst_slack;
Vertex *worst_vertex;
sta->worstSlack(corner, min_max, worst_slack, worst_vertex);
return worst_slack;
}
PathRef *
vertex_worst_arrival_path(Vertex *vertex,
const MinMax *min_max)
{
Sta *sta = Sta::sta();
PathRef path = sta->vertexWorstArrivalPath(vertex, min_max);
if (!path.isNull())
return new PathRef(path);
else
return nullptr;
}
PathRef *
vertex_worst_arrival_path_rf(Vertex *vertex,
const RiseFall *rf,
MinMax *min_max)
{
Sta *sta = Sta::sta();
PathRef path = sta->vertexWorstArrivalPath(vertex, rf, min_max);
if (!path.isNull())
return new PathRef(path);
else
return nullptr;
}
PathRef *
vertex_worst_slack_path(Vertex *vertex,
const MinMax *min_max)
{
Sta *sta = Sta::sta();
PathRef path = sta->vertexWorstSlackPath(vertex, min_max);
if (!path.isNull())
return new PathRef(path);
else
return nullptr;
}
int
tag_group_count()
{
return Sta::sta()->tagGroupCount();
}
void
report_tag_groups()
{
Sta::sta()->search()->reportTagGroups();
}
void
report_tag_arrivals_cmd(Vertex *vertex)
{
Sta::sta()->search()->reportArrivals(vertex);
}
void
report_arrival_count_histogram()
{
Sta::sta()->search()->reportArrivalCountHistogram();
}
int
tag_count()
{
return Sta::sta()->tagCount();
}
void
report_tags()
{
Sta::sta()->search()->reportTags();
}
void
report_clk_infos()
{
Sta::sta()->search()->reportClkInfos();
}
int
clk_info_count()
{
return Sta::sta()->clkInfoCount();
}
int
arrival_count()
{
return Sta::sta()->arrivalCount();
}
int
required_count()
{
return Sta::sta()->requiredCount();
}
int
graph_arrival_count()
{
return Sta::sta()->graph()->arrivalCount();
}
int
graph_required_count()
{
return Sta::sta()->graph()->requiredCount();
}
int
endpoint_violation_count(const MinMax *min_max)
{
return Sta::sta()->endpointViolationCount(min_max);
}
void
report_loops()
{
Sta *sta = Sta::sta();
Network *network = cmdLinkedNetwork();
Graph *graph = cmdGraph();
Report *report = sta->report();
for (GraphLoop *loop : *sta->graphLoops()) {
loop->report(report, network, graph);
report->reportLineString("");
}
}
////////////////////////////////////////////////////////////////
PathEndSeq
find_path_ends(ExceptionFrom *from,
ExceptionThruSeq *thrus,
ExceptionTo *to,
bool unconstrained,
Corner *corner,
const MinMaxAll *delay_min_max,
int group_count,
int endpoint_count,
bool unique_pins,
float slack_min,
float slack_max,
bool sort_by_slack,
PathGroupNameSet *groups,
bool setup,
bool hold,
bool recovery,
bool removal,
bool clk_gating_setup,
bool clk_gating_hold)
{
cmdLinkedNetwork();
Sta *sta = Sta::sta();
PathEndSeq ends = sta->findPathEnds(from, thrus, to, unconstrained,
corner, delay_min_max,
group_count, endpoint_count, unique_pins,
slack_min, slack_max,
sort_by_slack,
groups->size() ? groups : nullptr,
setup, hold,
recovery, removal,
clk_gating_setup, clk_gating_hold);
delete groups;
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)
{
Sta::sta()->setReportPathFormat(format);
}
void
set_report_path_field_order(StringSeq *field_names)
{
Sta::sta()->setReportPathFieldOrder(field_names);
delete field_names;
}
void
set_report_path_fields(bool report_input_pin,
bool report_net,
bool report_cap,
bool report_slew,
bool report_fanout)
{
Sta::sta()->setReportPathFields(report_input_pin,
report_net,
report_cap,
report_slew,
report_fanout);
}
void
set_report_path_field_properties(const char *field_name,
const char *title,
int width,
bool left_justify)
{
Sta *sta = Sta::sta();
ReportField *field = sta->findReportPathField(field_name);
if (field)
field->setProperties(title, width, left_justify);
else
sta->report()->error(1575, "unknown report path field %s", field_name);
}
void
set_report_path_field_width(const char *field_name,
int width)
{
Sta *sta = Sta::sta();
ReportField *field = sta->findReportPathField(field_name);
if (field)
field->setWidth(width);
else
sta->report()->error(1576, "unknown report path field %s", field_name);
}
void
set_report_path_digits(int digits)
{
Sta::sta()->setReportPathDigits(digits);
}
void
set_report_path_no_split(bool no_split)
{
Sta::sta()->setReportPathNoSplit(no_split);
}
void
set_report_path_sigmas(bool report_sigmas)
{
Sta::sta()->setReportPathSigmas(report_sigmas);
}
void
delete_path_ref(PathRef *path)
{
delete path;
}
void
report_path_cmd(PathRef *path)
{
Sta::sta()->reportPath(path);
}
////////////////////////////////////////////////////////////////
void
define_corners_cmd(StringSet *corner_names)
{
Sta *sta = Sta::sta();
sta->makeCorners(corner_names);
delete corner_names;
}
Corner *
cmd_corner()
{
return Sta::sta()->cmdCorner();
}
void
set_cmd_corner(Corner *corner)
{
Sta::sta()->setCmdCorner(corner);
}
Corner *
find_corner(const char *corner_name)
{
return Sta::sta()->findCorner(corner_name);
}
Corners *
corners()
{
return Sta::sta()->corners();
}
bool
multi_corner()
{
return Sta::sta()->multiCorner();
}
////////////////////////////////////////////////////////////////
CheckErrorSeq &
check_timing_cmd(bool no_input_delay,
bool no_output_delay,
bool reg_multiple_clks,
bool reg_no_clks,
bool unconstrained_endpoints,
bool loops,
bool generated_clks)
{
cmdLinkedNetwork();
return Sta::sta()->checkTiming(no_input_delay, no_output_delay,
reg_multiple_clks, reg_no_clks,
unconstrained_endpoints,
loops, generated_clks);
}
%} // inline
////////////////////////////////////////////////////////////////
//
// Object Methods
//
////////////////////////////////////////////////////////////////
%extend PathEnd {
bool is_unconstrained() { return self->isUnconstrained(); }
bool is_check() { return self->isCheck(); }
bool is_latch_check() { return self->isLatchCheck(); }
bool is_data_check() { return self->isDataCheck(); }
bool is_output_delay() { return self->isOutputDelay(); }
bool is_path_delay() { return self->isPathDelay(); }
bool is_gated_clock() { return self->isGatedClock(); }
Vertex *vertex() { return self->vertex(Sta::sta()); }
PathRef *path() { return &self->pathRef(); }
RiseFall *end_transition()
{ return const_cast<RiseFall*>(self->path()->transition(Sta::sta())); }
Slack slack() { return self->slack(Sta::sta()); }
ArcDelay margin() { return self->margin(Sta::sta()); }
Required data_required_time() { return self->requiredTimeOffset(Sta::sta()); }
Arrival data_arrival_time() { return self->dataArrivalTimeOffset(Sta::sta()); }
TimingRole *check_role() { return self->checkRole(Sta::sta()); }
MinMax *min_max() { return const_cast<MinMax*>(self->minMax(Sta::sta())); }
float source_clk_offset() { return self->sourceClkOffset(Sta::sta()); }
Arrival source_clk_latency() { return self->sourceClkLatency(Sta::sta()); }
Arrival source_clk_insertion_delay()
{ return self->sourceClkInsertionDelay(Sta::sta()); }
const Clock *target_clk() { return self->targetClk(Sta::sta()); }
const ClockEdge *target_clk_edge() { return self->targetClkEdge(Sta::sta()); }
Path *target_clk_path() { return self->targetClkPath(); }
float target_clk_time() { return self->targetClkTime(Sta::sta()); }
float target_clk_offset() { return self->targetClkOffset(Sta::sta()); }
float target_clk_mcp_adjustment()
{ return self->targetClkMcpAdjustment(Sta::sta()); }
Arrival target_clk_delay() { return self->targetClkDelay(Sta::sta()); }
Arrival target_clk_insertion_delay()
{ return self->targetClkInsertionDelay(Sta::sta()); }
float target_clk_uncertainty()
{ return self->targetNonInterClkUncertainty(Sta::sta()); }
float inter_clk_uncertainty()
{ return self->interClkUncertainty(Sta::sta()); }
Arrival target_clk_arrival() { return self->targetClkArrival(Sta::sta()); }
bool path_delay_margin_is_external()
{ return self->pathDelayMarginIsExternal();}
Crpr check_crpr() { return self->checkCrpr(Sta::sta()); }
RiseFall *target_clk_end_trans()
{ return const_cast<RiseFall*>(self->targetClkEndTrans(Sta::sta())); }
Delay clk_skew() { return self->clkSkew(Sta::sta()); }
}
%extend PathRef {
float
arrival()
{
Sta *sta = Sta::sta();
return delayAsFloat(self->arrival(sta));
}
float
required()
{
Sta *sta = Sta::sta();
return delayAsFloat(self->required(sta));
}
float
slack()
{
Sta *sta = Sta::sta();
return delayAsFloat(self->slack(sta));
}
const Pin *
pin()
{
Sta *sta = Sta::sta();
return self->pin(sta);
}
const char *
tag()
{
Sta *sta = Sta::sta();
return self->tag(sta)->asString(sta);
}
// mea_opt3
PinSeq
pins()
{
Sta *sta = Sta::sta();
PinSeq pins;
PathRef path1(self);
while (!path1.isNull()) {
pins.push_back(path1.vertex(sta)->pin());
PathRef prev_path;
path1.prevPath(sta, prev_path);
path1.init(prev_path);
}
return pins;
}
}
%extend VertexPathIterator {
bool has_next() { return self->hasNext(); }
PathRef *
next()
{
Path *path = self->next();
return new PathRef(path);
}
void finish() { delete self; }
}
%extend MinPulseWidthCheckSeqIterator {
bool has_next() { return self->hasNext(); }
MinPulseWidthCheck *next() { return self->next(); }
void finish() { delete self; }
} // MinPulseWidthCheckSeqIterator methods
%extend Corner {
const char *name() { return self->name(); }
}