// 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. // //////////////////////////////////////////////////////////////// class Library { private: Library(); ~Library(); }; class LibraryIterator { private: LibraryIterator(); ~LibraryIterator(); }; class Cell { private: Cell(); ~Cell(); }; class CellPortIterator { private: CellPortIterator(); ~CellPortIterator(); }; class Port { private: Port(); ~Port(); }; class PortMemberIterator { private: PortMemberIterator(); ~PortMemberIterator(); }; class Instance { private: Instance(); ~Instance(); }; class Pin { private: Pin(); ~Pin(); }; class Term { private: Term(); ~Term(); }; class InstanceChildIterator { private: InstanceChildIterator(); ~InstanceChildIterator(); }; class InstancePinIterator { private: InstancePinIterator(); ~InstancePinIterator(); }; class InstanceNetIterator { private: InstanceNetIterator(); ~InstanceNetIterator(); }; class LeafInstanceIterator { private: LeafInstanceIterator(); ~LeafInstanceIterator(); }; class Net { private: Net(); ~Net(); }; class NetPinIterator { private: NetPinIterator(); ~NetPinIterator(); }; class NetTermIterator { private: NetTermIterator(); ~NetTermIterator(); }; class NetConnectedPinIterator { private: NetConnectedPinIterator(); ~NetConnectedPinIterator(); }; class PinConnectedPinIterator { private: PinConnectedPinIterator(); ~PinConnectedPinIterator(); }; %inline %{ bool network_is_linked() { return Sta::sta()->network()->isLinked(); } void set_path_divider(char divider) { Network *network = Sta::sta()->network(); network->setPathDivider(divider); } void set_current_instance(Instance *inst) { Sta::sta()->setCurrentInstance(inst); } // Includes top instance. int network_instance_count() { Network *network = Sta::sta()->ensureLinked(); return network->instanceCount(); } int network_pin_count() { Network *network = Sta::sta()->ensureLinked(); return network->pinCount(); } int network_net_count() { Network *network = Sta::sta()->ensureLinked(); return network->netCount(); } int network_leaf_instance_count() { Network *network = Sta::sta()->ensureLinked(); return network->leafInstanceCount(); } int network_leaf_pin_count() { Network *network = Sta::sta()->ensureLinked(); return network->leafPinCount(); } Library * find_library(const char *name) { Network *network = Sta::sta()->ensureLinked(); return network->findLibrary(name); } LibraryIterator * library_iterator() { Network *network = Sta::sta()->ensureLinked(); return network->libraryIterator(); } CellSeq find_cells_matching(const char *pattern, bool regexp, bool nocase) { Network *network = Sta::sta()->ensureLinked(); PatternMatch matcher(pattern, regexp, nocase, Sta::sta()->tclInterp()); CellSeq matches; LibraryIterator *lib_iter = network->libraryIterator(); while (lib_iter->hasNext()) { Library *lib = lib_iter->next(); CellSeq lib_matches = network->findCellsMatching(lib, &matcher); for (Cell *match : lib_matches) matches.push_back(match); } delete lib_iter; return matches; } void set_cmd_namespace_cmd(const char *namespc) { Sta *sta = Sta::sta(); if (stringEq(namespc, "sdc")) sta->setCmdNamespace(CmdNamespace::sdc); else if (stringEq(namespc, "sta")) sta->setCmdNamespace(CmdNamespace::sta); else sta->report()->warn(2120, "unknown namespace"); } bool link_design_cmd(const char *top_cell_name, bool make_black_boxes) { return Sta::sta()->linkDesign(top_cell_name, make_black_boxes); } Instance * top_instance() { Network *network = Sta::sta()->ensureLinked(); return network->topInstance(); } LeafInstanceIterator * leaf_instance_iterator() { Network *network = Sta::sta()->ensureLinked(); return network->leafInstanceIterator(); } const char * port_direction(const Port *port) { return Sta::sta()->ensureLinked()->direction(port)->name(); } const char * pin_direction(const Pin *pin) { return Sta::sta()->ensureLinked()->direction(pin)->name(); } PortSeq find_ports_matching(const char *pattern, bool regexp, bool nocase) { Sta *sta = Sta::sta(); Network *network = sta->ensureLinked(); PatternMatch matcher(pattern, regexp, nocase, sta->tclInterp()); Cell *top_cell = network->cell(network->topInstance()); PortSeq matches1 = network->findPortsMatching(top_cell, &matcher); // Expand bus/bundle ports. PortSeq matches; for (const Port *port : matches1) { if (network->isBus(port) || network->isBundle(port)) { PortMemberIterator *member_iter = network->memberIterator(port); while (member_iter->hasNext()) { Port *member = member_iter->next(); matches.push_back(member); } delete member_iter; } else matches.push_back(port); } return matches; } PinSeq find_port_pins_matching(const char *pattern, bool regexp, bool nocase) { Sta *sta = Sta::sta(); Network *network = sta->ensureLinked(); PatternMatch matcher(pattern, regexp, nocase, sta->tclInterp()); Instance *top_inst = network->topInstance(); Cell *top_cell = network->cell(top_inst); PortSeq ports = network->findPortsMatching(top_cell, &matcher); PinSeq pins; for (const Port *port : ports) { if (network->isBus(port) || network->isBundle(port)) { PortMemberIterator *member_iter = network->memberIterator(port); while (member_iter->hasNext()) { Port *member = member_iter->next(); Pin *pin = network->findPin(top_inst, member); if (pin) pins.push_back(pin); } delete member_iter; } else { Pin *pin = network->findPin(top_inst, port); if (pin) pins.push_back(pin); } } return pins; } Pin * find_pin(const char *path_name) { Network *network = Sta::sta()->ensureLinked(); return network->findPin(path_name); } Pin * get_port_pin(const Port *port) { Network *network = Sta::sta()->ensureLinked(); return network->findPin(network->topInstance(), port); } PinSeq find_pins_matching(const char *pattern, bool regexp, bool nocase) { Sta *sta = Sta::sta(); Network *network = sta->ensureLinked(); PatternMatch matcher(pattern, regexp, nocase, sta->tclInterp()); Instance *current_instance = sta->currentInstance(); PinSeq matches = network->findPinsMatching(current_instance, &matcher); return matches; } PinSeq find_pins_hier_matching(const char *pattern, bool regexp, bool nocase) { Sta *sta = Sta::sta(); Network *network = sta->ensureLinked(); Instance *current_instance = sta->currentInstance(); PatternMatch matcher(pattern, regexp, nocase, sta->tclInterp()); PinSeq matches = network->findPinsHierMatching(current_instance, &matcher); return matches; } Instance * find_instance(char *path_name) { return Sta::sta()->ensureLinked()->findInstance(path_name); } InstanceSeq network_leaf_instances() { return Sta::sta()->ensureLinked()->leafInstances(); } InstanceSeq find_instances_matching(const char *pattern, bool regexp, bool nocase) { Sta *sta = Sta::sta(); Network *network = sta->ensureLinked(); Instance *current_instance = sta->currentInstance(); PatternMatch matcher(pattern, regexp, nocase, sta->tclInterp()); InstanceSeq matches = network->findInstancesMatching(current_instance, &matcher); return matches; } InstanceSeq find_instances_hier_matching(const char *pattern, bool regexp, bool nocase) { Sta *sta = Sta::sta(); Network *network = sta->ensureLinked(); Instance *current_instance = sta->currentInstance(); PatternMatch matcher(pattern, regexp, nocase, sta->tclInterp()); InstanceSeq matches = network->findInstancesHierMatching(current_instance, &matcher); return matches; } InstanceSet find_register_instances(ClockSet *clks, const RiseFallBoth *clk_tr, bool edge_triggered, bool latches) { Sta *sta = Sta::sta(); InstanceSet insts = sta->findRegisterInstances(clks, clk_tr, edge_triggered, latches); delete clks; return insts; } PinSet find_register_data_pins(ClockSet *clks, const RiseFallBoth *clk_tr, bool edge_triggered, bool latches) { Sta *sta = Sta::sta(); PinSet pins = sta->findRegisterDataPins(clks, clk_tr, edge_triggered, latches); delete clks; return pins; } PinSet find_register_clk_pins(ClockSet *clks, const RiseFallBoth *clk_tr, bool edge_triggered, bool latches) { Sta *sta = Sta::sta(); PinSet pins = sta->findRegisterClkPins(clks, clk_tr, edge_triggered, latches); delete clks; return pins; } PinSet find_register_async_pins(ClockSet *clks, const RiseFallBoth *clk_tr, bool edge_triggered, bool latches) { Sta *sta = Sta::sta(); PinSet pins = sta->findRegisterAsyncPins(clks, clk_tr, edge_triggered, latches); delete clks; return pins; } PinSet find_register_output_pins(ClockSet *clks, const RiseFallBoth *clk_tr, bool edge_triggered, bool latches) { Sta *sta = Sta::sta(); PinSet pins = sta->findRegisterOutputPins(clks, clk_tr, edge_triggered, latches); delete clks; return pins; } Net * find_net(char *path_name) { return Sta::sta()->ensureLinked()->findNet(path_name); } NetSeq find_nets_matching(const char *pattern, bool regexp, bool nocase) { Sta *sta = Sta::sta(); Network *network = sta->ensureLinked(); Instance *current_instance = sta->currentInstance(); PatternMatch matcher(pattern, regexp, nocase, sta->tclInterp()); NetSeq matches = network->findNetsMatching(current_instance, &matcher); return matches; } NetSeq find_nets_hier_matching(const char *pattern, bool regexp, bool nocase) { Sta *sta = Sta::sta(); Network *network = sta->ensureLinked(); Instance *current_instance = sta->currentInstance(); PatternMatch matcher(pattern, regexp, nocase, sta->tclInterp()); NetSeq matches = network->findNetsHierMatching(current_instance, &matcher); return matches; } PinSet net_driver_pins(Net *net) { Network *network = Sta::sta()->ensureLinked(); PinSet pins(network); NetConnectedPinIterator *pin_iter = network->connectedPinIterator(net); while (pin_iter->hasNext()) { const Pin *pin = pin_iter->next(); if (network->isDriver(pin)) pins.insert(pin); } delete pin_iter; return pins; } PinSet net_load_pins(Net *net) { Network *network = Sta::sta()->ensureLinked(); PinSet pins(network); NetConnectedPinIterator *pin_iter = network->connectedPinIterator(net); while (pin_iter->hasNext()) { const Pin *pin = pin_iter->next(); if (network->isLoad(pin)) pins.insert(pin); } delete pin_iter; return pins; } const char * pin_location(const Pin *pin) { Network *network = Sta::sta()->ensureLinked(); double x, y; bool exists; network->location(pin, x, y, exists); // return x/y as tcl list if (exists) return sta::stringPrintTmp("%f %f", x, y); else return ""; } const char * port_location(const Port *port) { Network *network = Sta::sta()->ensureLinked(); const Pin *pin = network->findPin(network->topInstance(), port); return pin_location(pin); } %} // inline //////////////////////////////////////////////////////////////// // // Object Methods // //////////////////////////////////////////////////////////////// %extend Library { const char *name() { return Sta::sta()->ensureLinked()->name(self); } Cell * find_cell(const char *name) { return Sta::sta()->ensureLinked()->findCell(self, name); } CellSeq find_cells_matching(const char *pattern, bool regexp, bool nocase) { Sta *sta = Sta::sta(); Network *network = sta->ensureLinked(); PatternMatch matcher(pattern, regexp, nocase, sta->tclInterp()); CellSeq matches = network->findCellsMatching(self, &matcher); return matches; } } // Library methods %extend LibraryIterator { bool has_next() { return self->hasNext(); } Library *next() { return self->next(); } void finish() { delete self; } } // LibraryIterator methods %extend Cell { const char *name() { return Sta::sta()->cmdNetwork()->name(self); } Library *library() { return Sta::sta()->cmdNetwork()->library(self); } LibertyCell *liberty_cell() { return Sta::sta()->cmdNetwork()->libertyCell(self); } bool is_leaf() { return Sta::sta()->cmdNetwork()->isLeaf(self); } CellPortIterator * port_iterator() { return Sta::sta()->cmdNetwork()->portIterator(self); } string get_attribute(const char *key) { return Sta::sta()->cmdNetwork()->getAttribute(self, key); } Port * find_port(const char *name) { return Sta::sta()->ensureLinked()->findPort(self, name); } PortSeq find_ports_matching(const char *pattern, bool regexp, bool nocase) { Sta *sta = Sta::sta(); Network *network = sta->ensureLinked(); PatternMatch matcher(pattern, regexp, nocase, sta->tclInterp()); return network->findPortsMatching(self, &matcher); } } // Cell methods %extend CellPortIterator { bool has_next() { return self->hasNext(); } Port *next() { return self->next(); } void finish() { delete self; } } // CellPortIterator methods %extend Port { const char *bus_name() { return Sta::sta()->ensureLinked()->busName(self); } Cell *cell() { return Sta::sta()->ensureLinked()->cell(self); } LibertyPort *liberty_port() { return Sta::sta()->ensureLibLinked()->libertyPort(self); } bool is_bus() { return Sta::sta()->ensureLinked()->isBus(self); } PortMemberIterator * member_iterator() { return Sta::sta()->ensureLinked()->memberIterator(self); } } // Port methods %extend PortMemberIterator { bool has_next() { return self->hasNext(); } Port *next() { return self->next(); } void finish() { delete self; } } // PortMemberIterator methods %extend Instance { Instance *parent() { return Sta::sta()->ensureLinked()->parent(self); } Cell *cell() { return Sta::sta()->ensureLinked()->cell(self); } LibertyCell *liberty_cell() { return Sta::sta()->ensureLibLinked()->libertyCell(self); } bool is_leaf() { return Sta::sta()->ensureLinked()->isLeaf(self); } InstanceChildIterator * child_iterator() { return Sta::sta()->ensureLinked()->childIterator(self); } InstancePinIterator * pin_iterator() { return Sta::sta()->ensureLinked()->pinIterator(self); } InstanceNetIterator * net_iterator() { return Sta::sta()->ensureLinked()->netIterator(self); } Pin * find_pin(const char *name) { return Sta::sta()->ensureLinked()->findPin(self, name); } string get_attribute(const char *key) { return Sta::sta()->ensureLinked()->getAttribute(self, key); } } // Instance methods %extend InstanceChildIterator { bool has_next() { return self->hasNext(); } Instance *next() { return self->next(); } void finish() { delete self; } } // InstanceChildIterator methods %extend LeafInstanceIterator { bool has_next() { return self->hasNext(); } Instance *next() { return self->next(); } void finish() { delete self; } } // LeafInstanceIterator methods %extend InstancePinIterator { bool has_next() { return self->hasNext(); } Pin *next() { return self->next(); } void finish() { delete self; } } // InstancePinIterator methods %extend InstanceNetIterator { bool has_next() { return self->hasNext(); } Net *next() { return self->next(); } void finish() { delete self; } } // InstanceNetIterator methods %extend Pin { const char *port_name() { return Sta::sta()->ensureLinked()->portName(self); } Instance *instance() { return Sta::sta()->ensureLinked()->instance(self); } Net *net() { return Sta::sta()->ensureLinked()->net(self); } Port *port() { return Sta::sta()->ensureLinked()->port(self); } Term *term() { return Sta::sta()->ensureLinked()->term(self); } LibertyPort *liberty_port() { return Sta::sta()->ensureLibLinked()->libertyPort(self); } bool is_driver() { return Sta::sta()->ensureLinked()->isDriver(self); } bool is_load() { return Sta::sta()->ensureLinked()->isLoad(self); } bool is_leaf() { return Sta::sta()->ensureLinked()->isLeaf(self); } bool is_hierarchical() { return Sta::sta()->ensureLinked()->isHierarchical(self); } bool is_top_level_port() { return Sta::sta()->ensureLinked()->isTopLevelPort(self); } PinConnectedPinIterator *connected_pin_iterator() { return Sta::sta()->ensureLinked()->connectedPinIterator(self); } Vertex ** vertices() { Vertex *vertex, *vertex_bidirect_drvr; static Vertex *vertices[3]; Graph *graph = Sta::sta()->ensureGraph(); graph->pinVertices(self, vertex, vertex_bidirect_drvr); vertices[0] = vertex; vertices[1] = vertex_bidirect_drvr; vertices[2] = nullptr; return vertices; } } // Pin methods %extend PinConnectedPinIterator { bool has_next() { return self->hasNext(); } const Pin *next() { return self->next(); } void finish() { delete self; } } // PinConnectedPinIterator methods %extend Term { Net *net() { return Sta::sta()->ensureLinked()->net(self); } Pin *pin() { return Sta::sta()->ensureLinked()->pin(self); } } // Term methods %extend Net { Instance *instance() { return Sta::sta()->ensureLinked()->instance(self); } const Net *highest_connected_net() { return Sta::sta()->ensureLinked()->highestConnectedNet(self); } NetPinIterator *pin_iterator() { return Sta::sta()->ensureLinked()->pinIterator(self);} NetTermIterator *term_iterator() {return Sta::sta()->ensureLinked()->termIterator(self);} NetConnectedPinIterator *connected_pin_iterator() { return Sta::sta()->ensureLinked()->connectedPinIterator(self); } bool is_power() { return Sta::sta()->ensureLinked()->isPower(self);} bool is_ground() { return Sta::sta()->ensureLinked()->isGround(self);} float capacitance(Corner *corner, const MinMax *min_max) { Sta *sta = Sta::sta(); sta->ensureLibLinked(); float pin_cap, wire_cap; sta->connectedCap(self, corner, min_max, pin_cap, wire_cap); return pin_cap + wire_cap; } float pin_capacitance(Corner *corner, const MinMax *min_max) { Sta *sta = Sta::sta(); sta->ensureLibLinked(); float pin_cap, wire_cap; sta->connectedCap(self, corner, min_max, pin_cap, wire_cap); return pin_cap; } float wire_capacitance(Corner *corner, const MinMax *min_max) { Sta *sta = Sta::sta(); sta->ensureLibLinked(); float pin_cap, wire_cap; sta->connectedCap(self, corner, min_max, pin_cap, wire_cap); return wire_cap; } // get_ports -of_objects net PortSeq ports() { Network *network = Sta::sta()->ensureLinked(); PortSeq ports; if (network->isTopInstance(network->instance(self))) { NetTermIterator *term_iter = network->termIterator(self); while (term_iter->hasNext()) { Term *term = term_iter->next(); Port *port = network->port(network->pin(term)); ports.push_back(port); } delete term_iter; } return ports; } } // Net methods %extend NetPinIterator { bool has_next() { return self->hasNext(); } const Pin *next() { return self->next(); } void finish() { delete self; } } // NetPinIterator methods %extend NetTermIterator { bool has_next() { return self->hasNext(); } const Term *next() { return self->next(); } void finish() { delete self; } } // NetTermIterator methods %extend NetConnectedPinIterator { bool has_next() { return self->hasNext(); } const Pin *next() { return self->next(); } void finish() { delete self; } } // NetConnectedPinIterator methods