OpenSTA/network/Network.cc

2212 lines
50 KiB
C++

// 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/>.
#include "Network.hh"
#include "StringUtil.hh"
#include "PatternMatch.hh"
#include "Liberty.hh"
#include "PortDirection.hh"
#include "Corner.hh"
#include "ParseBus.hh"
namespace sta {
Network::Network() :
default_liberty_(nullptr),
divider_('/'),
escape_('\\')
{
}
Network::~Network()
{
net_drvr_pin_map_.deleteContents();
}
void
Network::clear()
{
default_liberty_ = nullptr;
clearNetDrvrPinMap();
}
bool
Network::isLinked() const
{
return topInstance() != nullptr;
}
LibertyLibrary *
Network::libertyLibrary(const Cell *cell) const
{
return libertyCell(cell)->libertyLibrary();
}
PortSeq
Network::findPortsMatching(const Cell *cell,
const PatternMatch *pattern) const
{
PortSeq matches;
bool is_bus, is_range, subscript_wild;
string bus_name;
int from, to;
parseBusName(pattern->pattern(), '[', ']', '\\',
is_bus, is_range, bus_name, from, to, subscript_wild);
if (is_bus) {
PatternMatch bus_pattern(bus_name.c_str(), pattern);
CellPortIterator *port_iter = portIterator(cell);
while (port_iter->hasNext()) {
Port *port = port_iter->next();
if (isBus(port)
&& bus_pattern.match(name(port))) {
if (is_range) {
// bus[8:0]
if (from > to)
std::swap(from, to);
for (int bit = from; bit <= to; bit++) {
Port *port_bit = findBusBit(port, bit);
matches.push_back(port_bit);
}
}
else {
if (subscript_wild) {
PortMemberIterator *member_iter = memberIterator(port);
while (member_iter->hasNext()) {
Port *port_bit = member_iter->next();
matches.push_back(port_bit);
}
delete member_iter;
}
else {
// bus[0]
Port *port_bit = findBusBit(port, from);
if (port_bit != nullptr)
matches.push_back(port_bit);
}
}
}
}
delete port_iter;
}
else {
CellPortIterator *port_iter = portIterator(cell);
while (port_iter->hasNext()) {
Port *port = port_iter->next();
if (pattern->match(name(port)))
matches.push_back(port);
}
delete port_iter;
}
return matches;
}
LibertyLibrary *
Network::libertyLibrary(const Instance *instance) const
{
return libertyCell(instance)->libertyLibrary();
}
void
Network::readLibertyAfter(LibertyLibrary *)
{
}
LibertyCell *
Network::findLibertyCell(const char *name) const
{
LibertyLibraryIterator *iter = libertyLibraryIterator();
while (iter->hasNext()) {
LibertyLibrary *lib = iter->next();
LibertyCell *cell = lib->findLibertyCell(name);
if (cell) {
delete iter;
return cell;
}
}
delete iter;
return nullptr;
}
LibertyLibrary *
Network::defaultLibertyLibrary() const
{
return default_liberty_;
}
void
Network::setDefaultLibertyLibrary(LibertyLibrary *library)
{
default_liberty_ = library;
}
void
Network::checkLibertyCorners()
{
if (corners_->count() > 1) {
LibertyLibraryIterator *lib_iter = libertyLibraryIterator();
LibertyCellSet cells;
while (lib_iter->hasNext()) {
LibertyLibrary *lib = lib_iter->next();
LibertyCellIterator cell_iter(lib);
while (cell_iter.hasNext()) {
LibertyCell *cell = cell_iter.next();
LibertyCell *link_cell = findLibertyCell(cell->name());
cells.insert(link_cell);
}
}
delete lib_iter;
for (LibertyCell *cell : cells)
LibertyLibrary::checkCorners(cell, corners_, report_);
}
}
void
Network::checkNetworkLibertyCorners()
{
if (corners_->count() > 1) {
LibertyCellSet network_cells;
LeafInstanceIterator *leaf_iter = network_->leafInstanceIterator();
while (leaf_iter->hasNext()) {
const Instance *inst = leaf_iter->next();
LibertyCell *cell = libertyCell(inst);
if (cell)
network_cells.insert(cell);
}
delete leaf_iter;
for (LibertyCell *cell : network_cells)
LibertyLibrary::checkCorners(cell, corners_, report_);
}
}
// Only used by Sta::setMinLibrary so linear search is acceptable.
LibertyLibrary *
Network::findLibertyFilename(const char *filename)
{
LibertyLibraryIterator *lib_iter = libertyLibraryIterator();
while (lib_iter->hasNext()) {
LibertyLibrary *lib = lib_iter->next();
if (stringEq(lib->filename(), filename)) {
delete lib_iter;
return lib;
}
}
delete lib_iter;
return nullptr;
}
LibertyCell *
Network::libertyCell(const Instance *instance) const
{
return libertyCell(cell(instance));
}
LibertyPort *
Network::libertyPort(const Pin *pin) const
{
Port *port = this->port(pin);
if (port)
return libertyPort(port);
else
return nullptr;
}
bool
Network::busIndexInRange(const Port *port,
int index)
{
int from_index = fromIndex(port);
int to_index = toIndex(port);
return (from_index <= to_index
&& index <= to_index
&& index >= from_index)
|| (from_index > to_index
&& index >= to_index
&& index <= from_index);
}
bool
Network::hasMembers(const Port *port) const
{
return isBus(port) || isBundle(port);
}
const char *
Network::pathName(const Instance *instance) const
{
InstanceSeq inst_path;
path(instance, inst_path);
size_t name_length = 0;
InstanceSeq::Iterator path_iter1(inst_path);
while (path_iter1.hasNext()) {
const Instance *inst = path_iter1.next();
name_length += strlen(name(inst)) + 1;
}
char *path_name = makeTmpString(name_length + 1);
char *path_ptr = path_name;
// Top instance has null string name, so terminate the string here.
*path_name = '\0';
while (inst_path.size()) {
const Instance *inst = inst_path.back();
const char *inst_name = name(inst);
strcpy(path_ptr, inst_name);
path_ptr += strlen(inst_name);
inst_path.pop_back();
if (inst_path.size())
*path_ptr++ = pathDivider();
*path_ptr = '\0';
}
return path_name;
}
bool
Network::pathNameLess(const Instance *inst1,
const Instance *inst2) const
{
return pathNameCmp(inst1, inst2) < 0;
}
int
Network::pathNameCmp(const Instance *inst1,
const Instance *inst2) const
{
if (inst1 == nullptr && inst2)
return -1;
else if (inst1 && inst2 == nullptr)
return 1;
else if (inst1 == inst2)
return 0;
else {
InstanceSeq path1;
InstanceSeq path2;
path(inst1, path1);
path(inst2, path2);
while (!path1.empty() && !path2.empty()) {
const Instance *inst1 = path1.back();
const Instance *inst2 = path2.back();
int cmp = strcmp(name(inst1), name(inst2));
if (cmp != 0)
return cmp;
path1.pop_back();
path2.pop_back();
}
if (path1.empty() && !path2.empty())
return -1;
else if (path1.empty() && path2.empty())
return 0;
else
return 1;
}
}
void
Network::path(const Instance *inst,
// Return value.
InstanceSeq &path) const
{
while (!isTopInstance(inst)) {
path.push_back(inst);
inst = parent(inst);
}
}
bool
Network::isTopInstance(const Instance *inst) const
{
return inst == topInstance();
}
bool
Network::isInside(const Instance *inst,
const Instance *hier_inst) const
{
while (inst) {
if (inst == hier_inst)
return true;
inst = parent(inst);
}
return false;
}
bool
Network::isHierarchical(const Instance *instance) const
{
return !isLeaf(instance);
}
////////////////////////////////////////////////////////////////
const char *
Network::name(const Pin *pin) const
{
return pathName(pin);
}
const char *
Network::portName(const Pin *pin) const
{
return name(port(pin));
}
const char *
Network::pathName(const Pin *pin) const
{
const Instance *inst = instance(pin);
if (inst && inst != topInstance()) {
const char *inst_name = pathName(inst);
size_t inst_name_length = strlen(inst_name);
const char *port_name = portName(pin);
size_t port_name_length = strlen(port_name);
size_t path_name_length = inst_name_length + port_name_length + 2;
char *path_name = makeTmpString(path_name_length);
char *path_ptr = path_name;
strcpy(path_ptr, inst_name);
path_ptr += inst_name_length;
*path_ptr++ = pathDivider();
strcpy(path_ptr, port_name);
return path_name;
}
else
return portName(pin);
}
bool
Network::pathNameLess(const Pin *pin1,
const Pin *pin2) const
{
return pathNameCmp(pin1, pin2) < 0;
}
int
Network::pathNameCmp(const Pin *pin1,
const Pin *pin2) const
{
int inst_cmp = pathNameCmp(instance(pin1), instance(pin2));
if (inst_cmp == 0)
return strcmp(portName(pin1), portName(pin2));
else
return inst_cmp;
}
bool
Network::isInside(const Net *net,
const Instance *hier_inst) const
{
return isInside(instance(net), hier_inst);
}
bool
Network::isLeaf(const Pin *pin) const
{
return isLeaf(instance(pin));
}
bool
Network::isHierarchical(const Pin *pin) const
{
return (!isLeaf(pin) && !isTopLevelPort(pin));
}
bool
Network::isTopLevelPort(const Pin *pin) const
{
return (parent(instance(pin)) == nullptr);
}
bool
Network::isInside(const Pin *pin,
const Pin *hier_pin) const
{
return isInside(pin, instance(hier_pin));
}
bool
Network::isInside(const Pin *pin,
const Instance *hier_inst) const
{
return isInside(instance(pin), hier_inst);
}
bool
Network::pinLess(const Pin *pin1,
const Pin *pin2) const
{
return pathNameLess(pin1, pin2);
}
////////////////////////////////////////////////////////////////
const char *
Network::pathName(const Net *net) const
{
const Instance *inst = instance(net);
if (inst && inst != topInstance()) {
const char *inst_name = pathName(inst);
size_t inst_name_length = strlen(inst_name);
const char *net_name = name(net);
size_t net_name_length = strlen(net_name);
size_t path_name_length = inst_name_length + net_name_length + 2;
char *path_name = makeTmpString(path_name_length);
char *path_ptr = path_name;
strcpy(path_ptr, inst_name);
path_ptr += inst_name_length;
*path_ptr++ = pathDivider();
strcpy(path_ptr, net_name);
return path_name;
}
else
return name(net);
}
bool
Network::pathNameLess(const Net *net1,
const Net *net2) const
{
return pathNameCmp(net1, net2) < 0;
}
int
Network::pathNameCmp(const Net *net1,
const Net *net2) const
{
int inst_cmp = pathNameCmp(instance(net1), instance(net2));
if (inst_cmp == 0)
return strcmp(name(net1), name(net2));
else
return inst_cmp;
}
Net *
Network::highestNetAbove(Net *net) const
{
Net *highest_net = net;
// Search up from net terminals.
NetTermIterator *term_iter = termIterator(net);
while (term_iter->hasNext()) {
Term *term = term_iter->next();
Pin *above_pin = pin(term);
if (above_pin) {
Net *above_net = this->net(above_pin);
if (above_net) {
highest_net = highestNetAbove(above_net);
break;
}
}
}
delete term_iter;
return highest_net;
}
const Net *
Network::highestConnectedNet(Net *net) const
{
NetSet nets(this);
connectedNets(net, &nets);
const Net *highest_net = net;
int highest_level = hierarchyLevel(net);
NetSet::Iterator net_iter(nets);
while (net_iter.hasNext()) {
const Net *net1 = net_iter.next();
int level = hierarchyLevel(net1);
if (level < highest_level
|| (level == highest_level
&& stringLess(pathName(net1), pathName(highest_net)))) {
highest_net = net1;
highest_level = level;
}
}
return highest_net;
}
void
Network::connectedNets(Net *net,
NetSet *nets) const
{
if (!nets->hasKey(net)) {
nets->insert(net);
// Search up from net terminals.
NetTermIterator *term_iter = termIterator(net);
while (term_iter->hasNext()) {
Term *term = term_iter->next();
Pin *above_pin = pin(term);
if (above_pin) {
Net *above_net = this->net(above_pin);
if (above_net)
connectedNets(above_net, nets);
}
}
delete term_iter;
// Search down from net pins.
NetPinIterator *pin_iter = pinIterator(net);
while (pin_iter->hasNext()) {
const Pin *pin1 = pin_iter->next();
Term *below_term = term(pin1);
if (below_term) {
Net *below_net = this->net(below_term);
if (below_net)
connectedNets(below_net, nets);
}
}
delete pin_iter;
}
}
void
Network::connectedNets(const Pin *pin,
NetSet *nets) const
{
Net *net = this->net(pin);
if (net)
connectedNets(net, nets);
else {
Term *term = this->term(pin);
if (term) {
Net *below_net = this->net(term);
if (below_net)
connectedNets(below_net, nets);
}
}
}
int
Network::hierarchyLevel(const Net *net) const
{
NetTermIterator *term_iter = network_->termIterator(net);
while (term_iter->hasNext()) {
Term *term = term_iter->next();
Pin *pin = network_->pin(term);
if (pin) {
Net *above_net = network_->net(pin);
if (above_net) {
delete term_iter;
return hierarchyLevel(above_net) + 1;
}
}
}
delete term_iter;
return 0;
}
bool
Network::isDriver(const Pin *pin) const
{
PortDirection *dir = direction(pin);
const Instance *inst = instance(pin);
return (isLeaf(inst) && dir->isAnyOutput())
// isTopLevelPort(pin)
|| (isTopInstance(inst) && dir->isAnyInput());
}
bool
Network::isLoad(const Pin *pin) const
{
PortDirection *dir = direction(pin);
const Instance *inst = instance(pin);
return (isLeaf(inst) && dir->isAnyInput())
// isTopLevelPort(pin)
|| (isTopInstance(inst) && dir->isAnyOutput())
// Black box unknown ports are treated as loads.
|| dir->isUnknown();
}
bool
Network::isRegClkPin(const Pin *pin) const
{
const LibertyPort *port = libertyPort(pin);
return port && port->isRegClk();
}
bool
Network::isCheckClk(const Pin *pin) const
{
const LibertyPort *port = libertyPort(pin);
return port && port->isCheckClk();
}
bool
Network::isLatchData(const Pin *pin) const
{
LibertyPort *port = libertyPort(pin);
if (port)
return port->libertyCell()->isLatchData(port);
else
return false;
}
////////////////////////////////////////////////////////////////
const char *
Network::name(const Term *term) const
{
return name(pin(term));
}
const char *
Network::pathName(const Term *term) const
{
return pathName(pin(term));
}
const char *
Network::portName(const Term *term) const
{
return portName(pin(term));
}
////////////////////////////////////////////////////////////////
const char *
Network::cellName(const Instance *inst) const
{
return name(cell(inst));
}
Instance *
Network::findInstance(const char *path_name) const
{
return findInstanceRelative(topInstance(), path_name);
}
Instance *
Network::findInstanceRelative(const Instance *inst,
const char *path_name) const
{
char *first, *tail;
pathNameFirst(path_name, first, tail);
if (first) {
Instance *inst1 = findChild(inst, first);
stringDelete(first);
while (inst1 && tail) {
char *next_tail;
pathNameFirst(tail, first, next_tail);
if (first) {
inst1 = findChild(inst1, first);
stringDelete(first);
}
else
inst1 = findChild(inst1, tail);
stringDelete(tail);
tail = next_tail;
}
stringDelete(tail);
return inst1;
}
else
return findChild(inst, path_name);
}
InstanceSeq
Network::findInstancesMatching(const Instance *context,
const PatternMatch *pattern) const
{
InstanceSeq matches;
if (pattern->hasWildcards()) {
size_t context_name_length = 0;
if (context != topInstance())
// Add one for the trailing divider.
context_name_length = strlen(pathName(context)) + 1;
findInstancesMatching1(context, context_name_length, pattern, matches);
}
else {
Instance *inst = findInstanceRelative(context, pattern->pattern());
if (inst)
matches.push_back(inst);
}
return matches;
}
void
Network::findInstancesMatching1(const Instance *context,
size_t context_name_length,
const PatternMatch *pattern,
InstanceSeq &matches) const
{
InstanceChildIterator *child_iter = childIterator(context);
while (child_iter->hasNext()) {
Instance *child = child_iter->next();
const char *child_name = pathName(child);
// Remove context prefix from the name.
const char *child_context_name = &child_name[context_name_length];
if (pattern->match(child_context_name))
matches.push_back(child);
if (!isLeaf(child))
findInstancesMatching1(child, context_name_length, pattern, matches);
}
delete child_iter;
}
InstanceSeq
Network::findInstancesHierMatching(const Instance *instance,
const PatternMatch *pattern) const
{
InstanceSeq matches;
findInstancesHierMatching1(instance, pattern, matches);
return matches;
}
void
Network::findInstancesHierMatching1(const Instance *instance,
const PatternMatch *pattern,
InstanceSeq &matches) const
{
InstanceChildIterator *child_iter = childIterator(instance);
while (child_iter->hasNext()) {
Instance *child = child_iter->next();
if (pattern->match(name(child)))
matches.push_back(child);
if (!isLeaf(child))
findInstancesHierMatching1(child, pattern, matches);
}
delete child_iter;
}
void
Network::findChildrenMatching(const Instance *parent,
const PatternMatch *pattern,
InstanceSeq &matches) const
{
if (pattern->hasWildcards()) {
InstanceChildIterator *child_iter = childIterator(parent);
while (child_iter->hasNext()) {
Instance *child = child_iter->next();
if (pattern->match(name(child)))
matches.push_back(child);
}
delete child_iter;
}
else {
Instance *child = findChild(parent, pattern->pattern());
if (child)
matches.push_back(child);
}
}
Pin *
Network::findPin(const char *path_name) const
{
return findPinRelative(topInstance(), path_name);
}
Pin *
Network::findPinRelative(const Instance *inst,
const char *path_name) const
{
char *inst_path, *port_name;
pathNameLast(path_name, inst_path, port_name);
if (inst_path) {
Instance *pin_inst = findInstanceRelative(inst, inst_path);
if (pin_inst) {
Pin *pin = findPin(pin_inst, port_name);
stringDelete(inst_path);
stringDelete(port_name);
return pin;
}
stringDelete(inst_path);
stringDelete(port_name);
return nullptr;
}
else
// Top level pin.
return findPin(inst, path_name);
}
Pin *
Network::findPinLinear(const Instance *instance,
const char *port_name) const
{
InstancePinIterator *pin_iter = pinIterator(instance);
while (pin_iter->hasNext()) {
Pin *pin = pin_iter->next();
if (stringEq(port_name, portName(pin))) {
delete pin_iter;
return pin;
}
}
delete pin_iter;
return nullptr;
}
Pin *
Network::findPin(const Instance *instance,
const Port *port) const
{
return findPin(instance, name(port));
}
Pin *
Network::findPin(const Instance *instance,
const LibertyPort *port) const
{
return findPin(instance, port->name());
}
Net *
Network::findNet(const char *path_name) const
{
return findNetRelative(topInstance(), path_name);
}
Net *
Network::findNetRelative(const Instance *inst,
const char *path_name) const
{
char *inst_path, *net_name;
pathNameLast(path_name, inst_path, net_name);
if (inst_path) {
Instance *net_inst = findInstanceRelative(inst, inst_path);
if (net_inst) {
Net *net = findNet(net_inst, net_name);
stringDelete(inst_path);
stringDelete(net_name);
return net;
}
stringDelete(inst_path);
stringDelete(net_name);
return nullptr;
}
else
// Top level net.
return findNet(inst, path_name);
}
Net *
Network::findNetLinear(const Instance *instance,
const char *net_name) const
{
InstanceNetIterator *net_iter = netIterator(instance);
while (net_iter->hasNext()) {
Net *net = net_iter->next();
if (stringEq(name(net), net_name)) {
delete net_iter;
return net;
}
}
delete net_iter;
return nullptr;
}
NetSeq
Network::findNetsMatching(const Instance *context,
const PatternMatch *pattern) const
{
NetSeq matches;
findNetsMatching(context, pattern, matches);
return matches;
}
void
Network::findNetsMatching(const Instance *context,
const PatternMatch *pattern,
NetSeq &matches) const
{
if (pattern->hasWildcards()) {
char *inst_path, *net_name;
pathNameLast(pattern->pattern(), inst_path, net_name);
if (inst_path) {
PatternMatch inst_pattern(inst_path, pattern);
PatternMatch net_pattern(net_name, pattern);
InstanceSeq insts = findInstancesMatching(context, &inst_pattern);
InstanceSeq::Iterator inst_iter(insts);
while (inst_iter.hasNext()) {
const Instance *inst = inst_iter.next();
findNetsMatching(inst, &net_pattern, matches);
}
stringDelete(inst_path);
stringDelete(net_name);
}
else
// Top level net.
findInstNetsMatching(context, pattern, matches);
}
else {
Net *net = findNet(pattern->pattern());
if (net)
matches.push_back(net);
}
}
NetSeq
Network::findNetsHierMatching(const Instance *instance,
const PatternMatch *pattern) const
{
NetSeq matches;
findNetsHierMatching(instance, pattern, matches);
return matches;
}
void
Network::findNetsHierMatching(const Instance *instance,
const PatternMatch *pattern,
NetSeq &matches) const
{
findInstNetsMatching(instance, pattern, matches);
InstanceChildIterator *child_iter = childIterator(instance);
while (child_iter->hasNext()) {
Instance *child = child_iter->next();
findNetsHierMatching(child, pattern, matches);
}
delete child_iter;
}
NetSeq
Network::findNetsMatchingLinear(const Instance *instance,
const PatternMatch *pattern) const
{
NetSeq matches;
InstanceNetIterator *net_iter = netIterator(instance);
while (net_iter->hasNext()) {
Net *net = net_iter->next();
if (pattern->match(name(net)))
matches.push_back(net);
}
delete net_iter;
return matches;
}
PinSeq
Network::findPinsMatching(const Instance *instance,
const PatternMatch *pattern) const
{
PinSeq matches;
if (pattern->hasWildcards()) {
char *inst_path, *port_name;
pathNameLast(pattern->pattern(), inst_path, port_name);
if (inst_path) {
PatternMatch inst_pattern(inst_path, pattern);
PatternMatch port_pattern(port_name, pattern);
InstanceSeq insts = findInstancesMatching(instance, &inst_pattern);
InstanceSeq::Iterator inst_iter(insts);
while (inst_iter.hasNext()) {
const Instance *inst = inst_iter.next();
findInstPinsMatching(inst, &port_pattern, matches);
}
stringDelete(inst_path);
stringDelete(port_name);
}
else
// Top level pin.
findInstPinsMatching(instance, pattern, matches);
}
else {
Pin *pin = findPin(pattern->pattern());
if (pin)
matches.push_back(pin);
}
return matches;
}
PinSeq
Network::findPinsHierMatching(const Instance *instance,
const PatternMatch *pattern) const
{
PinSeq matches;
findPinsHierMatching(instance, pattern, matches);
return matches;
}
void
Network::findPinsHierMatching(const Instance *instance,
const PatternMatch *pattern,
// Return value.
PinSeq &matches) const
{
InstanceChildIterator *child_iter = childIterator(instance);
while (child_iter->hasNext()) {
Instance *child = child_iter->next();
findInstPinsHierMatching(child, pattern, matches);
findPinsHierMatching(child, pattern, matches);
}
delete child_iter;
}
void
Network::findInstPinsHierMatching(const Instance *instance,
const PatternMatch *pattern,
// Return value.
PinSeq &matches) const
{
string inst_name = name(instance);
InstancePinIterator *pin_iter = pinIterator(instance);
while (pin_iter->hasNext()) {
const Pin *pin = pin_iter->next();
const char *port_name = name(port(pin));
string pin_name = inst_name + divider_ + port_name;
if (pattern->match(pin_name.c_str()))
matches.push_back(pin);
}
delete pin_iter;
}
void
Network::findInstPinsMatching(const Instance *instance,
const PatternMatch *pattern,
PinSeq &matches) const
{
if (pattern->hasWildcards()) {
InstancePinIterator *pin_iter = pinIterator(instance);
while (pin_iter->hasNext()) {
const Pin *pin = pin_iter->next();
if (pattern->match(name(pin)))
matches.push_back(pin);
}
delete pin_iter;
}
else {
Pin *pin = findPin(instance, pattern->pattern());
if (pin)
matches.push_back(pin);
}
}
void
Network::location(const Pin *,
// Return values.
double &x,
double &y,
bool &exists) const
{
x = y = 0.0;
exists = false;
}
int
Network::instanceCount(Instance *inst)
{
int count = 1;
InstanceChildIterator *child_iter = childIterator(inst);
while (child_iter->hasNext()) {
Instance *child = child_iter->next();
count += instanceCount(child);
}
delete child_iter;
return count;
}
int
Network::instanceCount()
{
return instanceCount(topInstance());
}
int
Network::pinCount(Instance *inst)
{
int count = 0;
InstancePinIterator *pin_iter = pinIterator(inst);
while (pin_iter->hasNext()) {
pin_iter->next();
count++;
}
delete pin_iter;
InstanceChildIterator *child_iter = childIterator(inst);
while (child_iter->hasNext()) {
Instance *child = child_iter->next();
count += pinCount(child);
}
delete child_iter;
return count;
}
int
Network::pinCount()
{
return pinCount(topInstance());
}
int
Network::netCount(Instance *inst)
{
int count = 0;
InstanceNetIterator *net_iter = netIterator(inst);
while (net_iter->hasNext()) {
net_iter->next();
count++;
}
delete net_iter;
InstanceChildIterator *child_iter = childIterator(inst);
while (child_iter->hasNext()) {
Instance *child = child_iter->next();
count += netCount(child);
}
delete child_iter;
return count;
}
int
Network::netCount()
{
return netCount(topInstance());
}
int
Network::leafInstanceCount()
{
int count = 0;
LeafInstanceIterator *leaf_iter = leafInstanceIterator();
while (leaf_iter->hasNext()) {
leaf_iter->next();
count++;
}
delete leaf_iter;
return count;
}
int
Network::leafPinCount()
{
int count = 0;
LeafInstanceIterator *leaf_iter = leafInstanceIterator();
while (leaf_iter->hasNext()) {
Instance *leaf = leaf_iter->next();
InstancePinIterator *pin_iter = pinIterator(leaf);
while (pin_iter->hasNext()) {
pin_iter->next();
count++;
}
delete pin_iter;
}
delete leaf_iter;
return count;
}
InstanceSeq
Network::leafInstances()
{
InstanceSeq insts;
LeafInstanceIterator *iter = leafInstanceIterator();
while (iter->hasNext()) {
const Instance *inst = iter->next();
insts.push_back(inst);
}
delete iter;
return insts;
}
void
Network::setPathDivider(char divider)
{
divider_ = divider;
}
void
Network::setPathEscape(char escape)
{
escape_ = escape;
}
////////////////////////////////////////////////////////////////
typedef Vector<InstanceChildIterator *> InstanceChildIteratorSeq;
class LeafInstanceIterator1 : public LeafInstanceIterator
{
public:
LeafInstanceIterator1(const Instance *inst,
const Network *network);
bool hasNext() { return next_; }
Instance *next();
private:
void nextInst();
const Network *network_;
InstanceChildIteratorSeq pending_child_iters_;
InstanceChildIterator *child_iter_;
Instance *next_;
};
LeafInstanceIterator1::LeafInstanceIterator1(const Instance *inst,
const Network *network) :
network_(network),
child_iter_(network->childIterator(inst)),
next_(nullptr)
{
pending_child_iters_.reserve(8);
nextInst();
}
Instance *
LeafInstanceIterator1::next()
{
Instance *next = next_;
nextInst();
return next;
}
void
LeafInstanceIterator1::nextInst()
{
next_ = nullptr;
while (child_iter_) {
while (child_iter_->hasNext()) {
next_ = child_iter_->next();
if (network_->isLeaf(next_))
return;
else {
pending_child_iters_.push_back(child_iter_);
child_iter_ = network_->childIterator(next_);
next_ = nullptr;
}
}
delete child_iter_;
if (pending_child_iters_.empty())
child_iter_ = nullptr;
else {
child_iter_ = pending_child_iters_.back();
pending_child_iters_.pop_back();
}
}
}
LeafInstanceIterator *
Network::leafInstanceIterator() const
{
return new LeafInstanceIterator1(topInstance(), this);
}
LeafInstanceIterator *
Network::leafInstanceIterator(const Instance *hier_inst) const
{
return new LeafInstanceIterator1(hier_inst, this);
}
////////////////////////////////////////////////////////////////
void
Network::visitConnectedPins(const Pin *pin,
PinVisitor &visitor) const
{
NetSet visited_nets(network_);
Net *pin_net = net(pin);
Term *pin_term = term(pin);
if (pin_net)
visitConnectedPins(pin_net, visitor, visited_nets);
else if (pin_term == nullptr)
// Unconnected or internal pin.
visitor(pin);
// Search down from pin terminal.
if (pin_term) {
Net *term_net = net(pin_term);
if (term_net)
visitConnectedPins(term_net, visitor, visited_nets);
}
}
void
Network::visitConnectedPins(const Net *net,
PinVisitor &visitor) const
{
NetSet visited_nets(this);
visitConnectedPins(net, visitor, visited_nets);
}
void
Network::visitConnectedPins(const Net *net,
PinVisitor &visitor,
NetSet &visited_nets) const
{
if (!visited_nets.hasKey(net)) {
visited_nets.insert(net);
// Search up from net terminals.
NetTermIterator *term_iter = termIterator(net);
while (term_iter->hasNext()) {
Term *term = term_iter->next();
Pin *above_pin = pin(term);
if (above_pin) {
Net *above_net = this->net(above_pin);
if (above_net)
visitConnectedPins(above_net, visitor, visited_nets);
else
visitor(above_pin);
}
}
delete term_iter;
// Search down from net pins.
NetPinIterator *pin_iter = pinIterator(net);
while (pin_iter->hasNext()) {
const Pin *pin = pin_iter->next();
visitor(pin);
Term *below_term = term(pin);
if (below_term) {
Net *below_net = this->net(below_term);
if (below_net)
visitConnectedPins(below_net, visitor, visited_nets);
}
}
delete pin_iter;
}
}
////////////////////////////////////////////////////////////////
class ConnectedPinIterator1 : public ConnectedPinIterator
{
public:
explicit ConnectedPinIterator1(PinSet *pins);
virtual ~ConnectedPinIterator1();
virtual bool hasNext();
virtual const Pin *next();
protected:
PinSet::Iterator pin_iter_;
};
ConnectedPinIterator1::ConnectedPinIterator1(PinSet *pins) :
pin_iter_(pins)
{
}
ConnectedPinIterator1::~ConnectedPinIterator1()
{
delete pin_iter_.container();
}
bool
ConnectedPinIterator1::hasNext()
{
return pin_iter_.hasNext();
}
const Pin *
ConnectedPinIterator1::next()
{
return pin_iter_.next();
}
class FindConnectedPins : public PinVisitor
{
public:
explicit FindConnectedPins(PinSet *pins);
virtual void operator()(const Pin *pin);
protected:
PinSet *pins_;
};
FindConnectedPins::FindConnectedPins(PinSet *pins) :
PinVisitor(),
pins_(pins)
{
}
void
FindConnectedPins::operator()(const Pin *pin)
{
pins_->insert(pin);
}
NetConnectedPinIterator *
Network::connectedPinIterator(const Net *net) const
{
PinSet *pins = new PinSet(this);
FindConnectedPins visitor(pins);
visitConnectedPins(net, visitor);
return new ConnectedPinIterator1(pins);
}
PinConnectedPinIterator *
Network::connectedPinIterator(const Pin *pin) const
{
PinSet *pins = new PinSet(this);
pins->insert(const_cast<Pin*>(pin));
FindConnectedPins visitor(pins);
Net *pin_net = net(pin);
if (pin_net)
visitConnectedPins(pin_net, visitor);
// Search down from pin terminal.
Term *pin_term = term(pin);
if (pin_term) {
Net *term_net = net(pin_term);
if (term_net)
visitConnectedPins(term_net, visitor);
}
return new ConnectedPinIterator1(pins);
}
////////////////////////////////////////////////////////////////
bool
Network::isConnected(const Net *net,
const Pin *pin) const
{
if (this->net(pin) == net)
return true;
else {
NetSet nets(this);
return isConnected(net, pin, nets);
}
}
bool
Network::isConnected(const Net *net,
const Pin *pin,
NetSet &nets) const
{
if (!nets.hasKey(net)) {
nets.insert(net);
// Search up from net terminals.
NetTermIterator *term_iter = termIterator(net);
while (term_iter->hasNext()) {
Term *term = term_iter->next();
Pin *above_pin = this->pin(term);
if (above_pin) {
if (above_pin == pin) {
delete term_iter;
return true;
}
else {
Net *above_net = this->net(above_pin);
if (above_net && isConnected(above_net, pin, nets)) {
delete term_iter;
return true;
}
}
}
}
delete term_iter;
// Search down from net pins.
NetPinIterator *pin_iter = pinIterator(net);
while (pin_iter->hasNext()) {
const Pin *pin1 = pin_iter->next();
if (pin1 == pin) {
delete pin_iter;
return true;
}
else {
Term *below_term = term(pin1);
if (below_term) {
Net *below_net = this->net(below_term);
if (below_net && isConnected(below_net, pin, nets)) {
delete pin_iter;
return true;
}
}
}
}
delete pin_iter;
}
return false;
}
bool
Network::isConnected(const Net *net1,
const Net *net2) const
{
NetSet nets(this);
return isConnected(net1, net2, nets);
}
bool
Network::isConnected(const Net *net1,
const Net *net2,
NetSet &nets) const
{
if (net1 == net2)
return true;
else if (!nets.hasKey(net1)) {
nets.insert(net1);
// Search up from net terminals.
NetTermIterator *term_iter = termIterator(net1);
while (term_iter->hasNext()) {
Term *term = term_iter->next();
Pin *above_pin = pin(term);
if (above_pin) {
Net *above_net = net(above_pin);
if (above_net && isConnected(above_net, net2, nets)) {
delete term_iter;
return true;
}
}
}
delete term_iter;
// Search down from net pins.
NetPinIterator *pin_iter = pinIterator(net1);
while (pin_iter->hasNext()) {
const Pin *pin1 = pin_iter->next();
Term *below_term = term(pin1);
if (below_term) {
Net *below_net = net(below_term);
if (below_net && isConnected(below_net, net2, nets)) {
delete pin_iter;
return true;
}
}
}
delete pin_iter;
}
return false;
}
////////////////////////////////////////////////////////////////
class FindDrvrPins : public PinVisitor
{
public:
explicit FindDrvrPins(PinSet *pins,
const Network *network);
virtual void operator()(const Pin *pin);
protected:
PinSet *pins_;
const Network *network_;
};
FindDrvrPins::FindDrvrPins(PinSet *pins,
const Network *network) :
PinVisitor(),
pins_(pins),
network_(network)
{
}
void
FindDrvrPins::operator()(const Pin *pin)
{
if (network_->isDriver(pin))
pins_->insert(pin);
}
PinSet *
Network::drivers(const Pin *pin)
{
const Net *net = this->net(pin);
if (net)
return drivers(net);
else
return nullptr;
}
void
Network::clearNetDrvrPinMap()
{
net_drvr_pin_map_.deleteContentsClear();
}
PinSet *
Network::drivers(const Net *net)
{
PinSet *drvrs = net_drvr_pin_map_.findKey(net);
if (drvrs == nullptr) {
drvrs = new PinSet(this);
FindDrvrPins visitor(drvrs, this);
visitConnectedPins(net, visitor);
net_drvr_pin_map_[net] = drvrs;
}
return drvrs;
}
////////////////////////////////////////////////////////////////
void
Network::pathNameFirst(const char *path_name,
char *&first,
char *&tail) const
{
char escape = pathEscape();
char divider = pathDivider();
const char *d = strchr(path_name, divider);
// Skip escaped dividers.
while (d != nullptr
&& d > path_name
&& d[-1] == escape)
d = strchr(d + 1, divider);
if (d) {
first = new char[d - path_name + 1];
strncpy(first, path_name, d - path_name);
first[d - path_name] = '\0';
tail = new char[strlen(d)];
// Chop off the leading divider.
strcpy(tail, d + 1);
}
else {
// No divider in path_name.
first = nullptr;
tail = nullptr;
}
}
void
Network::pathNameLast(const char *path_name,
char *&head,
char *&last) const
{
char escape = pathEscape();
char divider = pathDivider();
const char *d = strrchr(path_name, divider);
// Search for a non-escaped divider.
if (d) {
while (d > path_name
&& (d[0] != divider
|| (d[0] == divider
&& d > &path_name[1]
&& d[-1] == escape)))
d--;
}
if (d && d != path_name) {
head = new char[d - path_name + 1];
strncpy(head, path_name, d - path_name);
head[d - path_name] = '\0';
last = new char[strlen(d)];
// Chop off the last divider.
strcpy(last, d + 1);
}
else {
// No divider in path_name.
head = nullptr;
last = nullptr;
}
}
////////////////////////////////////////////////////////////////
NetworkEdit::NetworkEdit() :
Network()
{
}
void
NetworkEdit::connectPin(Pin *pin,
Net *net)
{
connect(instance(pin), port(pin), net);
}
////////////////////////////////////////////////////////////////
NetworkConstantPinIterator::
NetworkConstantPinIterator(const Network *network,
NetSet &zero_nets,
NetSet &one_nets) :
ConstantPinIterator(),
network_(network),
constant_pins_{PinSet(network), PinSet(network)}
{
findConstantPins(zero_nets, constant_pins_[0]);
findConstantPins(one_nets, constant_pins_[1]);
value_ = LogicValue::zero;
pin_iter_ = new PinSet::Iterator(constant_pins_[0]);
}
NetworkConstantPinIterator::~NetworkConstantPinIterator()
{
delete pin_iter_;
}
void
NetworkConstantPinIterator::findConstantPins(NetSet &nets,
PinSet &pins)
{
NetSet::Iterator net_iter(nets);
while (net_iter.hasNext()) {
const Net *net = net_iter.next();
NetConnectedPinIterator *pin_iter = network_->connectedPinIterator(net);
while (pin_iter->hasNext()) {
const Pin *pin = pin_iter->next();
pins.insert(pin);
}
delete pin_iter;
}
}
bool
NetworkConstantPinIterator::hasNext()
{
if (pin_iter_->hasNext())
return true;
else if (value_ == LogicValue::zero) {
delete pin_iter_;
value_ = LogicValue::one;
pin_iter_ = new PinSet::Iterator(constant_pins_[1]);
return pin_iter_->hasNext();
}
else
return false;
}
void
NetworkConstantPinIterator::next(const Pin *&pin,
LogicValue &value)
{
pin = pin_iter_->next();
value = value_;
}
////////////////////////////////////////////////////////////////
FindNetDrvrLoads::FindNetDrvrLoads(const Pin *drvr_pin,
PinSet &visited_drvrs,
PinSeq &loads,
PinSeq &drvrs,
const Network *network) :
drvr_pin_(drvr_pin),
visited_drvrs_(visited_drvrs),
loads_(loads),
drvrs_(drvrs),
network_(network)
{
}
void
FindNetDrvrLoads::operator()(const Pin *pin)
{
if (network_->isLoad(pin))
loads_.push_back(pin);
if (network_->isDriver(pin)) {
drvrs_.push_back(pin);
if (pin != drvr_pin_)
visited_drvrs_.insert(pin);
}
}
////////////////////////////////////////////////////////////////
static void
visitPinsAboveNet1(const Pin *hpin,
Net *above_net,
NetSet &visited,
PinSet &above_drvrs,
PinSet &above_loads,
const Network *network)
{
visited.insert(above_net);
// Visit above net pins.
NetPinIterator *pin_iter = network->pinIterator(above_net);
while (pin_iter->hasNext()) {
const Pin *above_pin = pin_iter->next();
if (above_pin != hpin) {
if (network->isDriver(above_pin))
above_drvrs.insert(above_pin);
if (network->isLoad(above_pin))
above_loads.insert(above_pin);
Term *above_term = network->term(above_pin);
if (above_term) {
Net *above_net1 = network->net(above_term);
if (above_net1 && !visited.hasKey(above_net1))
visitPinsAboveNet1(above_pin, above_net1, visited,
above_drvrs, above_loads, network);
}
}
}
delete pin_iter;
// Search up from net terminals.
NetTermIterator *term_iter = network->termIterator(above_net);
while (term_iter->hasNext()) {
Term *term = term_iter->next();
Pin *above_pin = network->pin(term);
if (above_pin
&& above_pin != hpin) {
Net *above_net1 = network->net(above_pin);
if (above_net1 && !visited.hasKey(above_net1))
visitPinsAboveNet1(above_pin, above_net1, visited,
above_drvrs, above_loads, network);
if (network->isDriver(above_pin))
above_drvrs.insert(above_pin);
if (network->isLoad(above_pin))
above_loads.insert(above_pin);
}
}
delete term_iter;
}
static void
visitPinsBelowNet1(const Pin *hpin,
Net *below_net,
NetSet &visited,
PinSet &below_drvrs,
PinSet &below_loads,
const Network *network)
{
visited.insert(below_net);
// Visit below net pins.
NetPinIterator *pin_iter = network->pinIterator(below_net);
while (pin_iter->hasNext()) {
const Pin *below_pin = pin_iter->next();
if (below_pin != hpin) {
NetSet visited_above(network);
if (network->isDriver(below_pin))
below_drvrs.insert(below_pin);
if (network->isLoad(below_pin))
below_loads.insert(below_pin);
if (network->isHierarchical(below_pin)) {
Term *term = network->term(below_pin);
if (term) {
Net *below_net1 = network->net(term);
if (below_net1 && !visited.hasKey(below_net1))
visitPinsBelowNet1(below_pin, below_net1, visited,
below_drvrs, below_loads, network);
}
}
}
}
delete pin_iter;
}
static void
visitDrvrLoads(PinSet drvrs,
PinSet loads,
HierPinThruVisitor *visitor)
{
PinSet::Iterator drvr_iter(drvrs);
while (drvr_iter.hasNext()) {
const Pin *drvr = drvr_iter.next();
PinSet::Iterator load_iter(loads);
while (load_iter.hasNext()) {
const Pin *load = load_iter.next();
visitor->visit(drvr, load);
}
}
}
void
visitDrvrLoadsThruHierPin(const Pin *hpin,
const Network *network,
HierPinThruVisitor *visitor)
{
Net *above_net = network->net(hpin);
if (above_net) {
// Search down from hpin terminal.
Term *term = network->term(hpin);
if (term) {
Net *below_net = network->net(term);
if (below_net) {
NetSet visited(network);
PinSet above_drvrs(network);
PinSet above_loads(network);
visitPinsAboveNet1(hpin, above_net, visited,
above_drvrs, above_loads, network);
PinSet below_drvrs(network);
PinSet below_loads(network);
visitPinsBelowNet1(hpin, below_net, visited,
below_drvrs, below_loads, network);
visitDrvrLoads(above_drvrs, below_loads, visitor);
visitDrvrLoads(below_drvrs, above_loads, visitor);
}
}
}
}
void
visitDrvrLoadsThruNet(const Net *net,
const Network *network,
HierPinThruVisitor *visitor)
{
NetSet visited(network);
PinSet above_drvrs(network);
PinSet above_loads(network);
PinSet below_drvrs(network);
PinSet below_loads(network);
PinSet net_drvrs(network);
PinSet net_loads(network);
NetPinIterator *pin_iter = network->pinIterator(net);
while (pin_iter->hasNext()) {
const Pin *pin = pin_iter->next();
if (network->isHierarchical(pin)) {
// Search down from pin terminal.
const Term *term = network->term(pin);
if (term) {
Net *below_net = network->net(term);
if (below_net) {
visitPinsBelowNet1(pin, below_net, visited,
below_drvrs, below_loads, network);
}
}
}
else {
if (network->isDriver(pin))
net_drvrs.insert(pin);
if (network->isLoad(pin))
net_loads.insert(pin);
}
}
delete pin_iter;
NetTermIterator *term_iter = network->termIterator(net);
while (term_iter->hasNext()) {
Term *term = term_iter->next();
Pin *above_pin = network->pin(term);
if (above_pin) {
if (network->isDriver(above_pin))
above_drvrs.insert(above_pin);
if (network->isLoad(above_pin))
above_loads.insert(above_pin);
Net *above_net = network->net(above_pin);
if (above_net)
visitPinsAboveNet1(above_pin, above_net, visited,
above_drvrs, above_loads, network);
}
}
delete term_iter;
visitDrvrLoads(above_drvrs, below_loads, visitor);
visitDrvrLoads(above_drvrs, net_loads, visitor);
visitDrvrLoads(below_drvrs, above_loads, visitor);
visitDrvrLoads(below_drvrs, net_loads, visitor);
visitDrvrLoads(net_drvrs, above_loads, visitor);
visitDrvrLoads(net_drvrs, below_loads, visitor);
visitDrvrLoads(net_drvrs, net_loads, visitor);
}
////////////////////////////////////////////////////////////////
char
logicValueString(LogicValue value)
{
static char str[] = "01X^v";
return str[int(value)];
}
////////////////////////////////////////////////////////////////
CellIdLess::CellIdLess(const Network *network) :
network_(network)
{
}
bool
CellIdLess::operator()(const Cell *cell1,
const Cell *cell2) const
{
return network_->id(cell1) < network_->id(cell2);
}
PortIdLess::PortIdLess(const Network *network) :
network_(network)
{
}
bool
PortIdLess::operator()(const Port *port1,
const Port *port2) const
{
return network_->id(port1) < network_->id(port2);
}
InstanceIdLess::InstanceIdLess(const Network *network) :
network_(network)
{
}
bool
InstanceIdLess::operator()(const Instance *inst1,
const Instance *inst2) const
{
return network_->id(inst1) < network_->id(inst2);
}
PinIdLess::PinIdLess(const Network *network) :
network_(network)
{
}
bool
PinIdLess::operator()(const Pin *pin1,
const Pin *pin2) const
{
return network_->id(pin1) < network_->id(pin2);
}
PinIdHash::PinIdHash(const Network *network) :
network_(network)
{
}
size_t
PinIdHash::operator()(const Pin *pin) const
{
return network_->id(pin);
}
NetIdLess::NetIdLess(const Network *network) :
network_(network)
{
}
bool
NetIdLess::operator()(const Net *net1,
const Net *net2) const
{
return network_->id(net1) < network_->id(net2);
}
////////////////////////////////////////////////////////////////
CellSet::CellSet(const Network *network) :
Set<const Cell*, CellIdLess>(CellIdLess(network))
{
}
PortSet::PortSet(const Network *network) :
Set<const Port*, PortIdLess>(PortIdLess(network))
{
}
InstanceSet::InstanceSet() :
Set<const Instance*, InstanceIdLess>(InstanceIdLess(nullptr))
{
}
InstanceSet::InstanceSet(const Network *network) :
Set<const Instance*, InstanceIdLess>(InstanceIdLess(network))
{
}
int
InstanceSet::compare(const InstanceSet *set1,
const InstanceSet *set2,
const Network *network)
{
size_t size1 = set1 ? set1->size() : 0;
size_t size2 = set2 ? set2->size() : 0;
if (size1 == size2) {
InstanceSet::ConstIterator iter1(set1);
InstanceSet::ConstIterator iter2(set2);
while (iter1.hasNext() && iter2.hasNext()) {
const Instance *inst1 = iter1.next();
const Instance *inst2 = iter2.next();
ObjectId id1 = network->id(inst1);
ObjectId id2 = network->id(inst2);
if (id1 < id2)
return -1;
else if (id1 > id2)
return 1;
}
// Sets are equal.
return 0;
}
else
return (size1 > size2) ? 1 : -1;
}
bool
InstanceSet::intersects(const InstanceSet *set1,
const InstanceSet *set2,
const Network *network)
{
return Set<const Instance*, InstanceIdLess>::intersects(set1, set2, InstanceIdLess(network));
}
////////////////////////////////////////////////////////////////
PinSet::PinSet() :
Set<const Pin*, PinIdLess>(PinIdLess(nullptr))
{
}
PinSet::PinSet(const Network *network) :
Set<const Pin*, PinIdLess>(PinIdLess(network))
{
}
int
PinSet::compare(const PinSet *set1,
const PinSet *set2,
const Network *network)
{
size_t size1 = set1 ? set1->size() : 0;
size_t size2 = set2 ? set2->size() : 0;
if (size1 == size2) {
PinSet::ConstIterator iter1(set1);
PinSet::ConstIterator iter2(set2);
while (iter1.hasNext() && iter2.hasNext()) {
const Pin *pin1 = iter1.next();
const Pin *pin2 = iter2.next();
ObjectId id1 = network->id(pin1);
ObjectId id2 = network->id(pin2);
if (id1 < id2)
return -1;
else if (id1 > id2)
return 1;
}
// Sets are equal.
return 0;
}
else
return (size1 > size2) ? 1 : -1;
}
bool
PinSet::intersects(const PinSet *set1,
const PinSet *set2,
const Network *network)
{
return Set<const Pin*, PinIdLess>::intersects(set1, set2, PinIdLess(network));
}
////////////////////////////////////////////////////////////////
NetSet::NetSet() :
Set<const Net*, NetIdLess>(NetIdLess(nullptr))
{
}
NetSet::NetSet(const Network *network) :
Set<const Net*, NetIdLess>(NetIdLess(network))
{
}
int
NetSet::compare(const NetSet *set1,
const NetSet *set2,
const Network *network)
{
size_t size1 = set1 ? set1->size() : 0;
size_t size2 = set2 ? set2->size() : 0;
if (size1 == size2) {
NetSet::ConstIterator iter1(set1);
NetSet::ConstIterator iter2(set2);
while (iter1.hasNext() && iter2.hasNext()) {
const Net *net1 = iter1.next();
const Net *net2 = iter2.next();
ObjectId id1 = network->id(net1);
ObjectId id2 = network->id(net2);
if (id1 < id2)
return -1;
else if (id1 > id2)
return 1;
}
// Sets are equal.
return 0;
}
else
return (size1 > size2) ? 1 : -1;
}
bool
NetSet::intersects(const NetSet *set1,
const NetSet *set2,
const Network *network)
{
return Set<const Net*, NetIdLess>::intersects(set1, set2, NetIdLess(network));
}
} // namespace