// 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 . // // 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 sdc %{ #include "Sdc.hh" #include "Wireload.hh" #include "Clock.hh" #include "PortDelay.hh" #include "Property.hh" #include "Sta.hh" using namespace sta; %} //////////////////////////////////////////////////////////////// // // Empty class definitions to make swig happy. // Private constructor/destructor so swig doesn't emit them. // //////////////////////////////////////////////////////////////// class Clock { private: Clock(); ~Clock(); }; class ClockEdge { private: ClockEdge(); ~ClockEdge(); }; class ExceptionFrom { private: ExceptionFrom(); ~ExceptionFrom(); }; class ExceptionThru { private: ExceptionThru(); ~ExceptionThru(); }; class ExceptionTo { private: ExceptionTo(); ~ExceptionTo(); }; class OperatingConditions { private: OperatingConditions(); ~OperatingConditions(); }; %inline %{ void write_sdc_cmd(const char *filename, bool leaf, bool compatible, int digits, bool gzip, bool no_timestamp) { Sta::sta()->writeSdc(filename, leaf, compatible, digits, gzip, no_timestamp); } void set_analysis_type_cmd(const char *analysis_type) { AnalysisType type; if (stringEq(analysis_type, "single")) type = AnalysisType::single; else if (stringEq(analysis_type, "bc_wc")) type = AnalysisType::bc_wc; else if (stringEq(analysis_type, "on_chip_variation")) type = AnalysisType::ocv; else { Sta::sta()->report()->warn(2121, "unknown analysis type"); type = AnalysisType::single; } Sta::sta()->setAnalysisType(type); } OperatingConditions * operating_conditions(const MinMax *min_max) { return Sta::sta()->operatingConditions(min_max); } void set_operating_conditions_cmd(OperatingConditions *op_cond, const MinMaxAll *min_max) { Sta::sta()->setOperatingConditions(op_cond, min_max); } const char * operating_condition_analysis_type() { switch (Sta::sta()->sdc()->analysisType()){ case AnalysisType::single: return "single"; case AnalysisType::bc_wc: return "bc_wc"; case AnalysisType::ocv: return "on_chip_variation"; } // Prevent warnings from lame compilers. return "?"; } void set_instance_pvt(Instance *inst, const MinMaxAll *min_max, float process, float voltage, float temperature) { Pvt pvt(process, voltage, temperature); Sta::sta()->setPvt(inst, min_max, pvt); } float port_ext_pin_cap(const Port *port, const Corner *corner, const MinMax *min_max) { float pin_cap, wire_cap; int fanout; Sta::sta()->portExtCaps(port, corner, min_max, pin_cap, wire_cap, fanout); return pin_cap; } void set_port_ext_pin_cap(const Port *port, const RiseFallBoth *rf, const Corner *corner, const MinMaxAll *min_max, float cap) { Sta::sta()->setPortExtPinCap(port, rf, corner, min_max, cap); } float port_ext_wire_cap(const Port *port, const Corner *corner, const MinMax *min_max) { float pin_cap, wire_cap; int fanout; Sta::sta()->portExtCaps(port, corner, min_max, pin_cap, wire_cap, fanout); return wire_cap; } void set_port_ext_wire_cap(const Port *port, bool subtract_pin_cap, const RiseFallBoth *rf, const Corner *corner, const MinMaxAll *min_max, float cap) { Sta::sta()->setPortExtWireCap(port, subtract_pin_cap, rf, corner, min_max, cap); } void set_port_ext_fanout_cmd(const Port *port, int fanout, const Corner *corner, const MinMaxAll *min_max) { Sta::sta()->setPortExtFanout(port, fanout, corner, min_max); } float port_ext_fanout(const Port *port, const Corner *corner, const MinMax *min_max) { float pin_cap, wire_cap; int fanout; Sta::sta()->portExtCaps(port, corner, min_max, pin_cap, wire_cap, fanout); return fanout; } void set_net_wire_cap(const Net *net, bool subtract_pin_cap, const Corner *corner, const MinMaxAll *min_max, float cap) { Sta::sta()->setNetWireCap(net, subtract_pin_cap, corner, min_max, cap); } void set_wire_load_mode_cmd(const char *mode_name) { WireloadMode mode = stringWireloadMode(mode_name); if (mode == WireloadMode::unknown) Sta::sta()->report()->warn(2122, "unknown wire load mode"); else Sta::sta()->setWireloadMode(mode); } void set_net_resistance(Net *net, const MinMaxAll *min_max, float res) { Sta::sta()->setResistance(net, min_max, res); } void set_wire_load_cmd(Wireload *wireload, const MinMaxAll *min_max) { Sta::sta()->setWireload(wireload, min_max); } void set_wire_load_selection_group_cmd(WireloadSelection *selection, const MinMaxAll *min_max) { Sta::sta()->setWireloadSelection(selection, min_max); } void make_clock(const char *name, PinSet *pins, bool add_to_pins, float period, FloatSeq *waveform, char *comment) { Sta::sta()->makeClock(name, pins, add_to_pins, period, waveform, comment); } void make_generated_clock(const char *name, PinSet *pins, bool add_to_pins, Pin *src_pin, Clock *master_clk, int divide_by, int multiply_by, float duty_cycle, bool invert, bool combinational, IntSeq *edges, FloatSeq *edge_shifts, char *comment) { Sta::sta()->makeGeneratedClock(name, pins, add_to_pins, src_pin, master_clk, divide_by, multiply_by, duty_cycle, invert, combinational, edges, edge_shifts, comment); } void remove_clock_cmd(Clock *clk) { Sta::sta()->removeClock(clk); } void set_propagated_clock_cmd(Clock *clk) { Sta::sta()->setPropagatedClock(clk); } void set_propagated_clock_pin_cmd(Pin *pin) { Sta::sta()->setPropagatedClock(pin); } void unset_propagated_clock_cmd(Clock *clk) { Sta::sta()->removePropagatedClock(clk); } void unset_propagated_clock_pin_cmd(Pin *pin) { Sta::sta()->removePropagatedClock(pin); } void set_clock_slew_cmd(Clock *clk, const RiseFallBoth *rf, const MinMaxAll *min_max, float slew) { Sta::sta()->setClockSlew(clk, rf, min_max, slew); } void unset_clock_slew_cmd(Clock *clk) { Sta::sta()->removeClockSlew(clk); } void set_clock_latency_cmd(Clock *clk, Pin *pin, const RiseFallBoth *rf, MinMaxAll *min_max, float delay) { Sta::sta()->setClockLatency(clk, pin, rf, min_max, delay); } void set_clock_insertion_cmd(Clock *clk, Pin *pin, const RiseFallBoth *rf, const MinMaxAll *min_max, const EarlyLateAll *early_late, float delay) { Sta::sta()->setClockInsertion(clk, pin, rf, min_max, early_late, delay); } void unset_clock_latency_cmd(Clock *clk, Pin *pin) { Sta::sta()->removeClockLatency(clk, pin); } void unset_clock_insertion_cmd(Clock *clk, Pin *pin) { Sta::sta()->removeClockInsertion(clk, pin); } void set_clock_uncertainty_clk(Clock *clk, const SetupHoldAll *setup_hold, float uncertainty) { Sta::sta()->setClockUncertainty(clk, setup_hold, uncertainty); } void unset_clock_uncertainty_clk(Clock *clk, const SetupHoldAll *setup_hold) { Sta::sta()->removeClockUncertainty(clk, setup_hold); } void set_clock_uncertainty_pin(Pin *pin, const MinMaxAll *min_max, float uncertainty) { Sta::sta()->setClockUncertainty(pin, min_max, uncertainty); } void unset_clock_uncertainty_pin(Pin *pin, const MinMaxAll *min_max) { Sta::sta()->removeClockUncertainty(pin, min_max); } void set_inter_clock_uncertainty(Clock *from_clk, const RiseFallBoth *from_tr, Clock *to_clk, const RiseFallBoth *to_tr, const MinMaxAll *min_max, float uncertainty) { Sta::sta()->setClockUncertainty(from_clk, from_tr, to_clk, to_tr, min_max, uncertainty); } void unset_inter_clock_uncertainty(Clock *from_clk, const RiseFallBoth *from_tr, Clock *to_clk, const RiseFallBoth *to_tr, const MinMaxAll *min_max) { Sta::sta()->removeClockUncertainty(from_clk, from_tr, to_clk, to_tr, min_max); } void set_clock_gating_check_cmd(const RiseFallBoth *rf, const SetupHold *setup_hold, float margin) { Sta::sta()->setClockGatingCheck(rf, setup_hold, margin); } void set_clock_gating_check_clk_cmd(Clock *clk, const RiseFallBoth *rf, const SetupHold *setup_hold, float margin) { Sta::sta()->setClockGatingCheck(clk, rf, setup_hold, margin); } void set_clock_gating_check_pin_cmd(Pin *pin, const RiseFallBoth *rf, const SetupHold *setup_hold, float margin, LogicValue active_value) { Sta::sta()->setClockGatingCheck(pin, rf, setup_hold, margin, active_value); } void set_clock_gating_check_instance_cmd(Instance *inst, const RiseFallBoth *rf, const SetupHold *setup_hold, float margin, LogicValue active_value) { Sta::sta()->setClockGatingCheck(inst, rf, setup_hold, margin, active_value); } void set_data_check_cmd(Pin *from, const RiseFallBoth *from_rf, Pin *to, const RiseFallBoth *to_rf, Clock *clk, const SetupHoldAll *setup_hold, float margin) { Sta::sta()->setDataCheck(from, from_rf, to, to_rf, clk, setup_hold, margin); } void unset_data_check_cmd(Pin *from, const RiseFallBoth *from_tr, Pin *to, const RiseFallBoth *to_tr, Clock *clk, const SetupHoldAll *setup_hold) { Sta::sta()->removeDataCheck(from, from_tr, to, to_tr, clk, setup_hold); } void set_input_delay_cmd(Pin *pin, RiseFallBoth *rf, Clock *clk, RiseFall *clk_rf, Pin *ref_pin, bool source_latency_included, bool network_latency_included, MinMaxAll *min_max, bool add, float delay) { Sta::sta()->setInputDelay(pin, rf, clk, clk_rf, ref_pin, source_latency_included, network_latency_included, min_max, add, delay); } void unset_input_delay_cmd(Pin *pin, RiseFallBoth *rf, Clock *clk, RiseFall *clk_rf, MinMaxAll *min_max) { Sta::sta()->removeInputDelay(pin, rf, clk, clk_rf, min_max); } void set_output_delay_cmd(Pin *pin, const RiseFallBoth *rf, Clock *clk, const RiseFall *clk_rf, Pin *ref_pin, bool source_latency_included, bool network_latency_included, const MinMaxAll *min_max, bool add, float delay) { Sta::sta()->setOutputDelay(pin, rf, clk, clk_rf, ref_pin, source_latency_included, network_latency_included, min_max, add, delay); } void unset_output_delay_cmd(Pin *pin, RiseFallBoth *rf, Clock *clk, RiseFall *clk_rf, MinMaxAll *min_max) { Sta::sta()->removeOutputDelay(pin, rf, clk, clk_rf, min_max); } void disable_cell(LibertyCell *cell, LibertyPort *from, LibertyPort *to) { Sta::sta()->disable(cell, from, to); } void unset_disable_cell(LibertyCell *cell, LibertyPort *from, LibertyPort *to) { Sta::sta()->removeDisable(cell, from, to); } void disable_lib_port(LibertyPort *port) { Sta::sta()->disable(port); } void unset_disable_lib_port(LibertyPort *port) { Sta::sta()->removeDisable(port); } void disable_port(Port *port) { Sta::sta()->disable(port); } void unset_disable_port(Port *port) { Sta::sta()->removeDisable(port); } void disable_instance(Instance *instance, LibertyPort *from, LibertyPort *to) { Sta::sta()->disable(instance, from, to); } void unset_disable_instance(Instance *instance, LibertyPort *from, LibertyPort *to) { Sta::sta()->removeDisable(instance, from, to); } void disable_pin(Pin *pin) { Sta::sta()->disable(pin); } void unset_disable_pin(Pin *pin) { Sta::sta()->removeDisable(pin); } void disable_edge(Edge *edge) { Sta::sta()->disable(edge); } void unset_disable_edge(Edge *edge) { Sta::sta()->removeDisable(edge); } void disable_timing_arc_set(TimingArcSet *arc_set) { Sta::sta()->disable(arc_set); } void unset_disable_timing_arc_set(TimingArcSet *arc_set) { Sta::sta()->removeDisable(arc_set); } void disable_clock_gating_check_inst(Instance *inst) { Sta::sta()->disableClockGatingCheck(inst); } void disable_clock_gating_check_pin(Pin *pin) { Sta::sta()->disableClockGatingCheck(pin); } void unset_disable_clock_gating_check_inst(Instance *inst) { Sta::sta()->removeDisableClockGatingCheck(inst); } void unset_disable_clock_gating_check_pin(Pin *pin) { Sta::sta()->removeDisableClockGatingCheck(pin); } EdgeSeq disabled_edges_sorted() { return Sta::sta()->disabledEdgesSorted(); } bool timing_arc_disabled(Edge *edge, TimingArc *arc) { Graph *graph = Sta::sta()->graph(); return !searchThru(edge, arc, graph); } void make_false_path(ExceptionFrom *from, ExceptionThruSeq *thrus, ExceptionTo *to, const MinMaxAll *min_max, const char *comment) { Sta::sta()->makeFalsePath(from, thrus, to, min_max, comment); } void make_multicycle_path(ExceptionFrom *from, ExceptionThruSeq *thrus, ExceptionTo *to, const MinMaxAll *min_max, bool use_end_clk, int path_multiplier, const char *comment) { Sta::sta()->makeMulticyclePath(from, thrus, to, min_max, use_end_clk, path_multiplier, comment); } void make_path_delay(ExceptionFrom *from, ExceptionThruSeq *thrus, ExceptionTo *to, const MinMax *min_max, bool ignore_clk_latency, bool break_path, float delay, const char *comment) { Sta::sta()->makePathDelay(from, thrus, to, min_max, ignore_clk_latency, break_path, delay, comment); } void reset_path_cmd(ExceptionFrom * from, ExceptionThruSeq *thrus, ExceptionTo *to, const MinMaxAll *min_max) { Sta::sta()->resetPath(from, thrus, to, min_max); // from/to and thru are owned and deleted by the caller. // ExceptionThruSeq thrus arg is made by TclListSeqExceptionThru // in the swig converter so it is deleted here. delete thrus; } void make_group_path(const char *name, bool is_default, ExceptionFrom *from, ExceptionThruSeq *thrus, ExceptionTo *to, const char *comment) { if (name[0] == '\0') name = nullptr; Sta::sta()->makeGroupPath(name, is_default, from, thrus, to, comment); } bool is_path_group_name(const char *name) { return Sta::sta()->isGroupPathName(name); } ExceptionFrom * make_exception_from(PinSet *from_pins, ClockSet *from_clks, InstanceSet *from_insts, const RiseFallBoth *from_tr) { return Sta::sta()->makeExceptionFrom(from_pins, from_clks, from_insts, from_tr); } void delete_exception_from(ExceptionFrom *from) { Sta::sta()->deleteExceptionFrom(from); } void check_exception_from_pins(ExceptionFrom *from, const char *file, int line) { Sta::sta()->checkExceptionFromPins(from, file, line); } ExceptionThru * make_exception_thru(PinSet *pins, NetSet *nets, InstanceSet *insts, const RiseFallBoth *rf) { return Sta::sta()->makeExceptionThru(pins, nets, insts, rf); } void delete_exception_thru(ExceptionThru *thru) { Sta::sta()->deleteExceptionThru(thru); } ExceptionTo * make_exception_to(PinSet *to_pins, ClockSet *to_clks, InstanceSet *to_insts, const RiseFallBoth *rf, RiseFallBoth *end_rf) { return Sta::sta()->makeExceptionTo(to_pins, to_clks, to_insts, rf, end_rf); } void delete_exception_to(ExceptionTo *to) { Sta::sta()->deleteExceptionTo(to); } void check_exception_to_pins(ExceptionTo *to, const char *file, int line) { Sta::sta()->checkExceptionToPins(to, file, line); } ClockGroups * make_clock_groups(const char *name, bool logically_exclusive, bool physically_exclusive, bool asynchronous, bool allow_paths, const char *comment) { return Sta::sta()->makeClockGroups(name, logically_exclusive, physically_exclusive, asynchronous, allow_paths, comment); } void clock_groups_make_group(ClockGroups *clk_groups, ClockSet *clks) { Sta::sta()->makeClockGroup(clk_groups, clks); } void unset_clock_groups_logically_exclusive(const char *name) { Sta::sta()->removeClockGroupsLogicallyExclusive(name); } void unset_clock_groups_physically_exclusive(const char *name) { Sta::sta()->removeClockGroupsPhysicallyExclusive(name); } void unset_clock_groups_asynchronous(const char *name) { Sta::sta()->removeClockGroupsAsynchronous(name); } // Debugging function. bool same_clk_group(Clock *clk1, Clock *clk2) { Sta *sta = Sta::sta(); Sdc *sdc = sta->sdc(); return sdc->sameClockGroupExplicit(clk1, clk2); } void set_clock_sense_cmd(PinSet *pins, ClockSet *clks, bool positive, bool negative, bool stop_propagation) { Sta *sta = Sta::sta(); if (positive) sta->setClockSense(pins, clks, ClockSense::positive); else if (negative) sta->setClockSense(pins, clks, ClockSense::negative); else if (stop_propagation) sta->setClockSense(pins, clks, ClockSense::stop); else sta->report()->critical(1577, "unknown clock sense"); } void set_input_slew_cmd(Port *port, const RiseFallBoth *rf, const MinMaxAll *min_max, float slew) { Sta::sta()->setInputSlew(port, rf, min_max, slew); } void set_drive_cell_cmd(LibertyLibrary *library, LibertyCell *cell, Port *port, LibertyPort *from_port, float from_slew_rise, float from_slew_fall, LibertyPort *to_port, const RiseFallBoth *rf, const MinMaxAll *min_max) { float from_slews[RiseFall::index_count]; from_slews[RiseFall::riseIndex()] = from_slew_rise; from_slews[RiseFall::fallIndex()] = from_slew_fall; Sta::sta()->setDriveCell(library, cell, port, from_port, from_slews, to_port, rf, min_max); } void set_drive_resistance_cmd(Port *port, const RiseFallBoth *rf, const MinMaxAll *min_max, float res) { Sta::sta()->setDriveResistance(port, rf, min_max, res); } void set_slew_limit_clk(Clock *clk, const RiseFallBoth *rf, PathClkOrData clk_data, const MinMax *min_max, float slew) { Sta::sta()->setSlewLimit(clk, rf, clk_data, min_max, slew); } void set_slew_limit_port(Port *port, const MinMax *min_max, float slew) { Sta::sta()->setSlewLimit(port, min_max, slew); } void set_slew_limit_cell(Cell *cell, const MinMax *min_max, float slew) { Sta::sta()->setSlewLimit(cell, min_max, slew); } void set_port_capacitance_limit(Port *port, const MinMax *min_max, float cap) { Sta::sta()->setCapacitanceLimit(port, min_max, cap); } void set_pin_capacitance_limit(Pin *pin, const MinMax *min_max, float cap) { Sta::sta()->setCapacitanceLimit(pin, min_max, cap); } void set_cell_capacitance_limit(Cell *cell, const MinMax *min_max, float cap) { Sta::sta()->setCapacitanceLimit(cell, min_max, cap); } void set_latch_borrow_limit_pin(Pin *pin, float limit) { Sta::sta()->setLatchBorrowLimit(pin, limit); } void set_latch_borrow_limit_inst(Instance *inst, float limit) { Sta::sta()->setLatchBorrowLimit(inst, limit); } void set_latch_borrow_limit_clk(Clock *clk, float limit) { Sta::sta()->setLatchBorrowLimit(clk, limit); } void set_min_pulse_width_global(const RiseFallBoth *rf, float min_width) { Sta::sta()->setMinPulseWidth(rf, min_width); } void set_min_pulse_width_pin(Pin *pin, const RiseFallBoth *rf, float min_width) { Sta::sta()->setMinPulseWidth(pin, rf, min_width); } void set_min_pulse_width_clk(Clock *clk, const RiseFallBoth *rf, float min_width) { Sta::sta()->setMinPulseWidth(clk, rf, min_width); } void set_min_pulse_width_inst(Instance *inst, const RiseFallBoth *rf, float min_width) { Sta::sta()->setMinPulseWidth(inst, rf, min_width); } void set_max_area_cmd(float area) { Sta::sta()->setMaxArea(area); } void set_port_fanout_limit(Port *port, const MinMax *min_max, float fanout) { Sta::sta()->setFanoutLimit(port, min_max, fanout); } void set_cell_fanout_limit(Cell *cell, const MinMax *min_max, float fanout) { Sta::sta()->setFanoutLimit(cell, min_max, fanout); } void set_logic_value_cmd(Pin *pin, LogicValue value) { Sta::sta()->setLogicValue(pin, value); } void set_case_analysis_cmd(Pin *pin, LogicValue value) { Sta::sta()->setCaseAnalysis(pin, value); } void unset_case_analysis_cmd(Pin *pin) { Sta::sta()->removeCaseAnalysis(pin); } void set_timing_derate_cmd(TimingDerateType type, PathClkOrData clk_data, const RiseFallBoth *rf, const EarlyLate *early_late, float derate) { Sta::sta()->setTimingDerate(type, clk_data, rf, early_late, derate); } void set_timing_derate_net_cmd(const Net *net, PathClkOrData clk_data, const RiseFallBoth *rf, const EarlyLate *early_late, float derate) { Sta::sta()->setTimingDerate(net, clk_data, rf, early_late, derate); } void set_timing_derate_inst_cmd(const Instance *inst, TimingDerateCellType type, PathClkOrData clk_data, const RiseFallBoth *rf, const EarlyLate *early_late, float derate) { Sta::sta()->setTimingDerate(inst, type, clk_data, rf, early_late, derate); } void set_timing_derate_cell_cmd(const LibertyCell *cell, TimingDerateCellType type, PathClkOrData clk_data, const RiseFallBoth *rf, const EarlyLate *early_late, float derate) { Sta::sta()->setTimingDerate(cell, type, clk_data, rf, early_late, derate); } void unset_timing_derate_cmd() { Sta::sta()->unsetTimingDerate(); } Clock * find_clock(const char *name) { return Sta::sta()->sdc()->findClock(name); } bool is_clock_src(const Pin *pin) { return Sta::sta()->isClockSrc(pin); } Clock * default_arrival_clock() { return Sta::sta()->sdc()->defaultArrivalClock(); } ClockSeq find_clocks_matching(const char *pattern, bool regexp, bool nocase) { Sta *sta = Sta::sta(); Sdc *sdc = sta->sdc(); PatternMatch matcher(pattern, regexp, nocase, sta->tclInterp()); return sdc->findClocksMatching(&matcher); } void update_generated_clks() { Sta::sta()->updateGeneratedClks(); } bool is_clock(Pin *pin) { return Sta::sta()->isClock(pin); } bool is_ideal_clock(Pin *pin) { return Sta::sta()->isIdealClock(pin); } bool is_clock_search(const Pin *pin) { Sta *sta = Sta::sta(); Graph *graph = sta->graph(); Search *search = sta->search(); Vertex *vertex, *bidirect_drvr_vertex; graph->pinVertices(pin, vertex, bidirect_drvr_vertex); return search->isClock(vertex); } bool is_genclk_src(const Pin *pin) { Sta *sta = Sta::sta(); Graph *graph = sta->graph(); Search *search = sta->search(); Vertex *vertex, *bidirect_drvr_vertex; graph->pinVertices(pin, vertex, bidirect_drvr_vertex); return search->isGenClkSrc(vertex); } bool pin_is_constrained(Pin *pin) { return Sta::sta()->sdc()->isConstrained(pin); } bool instance_is_constrained(Instance *inst) { return Sta::sta()->sdc()->isConstrained(inst); } bool net_is_constrained(Net *net) { return Sta::sta()->sdc()->isConstrained(net); } bool clk_thru_tristate_enabled() { return Sta::sta()->clkThruTristateEnabled(); } void set_clk_thru_tristate_enabled(bool enabled) { Sta::sta()->setClkThruTristateEnabled(enabled); } void remove_constraints() { Sta::sta()->removeConstraints(); } PortSeq all_inputs_cmd(bool no_clocks) { Sta *sta = Sta::sta(); sta->ensureLinked(); return sta->sdc()->allInputs(no_clocks); } PortSeq all_outputs_cmd() { Sta *sta = Sta::sta(); sta->ensureLinked(); return sta->sdc()->allOutputs(); } template Vector filter_objects(const char *property, const char *op, const char *pattern, Vector *objects) { Vector filtered_objects; if (objects) { Sta *sta = Sta::sta(); Properties &properties = sta->properties(); bool exact_match = stringEq(op, "=="); bool pattern_match = stringEq(op, "=~"); bool not_match = stringEq(op, "!="); bool not_pattern_match = stringEq(op, "!~"); for (T *object : *objects) { PropertyValue value(properties.getProperty(object, property)); string prop_str = value.to_string(sta->network()); const char *prop = prop_str.c_str(); if (!prop_str.empty() && ((exact_match && stringEq(prop, pattern)) || (not_match && !stringEq(prop, pattern)) || (pattern_match && patternMatch(pattern, prop)) || (not_pattern_match && !patternMatch(pattern, prop)))) filtered_objects.push_back(object); } delete objects; } return filtered_objects; } PortSeq filter_ports(const char *property, const char *op, const char *pattern, PortSeq *ports) { return filter_objects(property, op, pattern, ports); } InstanceSeq filter_insts(const char *property, const char *op, const char *pattern, InstanceSeq *insts) { return filter_objects(property, op, pattern, insts); } PinSeq filter_pins(const char *property, const char *op, const char *pattern, PinSeq *pins) { return filter_objects(property, op, pattern, pins); } ClockSeq filter_clocks(const char *property, const char *op, const char *pattern, ClockSeq *clocks) { return filter_objects(property, op, pattern, clocks); } LibertyCellSeq filter_lib_cells(const char *property, const char *op, const char *pattern, LibertyCellSeq *cells) { return filter_objects(property, op, pattern, cells); } LibertyPortSeq filter_lib_pins(const char *property, const char *op, const char *pattern, LibertyPortSeq *pins) { return filter_objects(property, op, pattern, pins); } LibertyLibrarySeq filter_liberty_libraries(const char *property, const char *op, const char *pattern, LibertyLibrarySeq *libs) { return filter_objects(property, op, pattern, libs); } NetSeq filter_nets(const char *property, const char *op, const char *pattern, NetSeq *nets) { return filter_objects(property, op, pattern, nets); } EdgeSeq filter_timing_arcs(const char *property, const char *op, const char *pattern, EdgeSeq *edges) { return filter_objects(property, op, pattern, edges); } //////////////////////////////////////////////////////////////// StringSeq path_group_names() { StringSeq pg_names; for (auto const& [name, group] : Sta::sta()->sdc()->groupPaths()) pg_names.push_back(name); return pg_names; } //////////////////////////////////////////////////////////////// void set_voltage_global(const MinMax *min_max, float voltage) { Sta::sta()->setVoltage(min_max, voltage); } void set_voltage_net(const Net *net, const MinMax *min_max, float voltage) { Sta::sta()->setVoltage(net, min_max, voltage); } //////////////////////////////////////////////////////////////// PinSet group_path_pins(const char *group_path_name) { Sta *sta = Sta::sta(); Sdc *sdc = sta->sdc(); if (sdc->isGroupPathName(group_path_name)) return sta->findGroupPathPins(group_path_name); else return PinSet(sta->network()); } //////////////////////////////////////////////////////////////// char pin_case_logic_value(const Pin *pin) { Sta *sta = Sta::sta(); Sdc *sdc = sta->sdc(); LogicValue value = LogicValue::unknown; bool exists; sdc->caseLogicValue(pin, value, exists); return logicValueString(value); } char pin_logic_value(const Pin *pin) { Sta *sta = Sta::sta(); Sdc *sdc = sta->sdc(); LogicValue value = LogicValue::unknown; bool exists; sdc->logicValue(pin, value, exists); return logicValueString(value); } //////////////////////////////////////////////////////////////// // // Variables // //////////////////////////////////////////////////////////////// bool propagate_all_clocks() { return Sta::sta()->propagateAllClocks(); } void set_propagate_all_clocks(bool prop) { Sta::sta()->setPropagateAllClocks(prop); } %} // inline //////////////////////////////////////////////////////////////// // // Object Methods // //////////////////////////////////////////////////////////////// %extend Clock { float period() { return self->period(); } FloatSeq *waveform() { return self->waveform(); } float time(RiseFall *rf) { return self->edge(rf)->time(); } bool is_generated() { return self->isGenerated(); } bool waveform_valid() { return self->waveformValid(); } bool is_virtual() { return self->isVirtual(); } bool is_propagated() { return self->isPropagated(); } const PinSet &sources() { return self->pins(); } float slew(const RiseFall *rf, const MinMax *min_max) { return self->slew(rf, min_max); } } %extend ClockEdge { Clock *clock() { return self->clock(); } const RiseFall *transition() { return self->transition(); } float time() { return self->time(); } }