OpenSTA/liberty/Liberty.i

564 lines
12 KiB
OpenEdge ABL

// OpenSTA, Static Timing Analyzer
// Copyright (c) 2025, 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/>.
//
// The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software.
//
// Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
//
// This notice may not be removed or altered from any source distribution.
%module liberty
%{
#include "PortDirection.hh"
#include "Liberty.hh"
#include "EquivCells.hh"
#include "LibertyWriter.hh"
#include "Sta.hh"
using namespace sta;
%}
////////////////////////////////////////////////////////////////
//
// Empty class definitions to make swig happy.
// Private constructor/destructor so swig doesn't emit them.
//
////////////////////////////////////////////////////////////////
class LibertyLibrary
{
private:
LibertyLibrary();
~LibertyLibrary();
};
class LibertyLibraryIterator
{
private:
LibertyLibraryIterator();
~LibertyLibraryIterator();
};
class LibertyCell
{
private:
LibertyCell();
~LibertyCell();
};
class LibertyPort
{
private:
LibertyPort();
~LibertyPort();
};
class LibertyCellPortIterator
{
private:
LibertyCellPortIterator();
~LibertyCellPortIterator();
};
class LibertyPortMemberIterator
{
private:
LibertyPortMemberIterator();
~LibertyPortMemberIterator();
};
class TimingArcSet
{
private:
TimingArcSet();
~TimingArcSet();
};
class TimingArc
{
private:
TimingArc();
~TimingArc();
};
class Wireload
{
private:
Wireload();
~Wireload();
};
class WireloadSelection
{
private:
WireloadSelection();
~WireloadSelection();
};
%inline %{
bool
read_liberty_cmd(char *filename,
Corner *corner,
const MinMaxAll *min_max,
bool infer_latches)
{
Sta *sta = Sta::sta();
LibertyLibrary *lib = sta->readLiberty(filename, corner, min_max, infer_latches);
return (lib != nullptr);
}
void
write_liberty_cmd(LibertyLibrary *library,
char *filename)
{
writeLiberty(library, filename, Sta::sta());
}
void
make_equiv_cells(LibertyLibrary *lib)
{
LibertyLibrarySeq libs;
libs.push_back(lib);
Sta::sta()->makeEquivCells(&libs, nullptr);
}
LibertyCellSeq *
find_equiv_cells(LibertyCell *cell)
{
return Sta::sta()->equivCells(cell);
}
bool
equiv_cells(LibertyCell *cell1,
LibertyCell *cell2)
{
return sta::equivCells(cell1, cell2);
}
bool
equiv_cell_ports(LibertyCell *cell1,
LibertyCell *cell2)
{
return equivCellPorts(cell1, cell2);
}
bool
equiv_cell_timing_arcs(LibertyCell *cell1,
LibertyCell *cell2)
{
return equivCellTimingArcSets(cell1, cell2);
}
LibertyCellSeq *
find_library_buffers(LibertyLibrary *library)
{
return library->buffers();
}
const char *
liberty_port_direction(const LibertyPort *port)
{
return port->direction()->name();
}
bool
liberty_supply_exists(const char *supply_name)
{
auto network = Sta::sta()->network();
auto lib = network->defaultLibertyLibrary();
return lib && lib->supplyExists(supply_name);
}
LibertyLibraryIterator *
liberty_library_iterator()
{
return Sta::sta()->network()->libertyLibraryIterator();
}
LibertyLibrary *
find_liberty(const char *name)
{
return Sta::sta()->network()->findLiberty(name);
}
LibertyCell *
find_liberty_cell(const char *name)
{
return Sta::sta()->network()->findLibertyCell(name);
}
bool
timing_role_is_check(const TimingRole *role)
{
return role->isTimingCheck();
}
%} // inline
////////////////////////////////////////////////////////////////
//
// Object Methods
//
////////////////////////////////////////////////////////////////
%extend LibertyLibrary {
const char *name() { return self->name(); }
LibertyCell *
find_liberty_cell(const char *name)
{
return self->findLibertyCell(name);
}
LibertyCellSeq
find_liberty_cells_matching(const char *pattern,
bool regexp,
bool nocase)
{
PatternMatch matcher(pattern, regexp, nocase, Sta::sta()->tclInterp());
return self->findLibertyCellsMatching(&matcher);
}
Wireload *
find_wireload(const char *model_name)
{
return self->findWireload(model_name);
}
WireloadSelection *
find_wireload_selection(const char *selection_name)
{
return self->findWireloadSelection(selection_name);
}
OperatingConditions *
find_operating_conditions(const char *op_cond_name)
{
return self->findOperatingConditions(op_cond_name);
}
OperatingConditions *
default_operating_conditions()
{
return self->defaultOperatingConditions();
}
} // LibertyLibrary methods
%extend LibertyCell {
const char *name() { return self->name(); }
bool is_leaf() { return self->isLeaf(); }
bool is_buffer() { return self->isBuffer(); }
bool is_inverter() { return self->isInverter(); }
LibertyLibrary *liberty_library() { return self->libertyLibrary(); }
Cell *cell() { return reinterpret_cast<Cell*>(self); }
LibertyPort *
find_liberty_port(const char *name)
{
return self->findLibertyPort(name);
}
LibertyPortSeq
find_liberty_ports_matching(const char *pattern,
bool regexp,
bool nocase)
{
PatternMatch matcher(pattern, regexp, nocase, Sta::sta()->tclInterp());
return self->findLibertyPortsMatching(&matcher);
}
LibertyCellPortIterator *
liberty_port_iterator() { return new LibertyCellPortIterator(self); }
const TimingArcSetSeq &
timing_arc_sets()
{
return self->timingArcSets();
}
void
ensure_voltage_waveforms()
{
Corners *corners = Sta::sta()->corners();
const DcalcAnalysisPtSeq &dcalc_aps = corners->dcalcAnalysisPts();
self->ensureVoltageWaveforms(dcalc_aps);
}
LibertyCell *test_cell() { return self->testCell(); }
} // LibertyCell methods
%extend LibertyPort {
const char *bus_name() { return self->busName(); }
Cell *cell() { return self->cell(); }
bool is_bus() { return self->isBus(); }
bool is_bus_bit() { return self->isBusBit(); }
bool is_bundle() { return self->isBundle(); }
bool is_bundle_member() { return self->isBundleMember(); }
bool has_members() { return self->hasMembers(); }
LibertyPortMemberIterator *
member_iterator() { return new LibertyPortMemberIterator(self); }
LibertyPort *bundle_port() { return self->bundlePort(); }
string
function()
{
FuncExpr *func = self->function();
if (func)
return func->to_string();
else
return "";
}
string
tristate_enable()
{
FuncExpr *enable = self->tristateEnable();
if (enable)
return enable->to_string();
else
return "";
}
float
capacitance(Corner *corner,
const MinMax *min_max)
{
Sta *sta = Sta::sta();
return sta->capacitance(self, corner, min_max);
}
void
set_direction(const char *dir)
{
self->setDirection(PortDirection::find(dir));
}
const char *
scan_signal_type()
{
return scanSignalTypeName(self->scanSignalType());
}
} // LibertyPort methods
%extend TimingArcSet {
LibertyPort *from() { return self->from(); }
LibertyPort *to() { return self->to(); }
const TimingRole *role() { return self->role(); }
const char *sdf_cond() { return self->sdfCond(); }
const char *
full_name()
{
const char *from = self->from()->name();
const char *to = self->to()->name();
const char *cell_name = self->libertyCell()->name();
return stringPrintTmp("%s %s -> %s",
cell_name,
from,
to);
}
TimingArcSeq &
timing_arcs() { return self->arcs(); }
} // TimingArcSet methods
%extend TimingArc {
LibertyPort *from() { return self->from(); }
LibertyPort *to() { return self->to(); }
const Transition *from_edge() { return self->fromEdge(); }
const char *from_edge_name() { return self->fromEdge()->asRiseFall()->name(); }
const Transition *to_edge() { return self->toEdge(); }
const char *to_edge_name() { return self->toEdge()->asRiseFall()->name(); }
const TimingRole *role() { return self->role(); }
float
time_voltage(float in_slew,
float load_cap,
float time)
{
GateTableModel *gate_model = self->gateTableModel();
if (gate_model) {
OutputWaveforms *waveforms = gate_model->outputWaveforms();
if (waveforms)
return waveforms->timeVoltage(in_slew, load_cap, time);
}
return 0.0;
}
float
time_current(float in_slew,
float load_cap,
float time)
{
GateTableModel *gate_model = self->gateTableModel();
if (gate_model) {
OutputWaveforms *waveforms = gate_model->outputWaveforms();
if (waveforms)
return waveforms->timeCurrent(in_slew, load_cap, time);
}
return 0.0;
}
float
voltage_current(float in_slew,
float load_cap,
float voltage)
{
GateTableModel *gate_model = self->gateTableModel();
if (gate_model) {
OutputWaveforms *waveforms = gate_model->outputWaveforms();
if (waveforms)
return waveforms->voltageCurrent(in_slew, load_cap, voltage);
}
return 0.0;
}
float
voltage_time(float in_slew,
float load_cap,
float voltage)
{
GateTableModel *gate_model = self->gateTableModel();
if (gate_model) {
OutputWaveforms *waveforms = gate_model->outputWaveforms();
if (waveforms)
return waveforms->voltageTime(in_slew, load_cap, voltage);
}
return 0.0;
}
Table1
voltage_waveform(float in_slew,
float load_cap)
{
GateTableModel *gate_model = self->gateTableModel();
if (gate_model) {
OutputWaveforms *waveforms = gate_model->outputWaveforms();
if (waveforms) {
Table1 waveform = waveforms->voltageWaveform(in_slew, load_cap);
return waveform;
}
}
return Table1();
}
const Table1 *
voltage_waveform_raw(float in_slew,
float load_cap)
{
GateTableModel *gate_model = self->gateTableModel();
if (gate_model) {
OutputWaveforms *waveforms = gate_model->outputWaveforms();
if (waveforms) {
const Table1 *waveform = waveforms->voltageWaveformRaw(in_slew, load_cap);
return waveform;
}
}
return nullptr;
}
Table1
current_waveform(float in_slew,
float load_cap)
{
GateTableModel *gate_model = self->gateTableModel();
if (gate_model) {
OutputWaveforms *waveforms = gate_model->outputWaveforms();
if (waveforms) {
Table1 waveform = waveforms->currentWaveform(in_slew, load_cap);
return waveform;
}
}
return Table1();
}
const Table1 *
current_waveform_raw(float in_slew,
float load_cap)
{
GateTableModel *gate_model = self->gateTableModel();
if (gate_model) {
OutputWaveforms *waveforms = gate_model->outputWaveforms();
if (waveforms) {
const Table1 *waveform = waveforms->currentWaveformRaw(in_slew, load_cap);
return waveform;
}
}
return nullptr;
}
Table1
voltage_current_waveform(float in_slew,
float load_cap)
{
GateTableModel *gate_model = self->gateTableModel();
if (gate_model) {
OutputWaveforms *waveforms = gate_model->outputWaveforms();
if (waveforms) {
Table1 waveform = waveforms->voltageCurrentWaveform(in_slew, load_cap);
return waveform;
}
}
return Table1();
}
float
final_resistance()
{
GateTableModel *gate_model = self->gateTableModel();
if (gate_model) {
OutputWaveforms *waveforms = gate_model->outputWaveforms();
if (waveforms) {
return waveforms->finalResistance();
}
}
return 0.0;
}
} // TimingArc methods
%extend OperatingConditions {
float process() { return self->process(); }
float voltage() { return self->voltage(); }
float temperature() { return self->temperature(); }
}
%extend LibertyLibraryIterator {
bool has_next() { return self->hasNext(); }
LibertyLibrary *next() { return self->next(); }
void finish() { delete self; }
} // LibertyLibraryIterator methods
%extend LibertyCellPortIterator {
bool has_next() { return self->hasNext(); }
LibertyPort *next() { return self->next(); }
void finish() { delete self; }
} // LibertyCellPortIterator methods
%extend LibertyPortMemberIterator {
bool has_next() { return self->hasNext(); }
LibertyPort *next() { return self->next(); }
void finish() { delete self; }
} // LibertyPortMemberIterator methods